On Mon, Jun 1, 2015 at 9:02 AM, Shuah Khan <shua...@osg.samsung.com> wrote: > On 05/29/2015 03:58 PM, Andy Lutomirski wrote: >> Test a couple of special cases in 32-bit kernels for entries from >> vm86 mode. This will OOPS both old kernels due to a bug and and >> 4.1-rc5 due to a regression I introduced, and it should make sure >> that the SYSENTER-from-vm86-mode hack in the kernel keeps working. >> >> Tests: 394838c96013 x86/asm/entry/32: Fix user_mode() misuses >> Tests: 7ba554b5ac69 x86/asm/entry/32: Really make user_mode() work correctly >> for VM86 mode >> Signed-off-by: Andy Lutomirski <l...@kernel.org> >> --- >> >> Ingo, Shuah: I think this should go in through -tip. (In general, I think >> new x86 tests that don't have interesting interactions with the kselftest >> infrastructure should go in through -tip, especially tests such as this one >> that are related to recent regressions.) > > No problem going through tip. Could you please make sure > > "make kselftest" run from top level and > tools/testing/selftests/kselftest_install.sh > > don't break?
Both 'make kselftest -j12 TARGETS=x86' and ../../../tools/testing/selftests/kselftest_install.sh work for me. (The .. thing is annoying -- would it make sense to fix it to work from the kernel tree root?) --Andy > > Once the above are verified, here is my > > Acked-by: Shuah Khan <shua...@osg.samsung.com> > > Thanks, > -- Shuah > >> >> tools/testing/selftests/x86/Makefile | 6 +- >> tools/testing/selftests/x86/entry_from_vm86.c | 114 >> ++++++++++++++++++++++++++ >> 2 files changed, 118 insertions(+), 2 deletions(-) >> create mode 100644 tools/testing/selftests/x86/entry_from_vm86.c >> >> diff --git a/tools/testing/selftests/x86/Makefile >> b/tools/testing/selftests/x86/Makefile >> index 5bdb781163d1..9b0d8baf2934 100644 >> --- a/tools/testing/selftests/x86/Makefile >> +++ b/tools/testing/selftests/x86/Makefile >> @@ -5,8 +5,10 @@ include ../lib.mk >> .PHONY: all all_32 all_64 warn_32bit_failure clean >> >> TARGETS_C_BOTHBITS := sigreturn single_step_syscall >> +TARGETS_C_32BIT_ONLY := entry_from_vm86 >> >> -BINARIES_32 := $(TARGETS_C_BOTHBITS:%=%_32) >> +TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) >> +BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32) >> BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64) >> >> CFLAGS := -O2 -g -std=gnu99 -pthread -Wall >> @@ -32,7 +34,7 @@ all_64: $(BINARIES_64) >> clean: >> $(RM) $(BINARIES_32) $(BINARIES_64) >> >> -$(TARGETS_C_BOTHBITS:%=%_32): %_32: %.c >> +$(TARGETS_C_32BIT_ALL:%=%_32): %_32: %.c >> $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl >> >> $(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c >> diff --git a/tools/testing/selftests/x86/entry_from_vm86.c >> b/tools/testing/selftests/x86/entry_from_vm86.c >> new file mode 100644 >> index 000000000000..5c38a187677b >> --- /dev/null >> +++ b/tools/testing/selftests/x86/entry_from_vm86.c >> @@ -0,0 +1,114 @@ >> +/* >> + * entry_from_vm86.c - tests kernel entries from vm86 mode >> + * Copyright (c) 2014-2015 Andrew Lutomirski >> + * >> + * This exercises a few paths that need to special-case vm86 mode. >> + * >> + * GPL v2. >> + */ >> + >> +#define _GNU_SOURCE >> + >> +#include <assert.h> >> +#include <stdlib.h> >> +#include <sys/syscall.h> >> +#include <sys/signal.h> >> +#include <sys/ucontext.h> >> +#include <unistd.h> >> +#include <stdio.h> >> +#include <string.h> >> +#include <inttypes.h> >> +#include <sys/mman.h> >> +#include <err.h> >> +#include <stddef.h> >> +#include <stdbool.h> >> +#include <errno.h> >> +#include <sys/vm86.h> >> + >> +static unsigned long load_addr = 0x10000; >> +static int nerrs = 0; >> + >> +asm ( >> + ".pushsection .rodata\n\t" >> + ".type vmcode_bound, @object\n\t" >> + "vmcode:\n\t" >> + "vmcode_bound:\n\t" >> + ".code16\n\t" >> + "bound %ax, (2048)\n\t" >> + "int3\n\t" >> + "vmcode_sysenter:\n\t" >> + "sysenter\n\t" >> + ".size vmcode, . - vmcode\n\t" >> + "end_vmcode:\n\t" >> + ".code32\n\t" >> + ".popsection" >> + ); >> + >> +extern unsigned char vmcode[], end_vmcode[]; >> +extern unsigned char vmcode_bound[], vmcode_sysenter[]; >> + >> +static void do_test(struct vm86plus_struct *v86, unsigned long eip, >> + const char *text) >> +{ >> + long ret; >> + >> + printf("[RUN]\t%s from vm86 mode\n", text); >> + v86->regs.eip = eip; >> + ret = vm86(VM86_ENTER, v86); >> + >> + if (ret == -1 && errno == ENOSYS) { >> + printf("[SKIP]\tvm86 not supported\n"); >> + return; >> + } >> + >> + if (VM86_TYPE(ret) == VM86_INTx) { >> + char trapname[32]; >> + int trapno = VM86_ARG(ret); >> + if (trapno == 13) >> + strcpy(trapname, "GP"); >> + else if (trapno == 5) >> + strcpy(trapname, "BR"); >> + else if (trapno == 14) >> + strcpy(trapname, "PF"); >> + else >> + sprintf(trapname, "%d", trapno); >> + >> + printf("[OK]\tExited vm86 mode due to #%s\n", trapname); >> + } else if (VM86_TYPE(ret) == VM86_UNKNOWN) { >> + printf("[OK]\tExited vm86 mode due to unhandled GP fault\n"); >> + } else { >> + printf("[OK]\tExited vm86 mode due to type %ld, arg %ld\n", >> + VM86_TYPE(ret), VM86_ARG(ret)); >> + } >> +} >> + >> +int main(void) >> +{ >> + struct vm86plus_struct v86; >> + unsigned char *addr = mmap((void *)load_addr, 4096, >> + PROT_READ | PROT_WRITE | PROT_EXEC, >> + MAP_ANONYMOUS | MAP_PRIVATE, -1,0); >> + if (addr != (unsigned char *)load_addr) >> + err(1, "mmap"); >> + >> + memcpy(addr, vmcode, end_vmcode - vmcode); >> + addr[2048] = 2; >> + addr[2050] = 3; >> + >> + memset(&v86, 0, sizeof(v86)); >> + >> + v86.regs.cs = load_addr / 16; >> + v86.regs.ss = load_addr / 16; >> + v86.regs.ds = load_addr / 16; >> + v86.regs.es = load_addr / 16; >> + >> + assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */ >> + >> + /* #BR -- should deliver SIG??? */ >> + do_test(&v86, vmcode_bound - vmcode, "#BR"); >> + >> + /* SYSENTER -- should cause #GP or #UD depending on CPU */ >> + do_test(&v86, vmcode_sysenter - vmcode, "SYSENTER"); >> + >> + return (nerrs == 0 ? 0 : 1); >> +} >> > > > -- > Shuah Khan > Sr. Linux Kernel Developer > Open Source Innovation Group > Samsung Research America (Silicon Valley) > shua...@osg.samsung.com | (970) 217-8978 -- Andy Lutomirski AMA Capital Management, LLC -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/