Implement the remaining pieces needed to allow userland clocks via VDSO to work.
Based on a patch from jhibbits.
Tested on ppc64 (POWER9 Talos II), powerpcspe (e500v2 RB800), and powerpc (g4 PowerBook).
Differential D26347
[PowerPC] Implement VDSO timebase access bdragon on Sep 7 2020, 1:01 AM. Authored by Tags Referenced Files
Details
Implement the remaining pieces needed to allow userland clocks via VDSO to work. Based on a patch from jhibbits. Tested on ppc64 (POWER9 Talos II), powerpcspe (e500v2 RB800), and powerpc (g4 PowerBook). Here's a quick test program I wrote that reaches into libc internals to directly exercise both methods of getting a timestamp: /* * Demonstration of FreeBSD vdso gettimeofday(). * MUST be compiled static due to abuse of binding to weak symbols. * * cc -static -o gettimeofday_vdso gettimeofday_vdso.c */ #include <sys/time.h> #include <time.h> #include <stdio.h> #include <string.h> #include <sys/vdso.h> extern int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz); extern int __sys_gettimeofday(struct timeval *tv, struct timezone *tz); int main(int argc, char *argv[]) { struct timeval tv[5]; int i, j, err; for (i = 0; i < 10; i++) { for (j = 0; j < 4; j++) { err = __vdso_gettimeofday(&tv[j], 0); } for (j = 0; j < 4; j++) { if (err) printf("VDSO call failed. %s\n", strerror(err)); else printf("VDSO: %ju.%ju\n", (uintmax_t)tv[j].tv_sec, (uintmax_t)tv[j].tv_usec); } for (j = 0; j < 4; j++) { err = __sys_gettimeofday(&tv[j], 0); } for (j = 0; j < 4; j++) { if (err) printf("Fallback call failed. (?) %s\n", strerror(err)); else printf("SYSCALL: %ju.%ju\n", (uintmax_t)tv[j].tv_sec, (uintmax_t)tv[j].tv_usec); } } return (0); } And here is a test program I wrote to dump the timekeeping information on the VDSO page. /* * Test program to decode the portable parts of the timekeeping structure * on the shared page on FreeBSD. */ #include <sys/types.h> #include <sys/elf.h> #include <sys/auxv.h> #include <stdio.h> #include <sys/time.h> #include <sys/vdso.h> /* See sys/sys/vdso.h */ #define VDSO_TH_NUM 4 int main(int argc, char *argv[]) { struct vdso_timekeep *tk; int i; if (elf_aux_info(AT_TIMEKEEP, &tk, sizeof(tk))) { printf("No AT_TIMEKEEP?\n"); } printf("Version: %d Enabled: %d Current: %d\n", tk->tk_ver, tk->tk_enabled, tk->tk_current); for (i = 0; i < VDSO_TH_NUM; i++) { printf("th %u algo %u gen %u scale 0x%jx offset_count %u counter_mask 0x%x offset %ju.%ju boottime %ju.%ju\n", i, tk->tk_th[i].th_algo, tk->tk_th[i].th_gen, (uintmax_t)tk->tk_th[i].th_scale, tk->tk_th[i].th_offset_count, tk->tk_th[i].th_counter_mask, (uintmax_t)tk->tk_th[i].th_offset.sec, (uintmax_t)tk->tk_th[i].th_offset.frac, (uintmax_t)tk->tk_th[i].th_boottime.sec, (uintmax_t)tk->tk_th[i].th_boottime.frac); } return (0); }
Diff Detail
|