cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vdso_test_abi.c (5415B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * vdso_full_test.c: Sample code to test all the timers.
      4 * Copyright (c) 2019 Arm Ltd.
      5 *
      6 * Compile with:
      7 * gcc -std=gnu99 vdso_full_test.c parse_vdso.c
      8 *
      9 */
     10
     11#include <stdint.h>
     12#include <elf.h>
     13#include <stdio.h>
     14#include <time.h>
     15#include <sys/auxv.h>
     16#include <sys/time.h>
     17#define _GNU_SOURCE
     18#include <unistd.h>
     19#include <sys/syscall.h>
     20
     21#include "../kselftest.h"
     22#include "vdso_config.h"
     23
     24extern void *vdso_sym(const char *version, const char *name);
     25extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
     26extern void vdso_init_from_auxv(void *auxv);
     27
     28static const char *version;
     29static const char **name;
     30
     31typedef long (*vdso_gettimeofday_t)(struct timeval *tv, struct timezone *tz);
     32typedef long (*vdso_clock_gettime_t)(clockid_t clk_id, struct timespec *ts);
     33typedef long (*vdso_clock_getres_t)(clockid_t clk_id, struct timespec *ts);
     34typedef time_t (*vdso_time_t)(time_t *t);
     35
     36#define VDSO_TEST_PASS_MSG()	"\n%s(): PASS\n", __func__
     37#define VDSO_TEST_FAIL_MSG(x)	"\n%s(): %s FAIL\n", __func__, x
     38#define VDSO_TEST_SKIP_MSG(x)	"\n%s(): SKIP: Could not find %s\n", __func__, x
     39
     40static void vdso_test_gettimeofday(void)
     41{
     42	/* Find gettimeofday. */
     43	vdso_gettimeofday_t vdso_gettimeofday =
     44		(vdso_gettimeofday_t)vdso_sym(version, name[0]);
     45
     46	if (!vdso_gettimeofday) {
     47		ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[0]));
     48		return;
     49	}
     50
     51	struct timeval tv;
     52	long ret = vdso_gettimeofday(&tv, 0);
     53
     54	if (ret == 0) {
     55		ksft_print_msg("The time is %lld.%06lld\n",
     56			       (long long)tv.tv_sec, (long long)tv.tv_usec);
     57		ksft_test_result_pass(VDSO_TEST_PASS_MSG());
     58	} else {
     59		ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[0]));
     60	}
     61}
     62
     63static void vdso_test_clock_gettime(clockid_t clk_id)
     64{
     65	/* Find clock_gettime. */
     66	vdso_clock_gettime_t vdso_clock_gettime =
     67		(vdso_clock_gettime_t)vdso_sym(version, name[1]);
     68
     69	if (!vdso_clock_gettime) {
     70		ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[1]));
     71		return;
     72	}
     73
     74	struct timespec ts;
     75	long ret = vdso_clock_gettime(clk_id, &ts);
     76
     77	if (ret == 0) {
     78		ksft_print_msg("The time is %lld.%06lld\n",
     79			       (long long)ts.tv_sec, (long long)ts.tv_nsec);
     80		ksft_test_result_pass(VDSO_TEST_PASS_MSG());
     81	} else {
     82		ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[1]));
     83	}
     84}
     85
     86static void vdso_test_time(void)
     87{
     88	/* Find time. */
     89	vdso_time_t vdso_time =
     90		(vdso_time_t)vdso_sym(version, name[2]);
     91
     92	if (!vdso_time) {
     93		ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[2]));
     94		return;
     95	}
     96
     97	long ret = vdso_time(NULL);
     98
     99	if (ret > 0) {
    100		ksft_print_msg("The time in hours since January 1, 1970 is %lld\n",
    101				(long long)(ret / 3600));
    102		ksft_test_result_pass(VDSO_TEST_PASS_MSG());
    103	} else {
    104		ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[2]));
    105	}
    106}
    107
    108static void vdso_test_clock_getres(clockid_t clk_id)
    109{
    110	int clock_getres_fail = 0;
    111
    112	/* Find clock_getres. */
    113	vdso_clock_getres_t vdso_clock_getres =
    114		(vdso_clock_getres_t)vdso_sym(version, name[3]);
    115
    116	if (!vdso_clock_getres) {
    117		ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[3]));
    118		return;
    119	}
    120
    121	struct timespec ts, sys_ts;
    122	long ret = vdso_clock_getres(clk_id, &ts);
    123
    124	if (ret == 0) {
    125		ksft_print_msg("The vdso resolution is %lld %lld\n",
    126			       (long long)ts.tv_sec, (long long)ts.tv_nsec);
    127	} else {
    128		clock_getres_fail++;
    129	}
    130
    131	ret = syscall(SYS_clock_getres, clk_id, &sys_ts);
    132
    133	ksft_print_msg("The syscall resolution is %lld %lld\n",
    134			(long long)sys_ts.tv_sec, (long long)sys_ts.tv_nsec);
    135
    136	if ((sys_ts.tv_sec != ts.tv_sec) || (sys_ts.tv_nsec != ts.tv_nsec))
    137		clock_getres_fail++;
    138
    139	if (clock_getres_fail > 0) {
    140		ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[3]));
    141	} else {
    142		ksft_test_result_pass(VDSO_TEST_PASS_MSG());
    143	}
    144}
    145
    146const char *vdso_clock_name[12] = {
    147	"CLOCK_REALTIME",
    148	"CLOCK_MONOTONIC",
    149	"CLOCK_PROCESS_CPUTIME_ID",
    150	"CLOCK_THREAD_CPUTIME_ID",
    151	"CLOCK_MONOTONIC_RAW",
    152	"CLOCK_REALTIME_COARSE",
    153	"CLOCK_MONOTONIC_COARSE",
    154	"CLOCK_BOOTTIME",
    155	"CLOCK_REALTIME_ALARM",
    156	"CLOCK_BOOTTIME_ALARM",
    157	"CLOCK_SGI_CYCLE",
    158	"CLOCK_TAI",
    159};
    160
    161/*
    162 * This function calls vdso_test_clock_gettime and vdso_test_clock_getres
    163 * with different values for clock_id.
    164 */
    165static inline void vdso_test_clock(clockid_t clock_id)
    166{
    167	ksft_print_msg("\nclock_id: %s\n", vdso_clock_name[clock_id]);
    168
    169	vdso_test_clock_gettime(clock_id);
    170
    171	vdso_test_clock_getres(clock_id);
    172}
    173
    174#define VDSO_TEST_PLAN	16
    175
    176int main(int argc, char **argv)
    177{
    178	unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
    179
    180	ksft_print_header();
    181	ksft_set_plan(VDSO_TEST_PLAN);
    182
    183	if (!sysinfo_ehdr) {
    184		printf("AT_SYSINFO_EHDR is not present!\n");
    185		return KSFT_SKIP;
    186	}
    187
    188	version = versions[VDSO_VERSION];
    189	name = (const char **)&names[VDSO_NAMES];
    190
    191	printf("[vDSO kselftest] VDSO_VERSION: %s\n", version);
    192
    193	vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
    194
    195	vdso_test_gettimeofday();
    196
    197#if _POSIX_TIMERS > 0
    198
    199#ifdef CLOCK_REALTIME
    200	vdso_test_clock(CLOCK_REALTIME);
    201#endif
    202
    203#ifdef CLOCK_BOOTTIME
    204	vdso_test_clock(CLOCK_BOOTTIME);
    205#endif
    206
    207#ifdef CLOCK_TAI
    208	vdso_test_clock(CLOCK_TAI);
    209#endif
    210
    211#ifdef CLOCK_REALTIME_COARSE
    212	vdso_test_clock(CLOCK_REALTIME_COARSE);
    213#endif
    214
    215#ifdef CLOCK_MONOTONIC
    216	vdso_test_clock(CLOCK_MONOTONIC);
    217#endif
    218
    219#ifdef CLOCK_MONOTONIC_RAW
    220	vdso_test_clock(CLOCK_MONOTONIC_RAW);
    221#endif
    222
    223#ifdef CLOCK_MONOTONIC_COARSE
    224	vdso_test_clock(CLOCK_MONOTONIC_COARSE);
    225#endif
    226
    227#endif
    228
    229	vdso_test_time();
    230
    231	ksft_print_cnts();
    232	return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
    233}