The self test checks APIs defined in arch/x86/include/uapi/asm/ lib_direct_store.h and arch/x86/include/uapi/asm/lib_user_wait.h
Limited by testing environment, this test suit only tests simple cases. More test cases may be added later. Signed-off-by: Fenghua Yu <fenghua...@intel.com> --- tools/testing/selftests/x86/Makefile | 5 +- tools/testing/selftests/x86/directstore_umwait.c | 202 +++++++++++++++++++++++ 2 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/x86/directstore_umwait.c diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 186520198de7..36cf86f3eeae 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -12,7 +12,8 @@ CAN_BUILD_WITH_NOPIE := $(shell ./check_cc.sh $(CC) trivial_program.c -no-pie) TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \ check_initial_reg_state sigreturn iopl mpx-mini-test ioperm \ - protection_keys test_vdso test_vsyscall mov_ss_trap + protection_keys test_vdso test_vsyscall mov_ss_trap \ + directstore_umwait TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ vdso_restorer @@ -73,7 +74,7 @@ $(BINARIES_32): $(OUTPUT)/%_32: %.c $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm $(BINARIES_64): $(OUTPUT)/%_64: %.c - $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl + $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm # x86_64 users should be encouraged to install 32-bit libraries ifeq ($(CAN_BUILD_I386)$(CAN_BUILD_X86_64),01) diff --git a/tools/testing/selftests/x86/directstore_umwait.c b/tools/testing/selftests/x86/directstore_umwait.c new file mode 100644 index 000000000000..d1bb1293d2ad --- /dev/null +++ b/tools/testing/selftests/x86/directstore_umwait.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * directstore_umwait.c - Test APIs defined in lib_direct_store.h and + * lib_user_wait.h + * + * Copyright (c) 2018 Intel Corporation + * Fenghua Yu <fenghua...@intel.com> + */ +#define _GNU_SOURCE + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <unistd.h> +#include <string.h> +#include <asm/lib_direct_store.h> +#include <asm/lib_user_wait.h> + +void test_movdiri_32_bit(void) +{ + int __attribute((aligned(64))) dst[10]; + int __attribute((aligned(64))) data; + + if (!movdiri_supported()) { + printf("movdiri is not supported\n"); + + return; + } + dst[0] = 0; + data = 0x12345670; + + movdiri32(dst, data); + + if (dst[0] == data) + printf("movdiri 32-bit test passed\n"); + else + printf("movdiri 32-bit test failed\n"); +} + +void test_movdiri_64_bit(void) +{ + long __attribute((aligned(64))) dst[10]; + long __attribute((aligned(64))) data; + + if (!movdiri_supported()) { + printf("movdiri is not supported\n"); + + return; + } + dst[0] = 0; + data = 0x123456789abcdef0; + + movdiri64(dst, data); + + if (dst[0] == data) + printf("movdiri 64-bit test passed\n"); + else + printf("movdiri 64-bit test failed\n"); +} + +void test_movdiri(void) +{ + test_movdiri_32_bit(); + test_movdiri_64_bit(); +} + +void test_movdir64b(void) +{ + char __attribute((aligned(64))) src[1024], dst[1024]; + + if (!movdir64b_supported()) { + printf("movdir64b is not supported\n"); + + return; + } + memset(src, 0, 1024); + memset(dst, 0, 1024); + for (int i = 0; i < 1024; i++) + dst[i] = i; + + movdir64b(src, dst); + if (memcmp(src, dst, 64)) + printf("movdir64b test failed\n"); + else + printf("movdir64b test passed\n"); +} + +void test_timeout(char *test_name, int state, unsigned long timeout_ns, + unsigned long overhead_ns) +{ + unsigned long tsc1, tsc2, real_tsc, real_ns, tsc_per_nsec; + int ret; + + ret = nsec_to_tsc(1, &tsc_per_nsec); + if (ret) { + printf("umwait test failed: nsec cannot be coverted to tsc.\n"); + return; + } + + if (waitpkg_supported()) { + if (!strcmp(test_name, "umwait")) { + tsc1 = rdtsc(); + umwait(state, timeout_ns); + tsc2 = rdtsc(); + } else { + tsc1 = rdtsc(); + tpause(state, timeout_ns); + tsc2 = rdtsc(); + } + real_tsc = tsc2 - tsc1; + real_ns = real_tsc / tsc_per_nsec; + /* Give enough time for overhead on slow running machine. */ + if (abs(real_ns - timeout_ns) < overhead_ns) { + printf("%s test passed\n", test_name); + } else { + printf("%s test failed:\n", test_name); + printf("real=%luns, expected=%luns. ", + real_ns, timeout_ns); + printf("Likely due to slow machine. "); + printf("Please adjust overhead_ns or re-run test for a few more times.\n"); + } + } else { + printf("%s is not supported\n", test_name); + } +} + +void test_tpause_timeout(int state) +{ + /* + * Timeout 100usec. Assume overhead of executing umwait is 10usec. + * You can adjust the overhead number based on your machine. + */ + test_timeout("tpause", state, 100000, 10000); +} + +void test_tpause(void) +{ + /* Test timeout in state 0 (C0.2). */ + test_tpause_timeout(0); + /* Test timeout in state 1 (C0.1). */ + test_tpause_timeout(1); + /* More tests ... */ +} + +char umonitor_range[1024]; + +void test_umonitor_only(void) +{ + if (waitpkg_supported()) { + umonitor(umonitor_range); + printf("umonitor test passed\n"); + } else { + printf("waitpkg not supported\n"); + } +} + +void show_basic_info(void) +{ + unsigned long tsc; + int ret; + + ret = nsec_to_tsc(1, &tsc); + if (ret < 0) + printf("not tsc freq CPUID available\n"); + else + printf("1 nsec = %lu tsc\n", tsc); +} + +void test_umonitor(void) +{ + test_umonitor_only(); +} + +void test_umwait_timeout(int state) +{ + /* + * Timeout 100usec. Overhead of executing umwait assumes 90usec. + * You can adjust the overhead number based on your machine. + */ + test_timeout("umwait", state, 100000, 90000); +} + +void test_umwait(void) +{ + /* Test timeout in state 0 (C0.2). */ + test_umwait_timeout(0); + /* Test timeout in state 1 (C0.1). */ + test_umwait_timeout(1); + /* More tests ... */ +} + +int main(void) +{ + show_basic_info(); + test_movdiri(); + test_movdir64b(); + test_tpause(); + test_umonitor(); + test_umwait(); + + return 0; +} -- 2.5.0