Commit 683d6923 authored by Vincenzo Frascino's avatar Vincenzo Frascino
Browse files

selftests: Add per cpu vdso test



Add per cpu vdso test.
Signed-off-by: Vincenzo Frascino's avatarVincenzo Frascino <vincenzo.frascino@arm.com>
parent c3e93692
#!/usr/bin/env bash
aarch64-none-linux-gnu-gcc parse_vdso.c vdso_test_syscalls.c -o cvdso_test_syscalls -lpthread &&
aarch64-none-linux-gnu-gcc parse_vdso.c vdso_test_syscalls.c -o cvdso_test_syscalls_testing -lpthread -D__VDSO_TESTING__ &&
sudo mv cvdso_test_syscalls* /data0/nfs/ubuntu-aarch64-rootfs/mt_env/
// SPDX-License-Identifier: GPL-2.0-only
/*
* vdso_test_getcpu.c: Sample code to test parse_vdso.c and vDSO getcpu()
*
* Copyright (c) 2020 Arm Ltd
*/
#include <stdint.h>
#include <elf.h>
#include <stdio.h>
#include <sys/auxv.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <pthread.h>
#include <unistd.h>
#include "../kselftest.h"
#include "parse_vdso.h"
#if defined(__aarch64__)
const char *version = "LINUX_2.6.39";
const char *name[] = {
"__kernel_getcpu",
"__kernel_getpid",
"__kernel_gettid",
"__kernel_getuid",
"__kernel_geteuid",
"__kernel_getgid",
"__kernel_getegid",
"__kernel_getppid",
};
#else
const char *version = "LINUX_2.6";
const char *name[] = {
"__vdso_getcpu",
"__vdso_getpid",
"__vdso_gettid",
"__vdso_getuid",
"__vdso_geteuid",
"__vdso_getgid",
"__vdso_getegid",
"__vdso_getppid",
};
#endif
struct getcpu_cache;
typedef long (*getcpu_t)(unsigned int *, unsigned int *,
struct getcpu_cache *);
typedef int (*getpid_t)(void);
typedef int (*gettid_t)(void);
typedef int (*getuid_t)(void);
typedef int (*geteuid_t)(void);
typedef int (*getgid_t)(void);
typedef int (*getegid_t)(void);
typedef int (*getppid_t)(void);
getcpu_t get_cpu;
getpid_t get_pid;
gettid_t get_tid;
getuid_t get_uid;
geteuid_t get_euid;
getgid_t get_gid;
getegid_t get_egid;
getppid_t get_ppid;
int i;
int passed_tests;
void exec_syscalls(int id)
{
#ifdef __VDSO_TESTING__
unsigned int cpu, node;
int ret0;
ret0 = syscall(SYS_getcpu, &cpu, &node, 0);
printf("[SYSC] Running thread %d on CPU %lu NODE %lu PID %lu TID %lu UID %lu EUID %lu GID %lu EGID %lu PPID %lu\n",
i, cpu, node,
syscall(SYS_getpid),
syscall(SYS_gettid),
syscall(SYS_getuid),
syscall(SYS_geteuid),
syscall(SYS_getgid),
syscall(SYS_getegid),
syscall(SYS_getppid));
#endif
}
void verify_vdso_syscalls(int id)
{
#ifdef __VDSO_TESTING__
unsigned int cpu, node, _cpu, _node;
int ret0;
int i = 0;
ret0 = get_cpu(&cpu, &node, 0);
ret0 = syscall(SYS_getcpu, &_cpu, &_node, 0);
if ((cpu != _cpu) || (node != _node)) {
i = 0;
goto out;
}
if (syscall(SYS_getpid) != get_pid()) {
i = 1;
goto out;
}
if (syscall(SYS_gettid) != get_tid()) {
i = 2;
goto out;
}
if (syscall(SYS_getuid) != get_uid()) {
i = 3;
goto out;
}
if (syscall(SYS_geteuid) != get_euid()) {
i = 4;
goto out;
}
if (syscall(SYS_getgid) != get_gid()) {
i = 5;
goto out;
}
if (syscall(SYS_getegid) != get_egid()) {
i = 6;
goto out;
}
if (syscall(SYS_getppid) != get_ppid()) {
i = 7;
goto out;
}
printf("[TEST] %d: PASSED\n", id);
passed_tests++;
return;
out:
printf("[TEST] %d: FAILED on %s\n", id, name[i]);
#endif
}
void *read_tid(void *x)
{
unsigned int cpu, node;
int ret0;
i++;
exec_syscalls(i);
ret0 = get_cpu(&cpu, &node, 0);
printf("[VDSO] Running thread %d on CPU %d NODE %d PID %d TID %d UID %u EUID %u GID %u EGID %u PPID %u\n",
i, cpu, node,
get_pid(), get_tid(), get_uid(), get_euid(),
get_gid(), get_egid(), get_ppid());
verify_vdso_syscalls(i);
return NULL;
}
#define MAX_THREADS 1024
int main(int argc, char **argv)
{
unsigned long sysinfo_ehdr;
unsigned int cpu, node;
int i;
long ret;
int ret0;
pthread_t thread[MAX_THREADS];
sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
if (!sysinfo_ehdr) {
printf("AT_SYSINFO_EHDR is not present!\n");
return KSFT_SKIP;
}
vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
get_cpu = (getcpu_t)vdso_sym(version, name[0]);
if (!get_cpu) {
printf("Could not find %s\n", name[0]);
return KSFT_SKIP;
}
get_pid = (getpid_t)vdso_sym(version, name[1]);
if (!get_pid) {
printf("Could not find %s\n", name[1]);
return KSFT_SKIP;
}
get_tid = (gettid_t)vdso_sym(version, name[2]);
if (!get_tid) {
printf("Could not find %s\n", name[2]);
return KSFT_SKIP;
}
get_uid = (getuid_t)vdso_sym(version, name[3]);
if (!get_uid) {
printf("Could not find %s\n", name[3]);
return KSFT_SKIP;
}
get_euid = (geteuid_t)vdso_sym(version, name[4]);
if (!get_euid) {
printf("Could not find %s\n", name[4]);
return KSFT_SKIP;
}
get_gid = (getgid_t)vdso_sym(version, name[5]);
if (!get_gid) {
printf("Could not find %s\n", name[5]);
return KSFT_SKIP;
}
get_egid = (getegid_t)vdso_sym(version, name[6]);
if (!get_egid) {
printf("Could not find %s\n", name[6]);
return KSFT_SKIP;
}
get_ppid = (getppid_t)vdso_sym(version, name[7]);
if (!get_ppid) {
printf("Could not find %s\n", name[7]);
return KSFT_SKIP;
}
for (i = 0; i < MAX_THREADS; i++)
pthread_create(&thread[i], NULL, read_tid, NULL);
exec_syscalls(0);
printf("[VDSO] Running thread 0 PID %d TID %d UID %u EUID %u GID %u EGID %u PPID %u\n",
get_pid(), get_tid(), get_uid(), get_euid(), get_gid(), get_egid(), get_ppid());
verify_vdso_syscalls(i);
for (i = 0; i < MAX_THREADS; i++)
pthread_join(thread[i], NULL);
#ifdef __VDSO_TESTING__
if (passed_tests == (MAX_THREADS + 1))
printf("[VDSO SYSCALL TEST] PASSED\n");
else
printf("[VDSO SYSCALL TEST] FAILED\n");
#endif
return 0;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment