All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xen.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Julien Grall <julien.grall@arm.com>,
	Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>,
	Jan Beulich <JBeulich@suse.com>
Subject: [PATCH for 4.9 4/6] x86/svm: Introduce svm_emul_swint_injection()
Date: Fri, 31 Mar 2017 20:50:51 +0100	[thread overview]
Message-ID: <1490989853-21879-5-git-send-email-andrew.cooper3@citrix.com> (raw)
In-Reply-To: <1490989853-21879-1-git-send-email-andrew.cooper3@citrix.com>

Software events require emulation in some cases on AMD hardware.  Introduce
svm_emul_swint_injection() to perform this emulation if necessary in
svm_inject_event(), which will cope with any sources of event, rather than
just those coming from x86_emulate().

This logic mirrors inject_swint() in the x86 instruction emulator.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Boris Ostrovsky <boris.ostrovsky@oracle.com>
CC: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
CC: Julien Grall <julien.grall@arm.com>
---
 xen/arch/x86/hvm/svm/svm.c | 136 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 4d7e49f..6d77c7e 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1183,6 +1183,124 @@ static void svm_vcpu_destroy(struct vcpu *v)
     passive_domain_destroy(v);
 }
 
+/*
+ * Emulate enough of interrupt injection to cover the DPL check (omitted by
+ * hardware), and to work out whether it is safe to move %rip fowards for
+ * architectural trap vs fault semantics in the exception frame (which
+ * hardware won't cope with).
+ *
+ * The event parameter will be modified to a fault if necessary.
+ */
+static void svm_emul_swint_injection(struct x86_event *event)
+{
+    struct vcpu *curr = current;
+    struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
+    struct cpu_user_regs *regs = guest_cpu_user_regs();
+
+    unsigned int trap = event->vector, type = event->type;
+    unsigned int fault = TRAP_gp_fault, ec = 0;
+
+    if ( vmcb->_cr0 & X86_CR0_PE ) /* TODO: support real-mode injection? */
+    {
+        pagefault_info_t pf;
+        struct segment_register idtr;
+        unsigned int idte_size, idte_offset;
+        unsigned long idte_linear_addr;
+        struct { uint32_t a, b, c, d; } idte = {};
+        bool lm = vmcb->_efer & EFER_LMA;
+        enum hvm_segmentation_mode seg_mode =
+            lm ? hvm_seg_mode_long : hvm_seg_mode_prot;
+        int rc;
+
+        idte_size = lm ? 16 : 8;
+        idte_offset = trap * idte_size;
+
+        /* ICEBP sets the External Event bit despite being an instruction. */
+        ec = (trap << 3) | X86_XEC_IDT |
+            (type == X86_EVENTTYPE_PRI_SW_EXCEPTION ? X86_XEC_EXT : 0);
+
+        /*
+         * TODO: This does not cover the v8086 mode with CR4.VME case
+         * correctly, but falls on the safe side from the point of view of a
+         * 32bit OS.  Someone with many TUITs can see about reading the TSS
+         * Software Interrupt Redirection bitmap.
+         */
+        if ( (regs->eflags & X86_EFLAGS_VM) &&
+             MASK_EXTR(regs->eflags, X86_EFLAGS_IOPL) != 3 )
+            goto raise_exception;
+
+        /*
+         * Read all 8/16 bytes so the idtr limit check is applied properly to
+         * this entry, even though don't look all the words read.
+         */
+        hvm_get_segment_register(curr, x86_seg_idtr, &idtr);
+        if ( !hvm_virtual_to_linear_addr(x86_seg_idtr, &idtr, idte_offset,
+                                         idte_size, hvm_access_read,
+                                         seg_mode, &idte_linear_addr) )
+            goto raise_exception;
+
+        rc = hvm_copy_from_guest_linear(&idte, idte_linear_addr, idte_size,
+                                        PFEC_implicit, &pf);
+        if ( rc )
+        {
+            if ( rc == HVMCOPY_bad_gva_to_gfn )
+            {
+                fault = TRAP_page_fault;
+                ec = pf.ec;
+                event->cr2 = pf.linear;
+            }
+
+            goto raise_exception;
+        }
+
+        /* This must be an interrupt, trap, or task gate. */
+        switch ( (idte.b >> 8) & 0x1f )
+            {
+            case SYS_DESC_irq_gate:
+            case SYS_DESC_trap_gate:
+                break;
+            case SYS_DESC_irq_gate16:
+            case SYS_DESC_trap_gate16:
+            case SYS_DESC_task_gate:
+                if ( !lm )
+                    break;
+                /* fall through */
+            default:
+                goto raise_exception;
+            }
+
+        /* The 64-bit high half's type must be zero. */
+        if ( idte.d & 0x1f00 )
+            goto raise_exception;
+
+        /* ICEBP counts as a hardware event, and bypasses the dpl check. */
+        if ( type != X86_EVENTTYPE_PRI_SW_EXCEPTION &&
+             vmcb->_cpl > ((idte.b >> 13) & 3) )
+                goto raise_exception;
+
+        /* Is this entry present? */
+        if ( !(idte.b & (1u << 15)) )
+        {
+            fault = TRAP_no_segment;
+            goto raise_exception;
+        }
+
+        /*
+         * Any further fault during injection will cause a double fault.  It
+         * is fine to leave this up to hardware, and software won't be in a
+         * position to care about the architectural correctness of %rip in the
+         * exception frame.
+         */
+        return;
+    }
+
+ raise_exception:
+    event->vector = fault;
+    event->type = X86_EVENTTYPE_HW_EXCEPTION;
+    event->insn_len = 0;
+    event->error_code = ec;
+}
+
 static void svm_inject_event(const struct x86_event *event)
 {
     struct vcpu *curr = current;
@@ -1191,6 +1309,24 @@ static void svm_inject_event(const struct x86_event *event)
     struct x86_event _event = *event;
     struct cpu_user_regs *regs = guest_cpu_user_regs();
 
+    /*
+     * For hardware lacking NRips support, and always for ICEBP instructions,
+     * the processor requires extra help to deliver software events.
+     *
+     * Xen must emulate enough of the event injection to be sure that a
+     * further fault shouldn't occur during delivery.  This covers the fact
+     * that hardware doesn't perform DPL checking on injection.
+     *
+     * Also, it accounts for proper positioning of %rip for an event with trap
+     * semantics (where %rip should point after the instruction) which suffers
+     * a fault during injection (at which point %rip should point at the
+     * instruction).
+     */
+    if ( event->type == X86_EVENTTYPE_PRI_SW_EXCEPTION ||
+         (!cpu_has_svm_nrips && (event->type == X86_EVENTTYPE_SW_INTERRUPT ||
+                                 event->type == X86_EVENTTYPE_SW_EXCEPTION)) )
+        svm_emul_swint_injection(&_event);
+
     switch ( _event.vector )
     {
     case TRAP_debug:
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  parent reply	other threads:[~2017-03-31 19:50 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-31 19:50 [PATCH for 4.9 0/6] x86/emul: Fixes Andrew Cooper
2017-03-31 19:50 ` [PATCH for 4.9 1/6] x86/hvm: Correct some address space terminology Andrew Cooper
2017-04-03  8:24   ` Paul Durrant
2017-04-03  8:24   ` Jan Beulich
2017-04-03 10:19     ` Andrew Cooper
2017-04-03 10:29       ` Jan Beulich
2017-03-31 19:50 ` [PATCH for 4.9 2/6] x86/hvm: Correct long mode predicate Andrew Cooper
2017-04-03  8:26   ` Paul Durrant
2017-04-03  8:30   ` Jan Beulich
2017-04-03  8:50   ` George Dunlap
2017-04-05  7:08   ` Tian, Kevin
2017-03-31 19:50 ` [PATCH for 4.9 3/6] x86/hvm: Fix segmentation logic for system segments Andrew Cooper
2017-04-03  8:31   ` Paul Durrant
2017-04-03  9:13   ` Jan Beulich
2017-04-03 14:27     ` Andrew Cooper
2017-04-03 15:07       ` Jan Beulich
2017-04-03 15:42         ` Andrew Cooper
2017-04-03 16:08           ` Jan Beulich
2017-04-03 17:37             ` Andrew Cooper
2017-04-04 10:18               ` Andrew Cooper
2017-04-04 10:32                 ` Jan Beulich
2017-03-31 19:50 ` Andrew Cooper [this message]
2017-04-03  9:30   ` [PATCH for 4.9 4/6] x86/svm: Introduce svm_emul_swint_injection() Jan Beulich
2017-04-03 14:04   ` Boris Ostrovsky
2017-03-31 19:50 ` [PATCH for 4.9 5/6] x86/emul: Drop swint_emulate infrastructure Andrew Cooper
2017-04-03  8:36   ` Paul Durrant
2017-04-03  9:38   ` Jan Beulich
2017-03-31 19:50 ` [PATCH for 4.9 6/6] x86/emul: Require callers to provide LMA in the emulation context Andrew Cooper
2017-04-03  8:40   ` Paul Durrant
2017-04-03 10:10   ` Jan Beulich
2017-04-05 16:24     ` Andrew Cooper
2017-04-06  6:58       ` Jan Beulich
2017-04-06  9:47         ` Andrew Cooper
2017-04-06 14:14           ` Jan Beulich
2017-04-06 16:32             ` Andrew Cooper
2017-04-07  8:35               ` Jan Beulich
2017-04-05 16:07   ` Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1490989853-21879-5-git-send-email-andrew.cooper3@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=JBeulich@suse.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=julien.grall@arm.com \
    --cc=suravee.suthikulpanit@amd.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.