PATCH: get_cyclecount() on ARMv6 and better

Aleksandr Rybalko ray at freebsd.org
Sat Aug 3 11:51:48 UTC 2013


On Sat, 3 Aug 2013 10:24:40 +0100
Mark R V Murray <mark at grondar.org> wrote:

> Hi folks
> 
> The CSPRNG used to drive /dev/random is Yarrow, and it needs good
> timing jitter to produce decent numbers.
> 
> The i86_32 and i86_64 platforms both have the TSC register, wrapped
> in the get_cyclecount() inline function, but the ARM platform doesn't
> use its equivalent, the CCNT register. The alternative, using system
> time, loses LOTS of low-bit jitter, and is certainly worth improving
> upon.
> 
> I'm at the early stages of testing the patch below (I only have RPi),
> and would like to get some comments and reviews, please. I am very
> doubtful indeed that I got the #ifdefs right - they are a bit of a
> minefield! ;-)
> 
> The patch  returns the 32-bit CCNT register as the 64-bit quantity
> that get_cyclecount() provides on all platforms; this is a very minor
> problem, but I suppose I could figure out some kind of crude carry
> mechanism and force the number to increment beyond 32 bits; I doubt
> its worth it though, as its the low bits that provide the jitter.
> 
> Thanks in advance!
> 
> M
> -- 
> Mark R V Murray
> 
> Index: cpu.h
> ===================================================================
> --- cpu.h	(revision 253832)
> +++ cpu.h	(working copy)
> @@ -5,6 +5,9 @@
>  #define MACHINE_CPU_H
>  
>  #include <machine/armreg.h>
> +#ifndef _KERNEL
> +#include <machine/sysarch.h>
> +#endif
>  
>  void	cpu_halt(void);
>  void	swi_vm(void *);
> @@ -13,11 +16,26 @@
>  static __inline uint64_t
>  get_cyclecount(void)
>  {
> +#if defined (__ARM_ARCH_7__) || \
> +	defined (__ARM_ARCH_7A__)  || \
> +	defined (__ARM_ARCH_6__)   || \
> +	defined (__ARM_ARCH_6J__)  || \
> +	defined (__ARM_ARCH_6K__)  || \
> +	defined (__ARM_ARCH_6T2__) || \
> +	defined (__ARM_ARCH_6Z__)  || \
> +	defined (__ARM_ARCH_6ZK__)
> +
> +	uint32_t ccnt;
> +
> +	/* Read CCNT. Darn; its only 32 bits. */
> +	__asm __volatile("mrc p15, 0, %0, c9, c13, 0": "=r" (ccnt));
> +	return ((uint64_t)ccnt);
> +#else
>  	struct bintime bt;
>  
>  	binuptime(&bt);
>  	return ((uint64_t)bt.sec << 56 | bt.frac >> 8);
> -			
> +#endif
>  }
>  #endif
> 
> 
Hi Mark!

Do we setup Performance Monitor Control Register before use that
counter?

WBW
-- 
Aleksandr Rybalko <ray at freebsd.org>


More information about the freebsd-arm mailing list