All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ross Lagerwall <ross.lagerwall@citrix.com>
To: xen-devel@lists.xenproject.org
Cc: Sergey Dyasli <sergey.dyasli@citrix.com>,
	Kevin Tian <kevin.tian@intel.com>,
	Jun Nakajima <jun.nakajima@intel.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Ross Lagerwall <ross.lagerwall@citrix.com>,
	Jan Beulich <jbeulich@suse.com>
Subject: [PATCH v2] x86/vmx: Fix vmentry failure because of invalid LER on Broadwell
Date: Tue, 30 May 2017 15:05:04 +0100	[thread overview]
Message-ID: <20170530140504.22563-1-ross.lagerwall@citrix.com> (raw)

Occasionally, on certain Broadwell CPUs MSR_IA32_LASTINTTOIP has been
observed to have the top three bits corrupted as though the MSR is using
the LBR_FORMAT_EIP_FLAGS_TSX format. This is incorrect and causes a
vmentry failure -- the MSR should contain an offset into the current
code segment. This is assumed to be erratum BDF14. Workaround the issue
by sign-extending into bits 48:63 for MSR_IA32_LASTINT{FROM,TO}IP.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
---

Changes in v2:
- Use a single check if fixup is needed.
- Rename to include the erratum name/number.
- Sign extend properly rather than just the top three bits.

 xen/arch/x86/hvm/vmx/vmx.c         | 62 +++++++++++++++++++++++++++++++++++---
 xen/include/asm-x86/hvm/vmx/vmcs.h |  2 +-
 xen/include/asm-x86/x86_64/page.h  |  3 ++
 3 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index c8ef18a..9e1179a 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2434,6 +2434,7 @@ static void pi_notification_interrupt(struct cpu_user_regs *regs)
 }
 
 static void __init lbr_tsx_fixup_check(void);
+static void __init bdw_erratum_bdf14_fixup_check(void);
 
 const struct hvm_function_table * __init start_vmx(void)
 {
@@ -2499,6 +2500,7 @@ const struct hvm_function_table * __init start_vmx(void)
     setup_vmcs_dump();
 
     lbr_tsx_fixup_check();
+    bdw_erratum_bdf14_fixup_check();
 
     return &vmx_function_table;
 }
@@ -2791,7 +2793,11 @@ enum
 
 #define LBR_FROM_SIGNEXT_2MSB  ((1ULL << 59) | (1ULL << 60))
 
+#define FIXUP_LBR_TSX            (1 << 0)
+#define FIXUP_BDW_ERRATUM_BDF14  (1 << 1)
+
 static bool __read_mostly lbr_tsx_fixup_needed;
+static bool __read_mostly bdw_erratum_bdf14_fixup_needed;
 static uint32_t __read_mostly lbr_from_start;
 static uint32_t __read_mostly lbr_from_end;
 static uint32_t __read_mostly lbr_lastint_from;
@@ -2828,6 +2834,13 @@ static void __init lbr_tsx_fixup_check(void)
     }
 }
 
+static void __init bdw_erratum_bdf14_fixup_check(void)
+{
+    /* Broadwell E5-2600 v4 processors need to work around erratum BDF14. */
+    if ( boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 79 )
+        bdw_erratum_bdf14_fixup_needed = true;
+}
+
 static int is_last_branch_msr(u32 ecx)
 {
     const struct lbr_info *lbr = last_branch_msr_get();
@@ -3087,8 +3100,11 @@ static int vmx_msr_write_intercept(unsigned int msr, uint64_t msr_content)
                     if ( (rc = vmx_add_guest_msr(lbr->base + i)) == 0 )
                     {
                         vmx_disable_intercept_for_msr(v, lbr->base + i, MSR_TYPE_R | MSR_TYPE_W);
-                        v->arch.hvm_vmx.lbr_tsx_fixup_enabled =
-                            lbr_tsx_fixup_needed;
+                        if ( lbr_tsx_fixup_needed )
+                            v->arch.hvm_vmx.lbr_fixup_enabled |= FIXUP_LBR_TSX;
+                        if ( bdw_erratum_bdf14_fixup_needed )
+                            v->arch.hvm_vmx.lbr_fixup_enabled |=
+                                FIXUP_BDW_ERRATUM_BDF14;
                     }
         }
 
@@ -4174,6 +4190,44 @@ static void lbr_tsx_fixup(void)
         msr->data |= ((LBR_FROM_SIGNEXT_2MSB & msr->data) << 2);
 }
 
