> -----Original Message----- > From: Jason A. Donenfeld <Jason@xxxxxxxxx> > Sent: 05 May 2022 12:36 > To: David Laight <David.Laight@xxxxxxxxxx> > Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>; Peter Zijlstra <peterz@xxxxxxxxxxxxx>; Borislav Petkov > <bp@xxxxxxxxx>; LKML <linux-kernel@xxxxxxxxxxxxxxx>; x86@xxxxxxxxxx; Filipe Manana > <fdmanana@xxxxxxxx>; linux-crypto@xxxxxxxxxxxxxxx > Subject: Re: [patch 3/3] x86/fpu: Make FPU protection more robust > > On Thu, May 5, 2022 at 1:34 PM David Laight <David.Laight@xxxxxxxxxx> wrote: > > > > ... > > > + cycles_t end, start = get_cycles(); > > > blake2s_update(&input_pool.hash, in, nbytes); > > > + end = get_cycles(); > > > > If get_cycles() is rdtsc then that gives meaningless numbers. > > The cpu clock frequency will change on you. > > > > You can use one of the performance counters to get an actual > > Indeed. In the process of wiring up rdpmc now. I've used this before now. But the loop getting the pmc value in non-deterministic. So I sometimes remove it. Also you need to add a serialising instruction - otherwise the pmc get read before the code you are measuring actually finishes. I've used similar code to measure iterations on the ip checksum code. Can show how many bytes/clock that achieves in its inner loop. Which can match what you might expect the instructions to generate. David static inline unsigned int rdpmc(unsigned int counter) { unsigned int low, high; asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter)); // return low bits, counter might to 32 or 40 bits wide. return low; } static inline unsigned int rdtsc(void) { unsigned int low, high; asm volatile("rdtsc" : "=a" (low), "=d" (high)); return low; } unsigned int read_cpu_cycles(void) { static struct perf_event_attr perf_attr = { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES, .pinned = 1, }; static __thread struct perf_event_mmap_page *pc; static int pmc_failed; unsigned int seq, idx, count; if (pmc_failed) return rdtsc(); if (!pc) { int perf_fd; perf_fd = syscall(__NR_perf_event_open, &perf_attr, 0, -1, -1, 0); if (perf_fd < 0) { pmc_failed = 1; return rdtsc(); } pc = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ, MAP_SHARED, perf_fd, 0); close(perf_fd); if (pc == MAP_FAILED) { pmc_failed = 1; return rdtsc(); } } do { seq = pc->lock; asm volatile("":::"memory"); idx = pc->index; if (!idx) // || !pc->cap_user_rdpmc) return 0; count = pc->offset + rdpmc(idx - 1); asm volatile("":::"memory"); } while (pc->lock != seq); return count; } - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)