[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 3/4] x86: Allow non-faulting accesses to non-emulated MSRs if policy permits this


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
  • Date: Wed, 20 Jan 2021 17:49:11 -0500
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oracle.com; dmarc=pass action=none header.from=oracle.com; dkim=pass header.d=oracle.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=dCXkXSta+TTp5MqacSTXoq1rfECu1lT3kCVoJmd6hDA=; b=Uef6ywOxhlEpLqt+Ltva+/oA9tHDR3jAOQ4jmDLTXdpk3usN6wPUxWUkwT449r6v8UPMWXGK20/pBlWKIbWqBTSfKQFOZQuj+TKv5h5F2p7ikTuzcNLWEGCOifTjXWqVX1KsBSYJGVO23IXEMQoRsXgkM8Qh/d6DjgWfaHYa/A0cxqfMc1JxN23su40u25dKrJ8BE/guBYPiC5rPRDSwfnMFJDFuBpZFafJw/Ejn/o0YxM6+Ha7HOupSaf0HxleYCBPqllIHAdUJZe4vfg/dF9alzhoFGsR38mzTrYn/N6yoQyz5oSshE9KHZjHlirHLChHewbpTw8mt7D5cAJRpmg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hE2SOXghGeHsyNcoK1XZkmskvD7M8v5bXR9M0yRl47/lkfgoOYI9kDdOyGrDrxic7C4U+1+z8Fic39ujVCACXuTRH61le7W+vGfx94nVeJUgeCqgJenhiaygNytiInx0QlWpZScObtP8AzQ1fo2vyGHJb0HmwaApi5wVK4hwDvogzdtfQm2qZpN4lP9b29ZQgnt37nr1V3vpzzv6ywgzDuRMXnfFyYLGh6197IkejvJwKZPgIKUZgXMbwJf88gYZvBS6ry7tO+rU+lZuiccqBbrKYooVvHh2ci1yuHo3xAS0aLvBF6KrOxWvf/pe0awTXOT8QpFgTzDX93RwZA9blg==
  • Authentication-results: lists.xenproject.org; dkim=none (message not signed) header.d=none;lists.xenproject.org; dmarc=none action=none header.from=oracle.com;
  • Cc: iwj@xxxxxxxxxxxxxx, wl@xxxxxxx, anthony.perard@xxxxxxxxxx, jbeulich@xxxxxxxx, andrew.cooper3@xxxxxxxxxx, roger.pau@xxxxxxxxxx, jun.nakajima@xxxxxxxxx, kevin.tian@xxxxxxxxx, boris.ostrovsky@xxxxxxxxxx
  • Delivery-date: Wed, 20 Jan 2021 22:49:42 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Starting with commit 84e848fd7a16 ("x86/hvm: disallow access to unknown MSRs")
accesses to unhandled MSRs result in #GP sent to the guest. This caused a
regression for Solaris who tries to acccess MSR_RAPL_POWER_UNIT and (unlike,
for example, Linux) does not catch exceptions when accessing MSRs that
potentially may not be present.

Instead of special-casing RAPL registers we decide what to do when any
non-emulated MSR is accessed based on ignore_msrs field of msr_policy.

Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
---
Changes in v2:
* define x86_emul_guest_msr_access() and use it to determine whether emulated
  instruction is rd/wrmsr.
* Don't use ignore_msrs for MSR accesses that are not guest's rd/wrmsr.
* Clear @val for writes too in guest_unhandled_msr()

 xen/arch/x86/hvm/svm/svm.c             | 10 ++++------
 xen/arch/x86/hvm/vmx/vmx.c             | 10 ++++------
 xen/arch/x86/msr.c                     | 28 ++++++++++++++++++++++++++++
 xen/arch/x86/pv/emul-priv-op.c         | 10 ++++++----
 xen/arch/x86/x86_emulate/x86_emulate.h |  6 ++++++
 xen/include/asm-x86/msr.h              |  3 +++
 6 files changed, 51 insertions(+), 16 deletions(-)

diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index b819897a4a9f..7b59885b2619 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1965,8 +1965,8 @@ static int svm_msr_read_intercept(unsigned int msr, 
uint64_t *msr_content)
         break;
 
     default:
-        gdprintk(XENLOG_WARNING, "RDMSR 0x%08x unimplemented\n", msr);
-        goto gpf;
+        if ( guest_unhandled_msr(v, msr, msr_content, false, true) )
+            goto gpf;
     }
 
     HVM_DBG_LOG(DBG_LEVEL_MSR, "returns: ecx=%x, msr_value=%"PRIx64,
@@ -2151,10 +2151,8 @@ static int svm_msr_write_intercept(unsigned int msr, 
uint64_t msr_content)
         break;
 
     default:
-        gdprintk(XENLOG_WARNING,
-                 "WRMSR 0x%08x val 0x%016"PRIx64" unimplemented\n",
-                 msr, msr_content);
-        goto gpf;
+        if ( guest_unhandled_msr(v, msr, &msr_content, true, true) )
+            goto gpf;
     }
 
     return X86EMUL_OKAY;
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 2d4475ee3de2..87baca57d33f 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -3017,8 +3017,8 @@ static int vmx_msr_read_intercept(unsigned int msr, 
uint64_t *msr_content)
             break;
         }
 
