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

[xen staging] x86/pv: handle writes to the EFER MSR



commit feab5bddf771f04ec5e5fbe4c704db740e8401ab
Author:     Roger Pau Monne <roger.pau@xxxxxxxxxx>
AuthorDate: Mon Aug 17 17:57:52 2020 +0200
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Tue Aug 18 17:34:50 2020 +0100

    x86/pv: handle writes to the EFER MSR
    
    Silently drop writes to the EFER MSR for PV guests if the value is not
    changed from what it's being reported. Current PV Linux will attempt
    to write to the MSR with the same value that's been read, and raising
    a fault will result in a guest crash.
    
    As part of this work introduce a helper to easily get the EFER value
    reported to guests.
    
    Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
    Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/arch/x86/pv/emul-priv-op.c | 37 +++++++++++++++++++++++++++----------
 1 file changed, 27 insertions(+), 10 deletions(-)

diff --git a/xen/arch/x86/pv/emul-priv-op.c b/xen/arch/x86/pv/emul-priv-op.c
index efeb2a727e..d1d16b4806 100644
--- a/xen/arch/x86/pv/emul-priv-op.c
+++ b/xen/arch/x86/pv/emul-priv-op.c
@@ -837,6 +837,23 @@ static inline bool is_cpufreq_controller(const struct 
domain *d)
             is_hardware_domain(d));
 }
 
+static uint64_t guest_efer(const struct domain *d)
+{
+    uint64_t val;
+
+    /* Hide unknown bits, and unconditionally hide SVME from guests. */
+    val = read_efer() & EFER_KNOWN_MASK & ~EFER_SVME;
+    /*
+     * Hide the 64-bit features from 32-bit guests.  SCE has
+     * vendor-dependent behaviour.
+     */
+    if ( is_pv_32bit_domain(d) )
+        val &= ~(EFER_LME | EFER_LMA |
+                 (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
+                  ? EFER_SCE : 0));
+    return val;
+}
+
 static int read_msr(unsigned int reg, uint64_t *val,
                     struct x86_emulate_ctxt *ctxt)
 {
@@ -880,16 +897,7 @@ static int read_msr(unsigned int reg, uint64_t *val,
         return X86EMUL_OKAY;
 
     case MSR_EFER:
-        /* Hide unknown bits, and unconditionally hide SVME from guests. */
-        *val = read_efer() & EFER_KNOWN_MASK & ~EFER_SVME;
-        /*
-         * Hide the 64-bit features from 32-bit guests.  SCE has
-         * vendor-dependent behaviour.
-         */
-        if ( is_pv_32bit_domain(currd) )
-            *val &= ~(EFER_LME | EFER_LMA |
-                      (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
-                       ? EFER_SCE : 0));
+        *val = guest_efer(currd);
         return X86EMUL_OKAY;
 
     case MSR_K7_FID_VID_CTL:
@@ -1005,6 +1013,15 @@ static int write_msr(unsigned int reg, uint64_t val,
         curr->arch.pv.gs_base_user = val;
         return X86EMUL_OKAY;
 
+    case MSR_EFER:
+        /*
+         * Reject writes which change the value, but Linux depends on being
+         * able to write back the current value.
+         */
+        if ( val != guest_efer(currd) )
+            break;
+        return X86EMUL_OKAY;
+
     case MSR_K7_FID_VID_STATUS:
     case MSR_K7_FID_VID_CTL:
     case MSR_K8_PSTATE_LIMIT:
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

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