FreeBSD Bugzilla – Attachment 195062 Details for
Bug 229644
PINE64+ 12.0-CURRENT #0 r336112 - time management problem
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Yet another try at fixing the event timer 2^32 glitch.
a64unstable_generic_timer_take3.diff (text/plain), 2.89 KB, created by
Ian Lepore
on 2018-07-11 20:08:52 UTC
(
hide
)
Description:
Yet another try at fixing the event timer 2^32 glitch.
Filename:
MIME Type:
Creator:
Ian Lepore
Created:
2018-07-11 20:08:52 UTC
Size:
2.89 KB
patch
obsolete
>Index: sys/arm/arm/generic_timer.c >=================================================================== >--- sys/arm/arm/generic_timer.c (revision 336112) >+++ sys/arm/arm/generic_timer.c (working copy) >@@ -145,8 +145,8 @@ get_freq(void) > static uint64_t > get_cntxct_a64_unstable(bool physical) > { >- uint64_t val >-; >+ uint64_t val; >+ > isb(); > if (physical) { > do { >@@ -204,6 +204,16 @@ set_tval(uint32_t val, bool physical) > return (0); > } > >+static void >+set_cval(uint64_t val, bool physical) >+{ >+ >+ if (physical) >+ set_el0(cntp_cval, val); >+ else >+ set_el0(cntv_cval, val); >+} >+ > static int > get_ctrl(bool physical) > { >@@ -275,6 +285,41 @@ arm_tmr_start(struct eventtimer *et, sbintime_t fi > > } > >+static int >+arm_tmr_start_a64_unstable(struct eventtimer *et, sbintime_t first, >+ sbintime_t period __unused) >+{ >+ struct arm_tmr_softc *sc; >+ uint32_t ctrl; >+ uint64_t cntreg, counts; >+ >+ sc = (struct arm_tmr_softc *)et->et_priv; >+ >+ if (first == 0) >+ return (EINVAL); >+ >+ /* >+ * The hardware apparently suffers internally from the same bug software >+ * sees when reading the count register: during a rollover the read >+ * returns an indeterminate value for the low 11 bits (all-zeroes or >+ * all-ones). A write to the tval register is handled internally by >+ * reading the count register, adding the tval, and storing the result >+ * to the compare register; the rollover glitch can result in the >+ * compare register being set almost 2^32 ticks too far into the future. >+ * The Allwinner workaround in their linux BSP is to set tval, then >+ * calculate what cval should be, read cval back, and see if the >+ * hardware calculated it wrong. If we're going to do the math >+ * ourselves, we might as well just set cval directly ourselves. >+ */ >+ ctrl = (get_ctrl(sc->physical) & ~GT_CTRL_INT_MASK) | GT_CTRL_ENABLE; >+ counts = ((uint32_t)et->et_frequency * first) >> 32; >+ cntreg = get_cntxct_a64_unstable(sc->physical); >+ set_cval(cntreg + counts, sc->physical); >+ set_ctrl(ctrl, sc->physical); >+ >+ return (0); >+} >+ > static void > arm_tmr_disable(bool physical) > { >@@ -397,7 +442,9 @@ arm_tmr_attach(device_t dev) > #endif > int error; > int i; >+ bool a64_unstable; > >+ a64_unstable = false; > sc = device_get_softc(dev); > if (arm_tmr_sc) > return (ENXIO); >@@ -413,6 +460,7 @@ arm_tmr_attach(device_t dev) > sc->clkfreq = clock; > > if (OF_hasprop(node, "allwinner,sun50i-a64-unstable-timer")) { >+ a64_unstable = true; > sc->get_cntxct = &get_cntxct_a64_unstable; > if (bootverbose) > device_printf(dev, >@@ -475,7 +523,7 @@ arm_tmr_attach(device_t dev) > sc->et.et_frequency = sc->clkfreq; > sc->et.et_min_period = (0x00000010LLU << 32) / sc->et.et_frequency; > sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; >- sc->et.et_start = arm_tmr_start; >+ sc->et.et_start = (a64_unstable) ? arm_tmr_start_a64_unstable : arm_tmr_start; > sc->et.et_stop = arm_tmr_stop; > sc->et.et_priv = sc; > et_register(&sc->et);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 229644
:
195014
|
195033
| 195062 |
196420