-        gdprintk(XENLOG_WARNING, "RDMSR 0x%08x unimplemented\n", msr);
-        goto gp_fault;
+        if ( guest_unhandled_msr(curr, msr, msr_content, false, true) )
+            goto gp_fault;
     }
 
 done:
@@ -3319,10 +3319,8 @@ static int vmx_msr_write_intercept(unsigned int msr, 
uint64_t msr_content)
              is_last_branch_msr(msr) )
             break;
 
-        gdprintk(XENLOG_WARNING,
-                 "WRMSR 0x%08x val 0x%016"PRIx64" unimplemented\n",
-                 msr, msr_content);
-        goto gp_fault;
+        if ( guest_unhandled_msr(v, msr, &msr_content, true, true) )
+            goto gp_fault;
     }
 
     return X86EMUL_OKAY;
diff --git a/xen/arch/x86/msr.c b/xen/arch/x86/msr.c
index 433d16c80728..a57d838f642b 100644
--- a/xen/arch/x86/msr.c
+++ b/xen/arch/x86/msr.c
@@ -164,6 +164,34 @@ int init_vcpu_msr_policy(struct vcpu *v)
     return 0;
 }
 
+/* Returns true if policy requires #GP to the guest. */
+bool guest_unhandled_msr(const struct vcpu *v, uint32_t msr, uint64_t *val,
+                         bool is_write, bool is_guest_msr_access)
+{
+    u8 ignore_msrs = v->domain->arch.msr->ignore_msrs;
+
+    /*
+     * Accesses to unimplemented MSRs as part of emulation of instructions
+     * other than guest's RDMSR/WRMSR should never succeed.
+     */
+    if ( !is_guest_msr_access )
+        ignore_msrs = MSR_UNHANDLED_NEVER;
+
+    if ( unlikely(ignore_msrs != MSR_UNHANDLED_NEVER) )
+        *val = 0;
+
+    if ( likely(ignore_msrs != MSR_UNHANDLED_SILENT) )
+    {
+        if ( is_write )
+            gdprintk(XENLOG_WARNING, "WRMSR 0x%08x val 0x%016"PRIx64
+                    " unimplemented\n", msr, *val);
+        else
+            gdprintk(XENLOG_WARNING, "RDMSR 0x%08x unimplemented\n", msr);
+    }
+
+    return (ignore_msrs == MSR_UNHANDLED_NEVER);
+}
+
 int guest_rdmsr(struct vcpu *v, uint32_t msr, uint64_t *val)
 {
     const struct vcpu *curr = current;
diff --git a/xen/arch/x86/pv/emul-priv-op.c b/xen/arch/x86/pv/emul-priv-op.c
index dbceed8a05fd..6b378dbe2239 100644
--- a/xen/arch/x86/pv/emul-priv-op.c
+++ b/xen/arch/x86/pv/emul-priv-op.c
@@ -984,7 +984,9 @@ static int read_msr(unsigned int reg, uint64_t *val,
         }
         /* fall through */
     default:
-        gdprintk(XENLOG_WARNING, "RDMSR 0x%08x unimplemented\n", reg);
+        if ( !guest_unhandled_msr(curr, reg, val, false,
+                                  x86_emul_guest_msr_access(ctxt)) )
+            return X86EMUL_OKAY;
         break;
 
     normal:
@@ -1146,9 +1148,9 @@ static int write_msr(unsigned int reg, uint64_t val,
         }
         /* fall through */
     default:
-        gdprintk(XENLOG_WARNING,
-                 "WRMSR 0x%08x val 0x%016"PRIx64" unimplemented\n",
-                 reg, val);
+        if ( !guest_unhandled_msr(curr, reg, &val, true,
+                                  x86_emul_guest_msr_access(ctxt)) )
+            return X86EMUL_OKAY;
         break;
 
     invalid:
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h 
b/xen/arch/x86/x86_emulate/x86_emulate.h
index d8fb3a990933..06e6b7479f37 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.h
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h
@@ -850,4 +850,10 @@ static inline void x86_emul_reset_event(struct 
x86_emulate_ctxt *ctxt)
     ctxt->event = (struct x86_event){};
 }
 
+static inline bool x86_emul_guest_msr_access(struct x86_emulate_ctxt *ctxt)
+{
+    return ctxt->opcode == X86EMUL_OPC(0x0f, 0x32) ||  /* RDMSR */
+           ctxt->opcode == X86EMUL_OPC(0x0f, 0x30);    /* WRMSR */
+}
+
 #endif /* __X86_EMULATE_H__ */
diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h
index 16f95e734428..e7d69ad5bf29 100644
--- a/xen/include/asm-x86/msr.h
+++ b/xen/include/asm-x86/msr.h
@@ -345,5 +345,8 @@ int init_vcpu_msr_policy(struct vcpu *v);
  */
 int guest_rdmsr(struct vcpu *v, uint32_t msr, uint64_t *val);
 int guest_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val);
+bool guest_unhandled_msr(const struct vcpu *v, uint32_t msr,
+                         uint64_t *val, bool is_write,
+                         bool is_guest_msr_access);
 
 #endif /* __ASM_MSR_H */
-- 
1.8.3.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.