+static void sign_extend_msr(u32 msr, int type)
+{
+    struct vmx_msr_entry *entry;
+
+    if ( (entry = vmx_find_msr(msr, type)) != NULL )
+    {
+        if ( entry->data & VADDR_TOP_BIT )
+            entry->data |= CANONICAL_MASK;
+        else
+            entry->data &= ~CANONICAL_MASK;
+    }
+}
+
+static void bdw_erratum_bdf14_fixup(void)
+{
+    /*
+     * Occasionally, on certain Broadwell CPUs MSR_IA32_LASTINTTOIP has
+     * been observed to have the top three bits corrupted as though the
+     * MSR is using the LBR_FORMAT_EIP_FLAGS_TSX format. This is
+     * incorrect and causes a vmentry failure -- the MSR should contain
+     * an offset into the current code segment. This is assumed to be
+     * erratum BDF14. Fix up MSR_IA32_LASTINT{FROM,TO}IP by
+     * sign-extending into bits 48:63.
+     */
+    sign_extend_msr(MSR_IA32_LASTINTFROMIP, VMX_GUEST_MSR);
+    sign_extend_msr(MSR_IA32_LASTINTTOIP, VMX_GUEST_MSR);
+}
+
+static void lbr_fixup(void)
+{
+    struct vcpu *curr = current;
+
+    if ( curr->arch.hvm_vmx.lbr_fixup_enabled & FIXUP_LBR_TSX )
+        lbr_tsx_fixup();
+    if ( curr->arch.hvm_vmx.lbr_fixup_enabled & FIXUP_BDW_ERRATUM_BDF14 )
+        bdw_erratum_bdf14_fixup();
+}
+
 void vmx_vmenter_helper(const struct cpu_user_regs *regs)
 {
     struct vcpu *curr = current;
@@ -4230,8 +4284,8 @@ void vmx_vmenter_helper(const struct cpu_user_regs *regs)
     }
 
  out:
-    if ( unlikely(curr->arch.hvm_vmx.lbr_tsx_fixup_enabled) )
-        lbr_tsx_fixup();
+    if ( unlikely(curr->arch.hvm_vmx.lbr_fixup_enabled) )
+        lbr_fixup();
 
     HVMTRACE_ND(VMENTRY, 0, 1/*cycles*/, 0, 0, 0, 0, 0, 0, 0);
 
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h
index 9507bd2..e3cdfdf 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -136,7 +136,7 @@ struct arch_vmx_struct {
     /* Are we emulating rather than VMENTERing? */
     uint8_t              vmx_emulate;
 
-    bool                 lbr_tsx_fixup_enabled;
+    uint8_t              lbr_fixup_enabled;
 
     /* Bitmask of segments that we can't safely use in virtual 8086 mode */
     uint16_t             vm86_segment_mask;
diff --git a/xen/include/asm-x86/x86_64/page.h b/xen/include/asm-x86/x86_64/page.h
index 1a6cae6..d787724 100644
--- a/xen/include/asm-x86/x86_64/page.h
+++ b/xen/include/asm-x86/x86_64/page.h
@@ -28,6 +28,9 @@
 #define PADDR_MASK              ((1UL << PADDR_BITS)-1)
 #define VADDR_MASK              ((1UL << VADDR_BITS)-1)
 
+#define VADDR_TOP_BIT           (1UL << (VADDR_BITS - 1))
+#define CANONICAL_MASK          (~0UL & ~((1UL << VADDR_BITS) - 1))
+
 #define is_canonical_address(x) (((long)(x) >> 47) == ((long)(x) >> 63))
 
 #ifndef __ASSEMBLY__
-- 
2.9.4


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

             reply	other threads:[~2017-05-30 14:05 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-30 14:05 Ross Lagerwall [this message]
2017-05-30 14:17 ` [PATCH v2] x86/vmx: Fix vmentry failure because of invalid LER on Broadwell Andrew Cooper
2017-05-30 14:55 ` Jan Beulich
2017-06-01  2:08 ` Tian, Kevin

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=20170530140504.22563-1-ross.lagerwall@citrix.com \
    --to=ross.lagerwall@citrix.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=jbeulich@suse.com \
    --cc=jun.nakajima@intel.com \
    --cc=kevin.tian@intel.com \
    --cc=sergey.dyasli@citrix.com \
    --cc=xen-devel@lists.xenproject.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.