Commit 78393fdd authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Ingo Molnar

selftests/x86/entry_from_vm86: Add test cases for POPF

POPF is currently broken -- add tests to catch the error.  This
results in:

   [RUN]	POPF with VIP set and IF clear from vm86 mode
   [INFO]	Exited vm86 mode due to STI
   [FAIL]	Incorrect return reason (started at eip = 0xd, ended at eip = 0xf)

because POPF currently fails to check IF before reporting a pending
interrupt.

This patch also makes the FAIL message a bit more informative.
Reported-by: default avatarBart Oldeman <bartoldeman@gmail.com>
Signed-off-by: default avatarAndy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stas Sergeev <stsp@list.ru>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/a16270b5cfe7832d6d00c479d0f871066cbdb52b.1521003603.git.luto@kernel.orgSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 327d53d0
...@@ -95,6 +95,10 @@ asm ( ...@@ -95,6 +95,10 @@ asm (
"int3\n\t" "int3\n\t"
"vmcode_int80:\n\t" "vmcode_int80:\n\t"
"int $0x80\n\t" "int $0x80\n\t"
"vmcode_popf_hlt:\n\t"
"push %ax\n\t"
"popf\n\t"
"hlt\n\t"
"vmcode_umip:\n\t" "vmcode_umip:\n\t"
/* addressing via displacements */ /* addressing via displacements */
"smsw (2052)\n\t" "smsw (2052)\n\t"
...@@ -124,8 +128,8 @@ asm ( ...@@ -124,8 +128,8 @@ asm (
extern unsigned char vmcode[], end_vmcode[]; extern unsigned char vmcode[], end_vmcode[];
extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[], extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[], vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_popf_hlt[],
vmcode_umip_str[], vmcode_umip_sldt[]; vmcode_umip[], vmcode_umip_str[], vmcode_umip_sldt[];
/* Returns false if the test was skipped. */ /* Returns false if the test was skipped. */
static bool do_test(struct vm86plus_struct *v86, unsigned long eip, static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
...@@ -175,7 +179,7 @@ static bool do_test(struct vm86plus_struct *v86, unsigned long eip, ...@@ -175,7 +179,7 @@ static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
(VM86_TYPE(ret) == rettype && VM86_ARG(ret) == retarg)) { (VM86_TYPE(ret) == rettype && VM86_ARG(ret) == retarg)) {
printf("[OK]\tReturned correctly\n"); printf("[OK]\tReturned correctly\n");
} else { } else {
printf("[FAIL]\tIncorrect return reason\n"); printf("[FAIL]\tIncorrect return reason (started at eip = 0x%lx, ended at eip = 0x%lx)\n", eip, v86->regs.eip);
nerrs++; nerrs++;
} }
...@@ -264,6 +268,9 @@ int main(void) ...@@ -264,6 +268,9 @@ int main(void)
v86.regs.ds = load_addr / 16; v86.regs.ds = load_addr / 16;
v86.regs.es = load_addr / 16; v86.regs.es = load_addr / 16;
/* Use the end of the page as our stack. */
v86.regs.esp = 4096;
assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */ assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */
/* #BR -- should deliver SIG??? */ /* #BR -- should deliver SIG??? */
...@@ -295,6 +302,23 @@ int main(void) ...@@ -295,6 +302,23 @@ int main(void)
v86.regs.eflags &= ~X86_EFLAGS_IF; v86.regs.eflags &= ~X86_EFLAGS_IF;
do_test(&v86, vmcode_sti - vmcode, VM86_STI, 0, "STI with VIP set"); do_test(&v86, vmcode_sti - vmcode, VM86_STI, 0, "STI with VIP set");
/* POPF with VIP set but IF clear: should not trap */
v86.regs.eflags = X86_EFLAGS_VIP;
v86.regs.eax = 0;
do_test(&v86, vmcode_popf_hlt - vmcode, VM86_UNKNOWN, 0, "POPF with VIP set and IF clear");
/* POPF with VIP set and IF set: should trap */
v86.regs.eflags = X86_EFLAGS_VIP;
v86.regs.eax = X86_EFLAGS_IF;
do_test(&v86, vmcode_popf_hlt - vmcode, VM86_STI, 0, "POPF with VIP and IF set");
/* POPF with VIP clear and IF set: should not trap */
v86.regs.eflags = 0;
v86.regs.eax = X86_EFLAGS_IF;
do_test(&v86, vmcode_popf_hlt - vmcode, VM86_UNKNOWN, 0, "POPF with VIP clear and IF set");
v86.regs.eflags = 0;
/* INT3 -- should cause #BP */ /* INT3 -- should cause #BP */
do_test(&v86, vmcode_int3 - vmcode, VM86_TRAP, 3, "INT3"); do_test(&v86, vmcode_int3 - vmcode, VM86_TRAP, 3, "INT3");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment