Page MenuHomeFreeBSD

D48580.id150453.diff
No OneTemporary

D48580.id150453.diff

diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c
--- a/sys/arm/arm/generic_timer.c
+++ b/sys/arm/arm/generic_timer.c
@@ -60,6 +60,8 @@
#if defined(__aarch64__)
#include <machine/undefined.h>
+#include <machine/cpufunc.h>
+#include <machine/cpu_feat.h>
#endif
#ifdef FDT
@@ -94,6 +96,10 @@
#define GT_CNTKCTL_PL0VCTEN (1 << 1) /* PL0 CNTVCT and CNTFRQ access */
#define GT_CNTKCTL_PL0PCTEN (1 << 0) /* PL0 CNTPCT and CNTFRQ access */
+#if defined(__aarch64__)
+static bool __read_mostly enable_wfxt = false;
+#endif
+
struct arm_tmr_softc;
struct arm_tmr_irq {
@@ -805,12 +811,10 @@
BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
#endif
-static void
-arm_tmr_do_delay(int usec, void *arg)
+static int64_t
+arm_tmr_get_counts(int usec)
{
- struct arm_tmr_softc *sc = arg;
- int32_t counts, counts_per_usec;
- uint32_t first, last;
+ int64_t counts, counts_per_usec;
/* Get the number of times to count */
counts_per_usec = ((arm_tmr_timecount.tc_frequency / 1000000) + 1);
@@ -826,12 +830,30 @@
else
counts = usec * counts_per_usec;
+ return counts;
+}
+
+static void
+arm_tmr_do_delay(int usec, void *arg)
+{
+ struct arm_tmr_softc *sc = arg;
+ int64_t counts;
+ uint64_t first;
+#if defined(__aarch64__)
+ int64_t end;
+#endif
+
+ counts = arm_tmr_get_counts(usec);
first = sc->get_cntxct(sc->physical_sys);
+#if defined(__aarch64__)
+ end = first + counts;
+#endif
- while (counts > 0) {
- last = sc->get_cntxct(sc->physical_sys);
- counts -= (int32_t)(last - first);
- first = last;
+ while ((sc->get_cntxct(sc->physical_sys) - first) < counts) {
+#if defined(__aarch64__)
+ if (enable_wfxt)
+ wfet(end);
+#endif
}
}
@@ -843,21 +865,47 @@
TSENTER();
/*
- * Check the timers are setup, if not just
- * use a for loop for the meantime
- */
- if (arm_tmr_sc == NULL) {
+ * We have two options for a delay: using the timer, or using the wfet
+ * instruction. However, both of these are dependent on timers being
+ * setup, and if they're not just use a loop for the meantime.
+ */
+ if (arm_tmr_sc != NULL) {
+ arm_tmr_do_delay(usec, arm_tmr_sc);
+ } else {
for (; usec > 0; usec--)
for (counts = 200; counts > 0; counts--)
- /*
- * Prevent the compiler from optimizing
- * out the loop
- */
+ /* Prevent the compiler from optimizing out the loop */
cpufunc_nullop();
- } else
- arm_tmr_do_delay(usec, arm_tmr_sc);
+ }
TSEXIT();
}
+
+static bool
+wfxt_check(const struct cpu_feat *feat __unused, u_int midr __unused)
+{
+ uint64_t id_aa64isar2;
+
+ if (!get_kernel_reg(ID_AA64ISAR2_EL1, &id_aa64isar2))
+ return (false);
+ return (ID_AA64ISAR2_WFxT_VAL(id_aa64isar2) != ID_AA64ISAR2_WFxT_NONE);
+}
+
+static void
+wfxt_enable(const struct cpu_feat *feat __unused,
+ cpu_feat_errata errata_status __unused, u_int *errata_list __unused,
+ u_int errata_count __unused)
+{
+ /* will be called if wfxt_check returns true */
+ enable_wfxt = true;
+}
+
+static struct cpu_feat feat_wfxt = {
+ .feat_name = "FEAT_WFXT",
+ .feat_check = wfxt_check,
+ .feat_enable = wfxt_enable,
+ .feat_flags = CPU_FEAT_AFTER_DEV | CPU_FEAT_SYSTEM,
+};
+DATA_SET(cpu_feat_set, feat_wfxt);
#endif
static uint32_t

File Metadata

Mime Type
text/plain
Expires
Tue, Feb 24, 11:28 AM (18 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28969214
Default Alt Text
D48580.id150453.diff (3 KB)

Event Timeline