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.

Cc: sta...@vger.kernel.org
Reported-by: Bart Oldeman <bartolde...@gmail.com>
Signed-off-by: Andy Lutomirski <l...@kernel.org>
---
 tools/testing/selftests/x86/entry_from_vm86.c | 30 ++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/x86/entry_from_vm86.c 
b/tools/testing/selftests/x86/entry_from_vm86.c
index 6e85f0d0498d..ade443a88421 100644
--- a/tools/testing/selftests/x86/entry_from_vm86.c
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -95,6 +95,10 @@ asm (
        "int3\n\t"
        "vmcode_int80:\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"
        /* addressing via displacements */
        "smsw (2052)\n\t"
@@ -124,8 +128,8 @@ asm (
 
 extern unsigned char vmcode[], end_vmcode[];
 extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
-       vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[],
-       vmcode_umip_str[], vmcode_umip_sldt[];
+       vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_popf_hlt[],
+       vmcode_umip[], vmcode_umip_str[], vmcode_umip_sldt[];
 
 /* Returns false if the test was skipped. */
 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)) {
                printf("[OK]\tReturned correctly\n");
        } 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++;
        }
 
@@ -264,6 +268,9 @@ int main(void)
        v86.regs.ds = 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 */
 
        /* #BR -- should deliver SIG??? */
@@ -295,6 +302,23 @@ int main(void)
        v86.regs.eflags &= ~X86_EFLAGS_IF;
        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 */
        do_test(&v86, vmcode_int3 - vmcode, VM86_TRAP, 3, "INT3");
 
-- 
2.14.3

Reply via email to