From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753380AbbFAQC2 (ORCPT ); Mon, 1 Jun 2015 12:02:28 -0400 Received: from lists.s-osg.org ([54.187.51.154]:45049 "EHLO lists.s-osg.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752160AbbFAQCT (ORCPT ); Mon, 1 Jun 2015 12:02:19 -0400 Message-ID: <556C8209.1030007@osg.samsung.com> Date: Mon, 01 Jun 2015 10:02:17 -0600 From: Shuah Khan Organization: Samsung Open Source Group User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: Andy Lutomirski , Ingo Molnar CC: Jan Beulich , x86@kernel.org, "linux-kernel@vger.kernel.org" Subject: Re: [PATCH] x86_32, entry, selftests: Add a selftest for kernel entries from vm86 mode References: <09a9916761e0a9e42d4922f147af45a0079cc1e8.1432936374.git.luto@kernel.org> In-Reply-To: <09a9916761e0a9e42d4922f147af45a0079cc1e8.1432936374.git.luto@kernel.org> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 > --- > > 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? Once the above are verified, here is my Acked-by: Shuah Khan 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 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +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) shuahkh@osg.samsung.com | (970) 217-8978