linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] x86_32, entry, selftests: Add a selftest for kernel entries from vm86 mode
@ 2015-05-29 21:58 Andy Lutomirski
  2015-06-01 16:02 ` Shuah Khan
  2015-06-02  5:37 ` [tip:x86/urgent] x86/asm/entry/32, selftests: Add a selftest for kernel entries from VM86 mode tip-bot for Andy Lutomirski
  0 siblings, 2 replies; 7+ messages in thread
From: Andy Lutomirski @ 2015-05-29 21:58 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: Jan Beulich, x86, linux-kernel, Shuah Khan, Andy Lutomirski

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 <luto@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.)

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);
+}
-- 
2.3.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] x86_32, entry, selftests: Add a selftest for kernel entries from vm86 mode
  2015-05-29 21:58 [PATCH] x86_32, entry, selftests: Add a selftest for kernel entries from vm86 mode Andy Lutomirski
@ 2015-06-01 16:02 ` Shuah Khan
  2015-06-01 22:54   ` Andy Lutomirski
  2015-06-02  5:37 ` [tip:x86/urgent] x86/asm/entry/32, selftests: Add a selftest for kernel entries from VM86 mode tip-bot for Andy Lutomirski
  1 sibling, 1 reply; 7+ messages in thread
From: Shuah Khan @ 2015-06-01 16:02 UTC (permalink / raw)
  To: Andy Lutomirski, Ingo Molnar; +Cc: Jan Beulich, x86, linux-kernel

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 <luto@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?

Once the above are verified, here is my

Acked-by: Shuah Khan <shuahkh@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)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] x86_32, entry, selftests: Add a selftest for kernel entries from vm86 mode
  2015-06-01 16:02 ` Shuah Khan
@ 2015-06-01 22:54   ` Andy Lutomirski
  2015-06-01 23:27     ` Shuah Khan
  0 siblings, 1 reply; 7+ messages in thread
From: Andy Lutomirski @ 2015-06-01 22:54 UTC (permalink / raw)
  To: Shuah Khan
  Cc: Andy Lutomirski, Ingo Molnar, Jan Beulich, X86 ML, linux-kernel

On Mon, Jun 1, 2015 at 9:02 AM, Shuah Khan <shuahkh@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 <luto@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 <shuahkh@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)
> shuahkh@osg.samsung.com | (970) 217-8978



-- 
Andy Lutomirski
AMA Capital Management, LLC

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] x86_32, entry, selftests: Add a selftest for kernel entries from vm86 mode
  2015-06-01 22:54   ` Andy Lutomirski
@ 2015-06-01 23:27     ` Shuah Khan
  2015-06-01 23:45       ` Andy Lutomirski
  0 siblings, 1 reply; 7+ messages in thread
From: Shuah Khan @ 2015-06-01 23:27 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Andy Lutomirski, Ingo Molnar, Jan Beulich, X86 ML, linux-kernel,
	Shuah Khan

On 06/01/2015 04:54 PM, Andy Lutomirski wrote:
> On Mon, Jun 1, 2015 at 9:02 AM, Shuah Khan <shuahkh@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 <luto@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?)
> 

What is annoying about it and how would it get solved by making it
run from the kernel tree root?

-- Shuah


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] x86_32, entry, selftests: Add a selftest for kernel entries from vm86 mode
  2015-06-01 23:27     ` Shuah Khan
@ 2015-06-01 23:45       ` Andy Lutomirski
  2015-06-01 23:58         ` Shuah Khan
  0 siblings, 1 reply; 7+ messages in thread
From: Andy Lutomirski @ 2015-06-01 23:45 UTC (permalink / raw)
  To: Shuah Khan
  Cc: Andy Lutomirski, Ingo Molnar, Jan Beulich, X86 ML, linux-kernel

On Mon, Jun 1, 2015 at 4:27 PM, Shuah Khan <shuahkh@osg.samsung.com> wrote:
> On 06/01/2015 04:54 PM, Andy Lutomirski wrote:
>> On Mon, Jun 1, 2015 at 9:02 AM, Shuah Khan <shuahkh@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 <luto@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?)
>>
>
> What is annoying about it and how would it get solved by making it
> run from the kernel tree root?
>

I ran it from the kernel tree root and it told me to change my
directory.  I think it should have changed the directory itself :)

--Andy

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] x86_32, entry, selftests: Add a selftest for kernel entries from vm86 mode
  2015-06-01 23:45       ` Andy Lutomirski
@ 2015-06-01 23:58         ` Shuah Khan
  0 siblings, 0 replies; 7+ messages in thread
From: Shuah Khan @ 2015-06-01 23:58 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Andy Lutomirski, Ingo Molnar, Jan Beulich, X86 ML, linux-kernel,
	Shuah Khan

On 06/01/2015 05:45 PM, Andy Lutomirski wrote:
> On Mon, Jun 1, 2015 at 4:27 PM, Shuah Khan <shuahkh@osg.samsung.com> wrote:
>> On 06/01/2015 04:54 PM, Andy Lutomirski wrote:
>>> On Mon, Jun 1, 2015 at 9:02 AM, Shuah Khan <shuahkh@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 <luto@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?)
>>>
>>
>> What is annoying about it and how would it get solved by making it
>> run from the kernel tree root?
>>
> 
> I ran it from the kernel tree root and it told me to change my
> directory.  I think it should have changed the directory itself :)
> 

ok that makes sense. I can make it do that. :)

thanks,
-- Shuah


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tip:x86/urgent] x86/asm/entry/32, selftests: Add a selftest for kernel entries from VM86 mode
  2015-05-29 21:58 [PATCH] x86_32, entry, selftests: Add a selftest for kernel entries from vm86 mode Andy Lutomirski
  2015-06-01 16:02 ` Shuah Khan
@ 2015-06-02  5:37 ` tip-bot for Andy Lutomirski
  1 sibling, 0 replies; 7+ messages in thread
From: tip-bot for Andy Lutomirski @ 2015-06-02  5:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, luto, linux-kernel, mingo, shuahkh, JBeulich, tglx, hpa,
	torvalds

Commit-ID:  c2affbf9a50882572e04645d5946ab0a921f061f
Gitweb:     http://git.kernel.org/tip/c2affbf9a50882572e04645d5946ab0a921f061f
Author:     Andy Lutomirski <luto@kernel.org>
AuthorDate: Fri, 29 May 2015 14:58:24 -0700
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Sat, 30 May 2015 10:21:32 +0200

x86/asm/entry/32, selftests: Add a selftest for kernel entries from VM86 mode

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.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/09a9916761e0a9e42d4922f147af45a0079cc1e8.1432936374.git.luto@kernel.org
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: Ingo Molnar <mingo@kernel.org>
---
 tools/testing/selftests/x86/Makefile          |   6 +-
 tools/testing/selftests/x86/entry_from_vm86.c | 114 ++++++++++++++++++++++++++
 2 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index 5bdb781..9b0d8ba 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 0000000..5c38a18
--- /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);
+}

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-06-02  5:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-29 21:58 [PATCH] x86_32, entry, selftests: Add a selftest for kernel entries from vm86 mode Andy Lutomirski
2015-06-01 16:02 ` Shuah Khan
2015-06-01 22:54   ` Andy Lutomirski
2015-06-01 23:27     ` Shuah Khan
2015-06-01 23:45       ` Andy Lutomirski
2015-06-01 23:58         ` Shuah Khan
2015-06-02  5:37 ` [tip:x86/urgent] x86/asm/entry/32, selftests: Add a selftest for kernel entries from VM86 mode tip-bot for Andy Lutomirski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).