Page MenuHomeFreeBSD

[PowerPC] Implement VDSO timebase access
ClosedPublic

Authored by bdragon on Sep 7 2020, 1:01 AM.
Referenced Files
Unknown Object (File)
Fri, Mar 22, 1:56 AM
Unknown Object (File)
Mar 16 2024, 1:24 PM
Unknown Object (File)
Feb 15 2024, 2:02 AM
Unknown Object (File)
Jan 31 2024, 10:11 AM
Unknown Object (File)
Dec 19 2023, 2:10 AM
Unknown Object (File)
Dec 3 2023, 2:48 PM
Unknown Object (File)
Dec 3 2023, 2:48 PM
Unknown Object (File)
Dec 3 2023, 2:48 PM
Subscribers

Details

Summary

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).

Test Plan

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

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

bdragon edited the summary of this revision. (Show Details)

Final version.

This revision was not accepted when it landed; it landed in state Needs Review.Sep 8 2020, 3:00 AM
This revision was automatically updated to reflect the committed changes.