diff mbox

[for-4.8] x86/pv: Fix the handling of `int $x` for vectors which alias exceptions

Message ID 1498158767-4923-1-git-send-email-andrew.cooper3@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andrew Cooper June 22, 2017, 7:12 p.m. UTC
The claim at the top of c/s 2e426d6eecf "x86/traps: Drop use_error_code
parameter from do_{,guest_}trap()" is only actually true for hardware
exceptions.  It is not true for `int $x` instructions (which never push error
code), irrespective of whether the vector aliases an exception or not.

Furthermore, c/s 6480cc6280e "x86/traps: Fix failed ASSERT() in
do_guest_trap()" really should have helped highlight that a regression had
been introduced.

Modify pv_inject_event() to understand event types other than
X86_EVENTTYPE_HW_EXCEPTION, and introduce pv_inject_sw_interrupt() for the
`int $x` handling code.

Add further assertions to pv_inject_event() concerning the type of events
passed in, which in turn requires that do_guest_trap() set its type
appropriately (which is now used exclusively for hardware exceptions).

This is logically a backport of c/s 5c4f579e0ee4f38cad5636bbf8ce700a394338d0
from Xen 4.9, but disentangled from the other injection work.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
---
 xen/arch/x86/traps.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

Comments

Jan Beulich June 23, 2017, 1:17 p.m. UTC | #1
>>> On 22.06.17 at 21:12, <andrew.cooper3@citrix.com> wrote:
> The claim at the top of c/s 2e426d6eecf "x86/traps: Drop use_error_code
> parameter from do_{,guest_}trap()" is only actually true for hardware
> exceptions.  It is not true for `int $x` instructions (which never push error
> code), irrespective of whether the vector aliases an exception or not.
> 
> Furthermore, c/s 6480cc6280e "x86/traps: Fix failed ASSERT() in
> do_guest_trap()" really should have helped highlight that a regression had
> been introduced.
> 
> Modify pv_inject_event() to understand event types other than
> X86_EVENTTYPE_HW_EXCEPTION, and introduce pv_inject_sw_interrupt() for the
> `int $x` handling code.
> 
> Add further assertions to pv_inject_event() concerning the type of events
> passed in, which in turn requires that do_guest_trap() set its type
> appropriately (which is now used exclusively for hardware exceptions).
> 
> This is logically a backport of c/s 5c4f579e0ee4f38cad5636bbf8ce700a394338d0
> from Xen 4.9, but disentangled from the other injection work.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Thanks, applied.

Jan
diff mbox

Patch

diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 19ac652..8c992ce 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -625,14 +625,24 @@  void fatal_trap(const struct cpu_user_regs *regs, bool_t show_remote)
           (regs->eflags & X86_EFLAGS_IF) ? "" : ", IN INTERRUPT CONTEXT");
 }
 
-static void do_guest_trap(unsigned int trapnr,
-                          const struct cpu_user_regs *regs)
+static void pv_inject_event(
+    unsigned int trapnr, const struct cpu_user_regs *regs, unsigned int type)
 {
     struct vcpu *v = current;
     struct trap_bounce *tb;
     const struct trap_info *ti;
-    const bool use_error_code =
-        ((trapnr < 32) && (TRAP_HAVE_EC & (1u << trapnr)));
+    bool use_error_code;
+
+    if ( type == X86_EVENTTYPE_HW_EXCEPTION )
+    {
+        ASSERT(trapnr < 32);
+        use_error_code = TRAP_HAVE_EC & (1u << trapnr);
+    }
+    else
+    {
+        ASSERT(type == X86_EVENTTYPE_SW_INTERRUPT);
+        use_error_code = false;
+    }
 
     trace_pv_trap(trapnr, regs->eip, use_error_code, regs->error_code);
 
@@ -658,6 +668,12 @@  static void do_guest_trap(unsigned int trapnr,
                 trapstr(trapnr), trapnr, regs->error_code);
 }
 
+static void do_guest_trap(
+    unsigned int trapnr, const struct cpu_user_regs *regs)
+{
+    pv_inject_event(trapnr, regs, X86_EVENTTYPE_HW_EXCEPTION);
+}
+
 static void instruction_done(
     struct cpu_user_regs *regs, unsigned long eip, unsigned int bpmatch)
 {
@@ -3685,7 +3701,7 @@  void do_general_protection(struct cpu_user_regs *regs)
         if ( permit_softint(TI_GET_DPL(ti), v, regs) )
         {
             regs->eip += 2;
-            do_guest_trap(vector, regs);
+            pv_inject_event(vector, regs, X86_EVENTTYPE_SW_INTERRUPT);
             return;
         }
     }