summaryrefslogtreecommitdiff
path: root/xen/arch/x86/msr.c
diff options
context:
space:
mode:
authorRoger Pau Monné <roger.pau@citrix.com>2020-10-06 18:23:27 +0200
committerAndrew Cooper <andrew.cooper3@citrix.com>2020-11-10 11:20:14 +0000
commit3059178798a23ba870ff86ff54d442a07e6651fc (patch)
tree94f77e46acb0fbf852824db5adc38d296235c1a3 /xen/arch/x86/msr.c
parent0a5e0ce0fb7e5a3b5dfdc936058d2c0e04e5e258 (diff)
x86/msr: fix handling of MSR_IA32_PERF_{STATUS/CTL}
Currently a PV hardware domain can also be given control over the CPU frequency, and such guest is allowed to write to MSR_IA32_PERF_CTL. However since commit 322ec7c89f6 the default behavior has been changed to reject accesses to not explicitly handled MSRs, preventing PV guests that manage CPU frequency from reading MSR_IA32_PERF_{STATUS/CTL}. Additionally some HVM guests (Windows at least) will attempt to read MSR_IA32_PERF_CTL and will panic if given back a #GP fault: vmx.c:3035:d8v0 RDMSR 0x00000199 unimplemented d8v0 VIRIDIAN CRASH: 3b c0000096 fffff806871c1651 ffffda0253683720 0 Move the handling of MSR_IA32_PERF_{STATUS/CTL} to the common MSR handling shared between HVM and PV guests, and add an explicit case for reads to MSR_IA32_PERF_{STATUS/CTL}. Restore previous behavior and allow PV guests with the required permissions to read the contents of the mentioned MSRs. Non privileged guests will get 0 when trying to read those registers, as writes to MSR_IA32_PERF_CTL by such guest will already be silently dropped. Fixes: 322ec7c89f6 ('x86/pv: disallow access to unknown MSRs') Fixes: 84e848fd7a1 ('x86/hvm: disallow access to unknown MSRs') Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com>
Diffstat (limited to 'xen/arch/x86/msr.c')
-rw-r--r--xen/arch/x86/msr.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/xen/arch/x86/msr.c b/xen/arch/x86/msr.c
index 9c69ef8792..be8e363862 100644
--- a/xen/arch/x86/msr.c
+++ b/xen/arch/x86/msr.c
@@ -242,6 +242,25 @@ int guest_rdmsr(struct vcpu *v, uint32_t msr, uint64_t *val)
goto gp_fault;
break;
+ /*
+ * These MSRs are not enumerated in CPUID. They have been around
+ * since the Pentium 4, and implemented by other vendors.
+ *
+ * Some versions of Windows try reading these before setting up a #GP
+ * handler, and Linux has several unguarded reads as well. Provide
+ * RAZ semantics, in general, but permit a cpufreq controller dom0 to
+ * have full access.
+ */
+ case MSR_IA32_PERF_STATUS:
+ case MSR_IA32_PERF_CTL:
+ if ( !(cp->x86_vendor & (X86_VENDOR_INTEL | X86_VENDOR_CENTAUR)) )
+ goto gp_fault;
+
+ *val = 0;
+ if ( likely(!is_cpufreq_controller(d)) || rdmsr_safe(msr, *val) == 0 )
+ break;
+ goto gp_fault;
+
case MSR_IA32_THERM_STATUS:
if ( cp->x86_vendor != X86_VENDOR_INTEL )
goto gp_fault;
@@ -448,6 +467,21 @@ int guest_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val)
goto gp_fault;
break;
+ /*
+ * This MSR is not enumerated in CPUID. It has been around since the
+ * Pentium 4, and implemented by other vendors.
+ *
+ * To match the RAZ semantics, implement as write-discard, except for
+ * a cpufreq controller dom0 which has full access.
+ */
+ case MSR_IA32_PERF_CTL:
+ if ( !(cp->x86_vendor & (X86_VENDOR_INTEL | X86_VENDOR_CENTAUR)) )
+ goto gp_fault;
+
+ if ( likely(!is_cpufreq_controller(d)) || wrmsr_safe(msr, val) == 0 )
+ break;
+ goto gp_fault;
+
case MSR_X2APIC_FIRST ... MSR_X2APIC_LAST:
if ( !is_hvm_domain(d) || v != curr )
goto gp_fault;