On Thu, Jul 09, 2020 at 10:35:46AM +0200, Mark Kettenis wrote:
> 
> Here is the arm64 version.  Again I've taken the approach of copying
> the kernel timecounter code verbatim.  Technically we don't need the
> Cortex-A73 errata workaround here since the timecounter only uses the
> low 32 bits.  But that is true for the kernel as well!  If people
> think it is worth avoiding this, I'd propose to introduce
> agtimer_readcnt32() and use that for the timecounter in both the
> kernel and userland.

I think keeping it simple in userspace is preferable.  We only want the
lower 32 bits, so let's only work with those bits.

While discussing the powerpc usertc code Theo pointed out to me
(again) that you can get a context switch at any moment in userspace.
Multiple reads may yield results from multiple cores.

Said another way...

> @@ -18,4 +18,39 @@
>  #include <sys/types.h>
>  #include <sys/timetc.h>
>  
> -int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> +static inline uint64_t
> +agtimer_readcnt64(void)
> +{
> +     uint64_t val0, val1;
> +
> +     /*
> +      * Work around Cortex-A73 errata 858921, where there is a
> +      * one-cycle window where the read might return the old value
> +      * for the low 32 bits and the new value for the high 32 bits
> +      * upon roll-over of the low 32 bits.
> +      */
> +     __asm volatile("isb" : : : "memory");
> +     __asm volatile("mrs %x0, CNTVCT_EL0" : "=r" (val0));

Hypothetically, what might happen if you were switched *here*?
Between these two instructions?

> +     __asm volatile("mrs %x0, CNTVCT_EL0" : "=r" (val1));
> +     return ((val0 ^ val1) & 0x100000000ULL) ? val0 : val1;
> +}

Reply via email to