Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145710588
D48580.id150453.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D48580.id150453.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D48580: arm64: use FEAT_WFxT for DELAY() when available
Attached
Detach File
Event Timeline
Log In to Comment