Run the test with Intel's vendor ID and in the long mode, to test the emulation of this instruction on AMD. Signed-off-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx> --- x86/Makefile.x86_64 | 2 + x86/sysenter.c | 127 ++++++++++++++++++++++++++++++++++++++++++++ x86/unittests.cfg | 5 ++ 3 files changed, 134 insertions(+) create mode 100644 x86/sysenter.c diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64 index 865da07d..8ce53650 100644 --- a/x86/Makefile.x86_64 +++ b/x86/Makefile.x86_64 @@ -33,6 +33,7 @@ tests += $(TEST_DIR)/vmware_backdoors.$(exe) tests += $(TEST_DIR)/rdpru.$(exe) tests += $(TEST_DIR)/pks.$(exe) tests += $(TEST_DIR)/pmu_lbr.$(exe) +tests += $(TEST_DIR)/sysenter.$(exe) ifeq ($(CONFIG_EFI),y) @@ -60,3 +61,4 @@ $(TEST_DIR)/hyperv_clock.$(bin): $(TEST_DIR)/hyperv_clock.o $(TEST_DIR)/vmx.$(bin): $(TEST_DIR)/vmx_tests.o $(TEST_DIR)/svm.$(bin): $(TEST_DIR)/svm_tests.o $(TEST_DIR)/svm_npt.$(bin): $(TEST_DIR)/svm_npt.o +$(TEST_DIR)/sysenter.o: CFLAGS += -Wa,-mintel64 diff --git a/x86/sysenter.c b/x86/sysenter.c new file mode 100644 index 00000000..6c32fea4 --- /dev/null +++ b/x86/sysenter.c @@ -0,0 +1,127 @@ +#include "alloc.h" +#include "libcflat.h" +#include "processor.h" +#include "msr.h" +#include "desc.h" + + +// undefine this to run the syscall instruction in 64 bit mode. +// this won't work on AMD due to disabled code in the emulator. +#define COMP32 + +int main(int ac, char **av) +{ + extern void sysenter_target(void); + extern void test_done(void); + + setup_vm(); + + int gdt_index = 0x50 >> 3; + ulong rax = 0xDEAD; + + /* init the sysenter GDT block */ + /*gdt64[gdt_index+0] = gdt64[KERNEL_CS >> 3]; + gdt64[gdt_index+1] = gdt64[KERNEL_DS >> 3]; + gdt64[gdt_index+2] = gdt64[USER_CS >> 3]; + gdt64[gdt_index+3] = gdt64[USER_DS >> 3];*/ + + /* init the sysenter msrs*/ + wrmsr(MSR_IA32_SYSENTER_CS, gdt_index << 3); + wrmsr(MSR_IA32_SYSENTER_ESP, 0xAAFFFFFFFF); + wrmsr(MSR_IA32_SYSENTER_EIP, (uint64_t)sysenter_target); + + u8 *thunk = (u8*)malloc(50); + u8 *tmp = thunk; + + printf("Thunk at 0x%lx\n", (u64)thunk); + + /* movabs test_done, %rdx*/ + *tmp++ = 0x48; *tmp++ = 0xBA; + *(u64 *)tmp = (uint64_t)test_done; tmp += 8; + /* jmp %%rdx*/ + *tmp++ = 0xFF; *tmp++ = 0xe2; + + asm volatile ( +#ifdef COMP32 + "# switch to comp32, mode prior to running the test\n" + "ljmpl *1f\n" + "1:\n" + ".long 1f\n" + ".long " xstr(KERNEL_CS32) "\n" + "1:\n" + ".code32\n" +#else + "# store the 64 bit thunk address to rdx\n" + "mov %[thunk], %%rdx\n" +#endif + "#+++++++++++++++++++++++++++++++++++++++++++++++++++" + "# user code (64 bit or comp32)" + "#+++++++++++++++++++++++++++++++++++++++++++++++++++" + + "# use sysenter to enter 64 bit system code\n" + "mov %%esp, %%ecx #stash rsp value\n" + "mov $1, %%ebx\n" + "sysenter\n" + "ud2\n" + + "#+++++++++++++++++++++++++++++++++++++++++++++++++++\n" + "# 64 bit cpl=0 code" + "#+++++++++++++++++++++++++++++++++++++++++++++++++++\n" + + ".code64\n" + "sysenter_target:\n" + +#ifdef COMP32 + "test %%rbx, %%rbx # check if we are here for second time \n" + "jne 1f\n" + "movq %%rcx, %%rsp # restore stack pointer manually\n" + "jmp test_done\n" + "1:\n" +#endif + + "# test that MSR_IA32_SYSENTER_ESP is correct\n" + "movq $0xAAFFFFFFFF, %%rbx\n" + "movq $0xDEAD, %%rax\n" + "cmpq %%rsp, %%rbx \n" + "jne 1f\n" + "movq $0xACED, %%rax\n" + + "# use sysexit to exit back\n" + "1:\n" +#ifdef COMP32 + "leaq sysexit_target, %%rdx\n" + "sysexit\n" + "sysexit_target:\n" + "# second sysenter to return to CPL=0 and 64 bit\n" + "# the sysenter handler will jump back to here without sysexit due to ebx=0\n" + ".code32\n" + "mov $0, %%ebx\n" + "sysenter\n" +#else + "# this will go through thunk to test_done, which tests,\n" + "# that we can sysexit to high addresses\n" + ".byte 0x48\n" + "sysexit\n" + "ud2\n" +#endif + + ".code64\n" + "test_done:\n" + "nop\n" + + : /*outputs*/ + "=a" (rax) + : /* inputs*/ + [thunk] "r" (thunk) + : /*clobbers*/ + "rbx", /* action flag for sysenter_target */ + "rcx", /* saved RSP */ + "rdx", /* used for SYSEXIT*/ + "flags" + ); + + report(rax == 0xACED, "MSR_IA32_SYSENTER_ESP has correct value"); + return report_summary(); +} + + diff --git a/x86/unittests.cfg b/x86/unittests.cfg index db9bb3ac..ebb3fdfc 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -223,6 +223,11 @@ file = syscall.flat arch = x86_64 extra_params = -cpu Opteron_G1,vendor=AuthenticAMD +[sysenter] +file = sysenter.flat +arch = x86_64 +extra_params = -cpu host,vendor=GenuineIntel + [tsc] file = tsc.flat extra_params = -cpu kvm64,+rdtscp -- 2.26.3