int guest_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val)
{
+ const struct domain *d = v->domain;
const struct cpuid_policy *cp = v->domain->arch.cpuid;
const struct msr_domain_policy *dp = v->domain->arch.msr;
const struct msr_vcpu_policy *vp = v->arch.msr;
_MSR_MISC_FEATURES_CPUID_FAULTING;
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;
+
/*
* TODO: Implement when we have better topology representation.
case MSR_INTEL_CORE_THREAD_COUNT:
case MSR_INTEL_CORE_THREAD_COUNT:
case MSR_INTEL_PLATFORM_INFO:
case MSR_ARCH_CAPABILITIES:
+ case MSR_IA32_PERF_STATUS:
/* Read-only */
case MSR_TSX_FORCE_ABORT:
case MSR_TSX_CTRL:
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;
+
default:
return X86EMUL_UNHANDLEABLE;
}
return val;
}
-static inline bool is_cpufreq_controller(const struct domain *d)
-{
- return ((cpufreq_controller == FREQCTL_dom0_kernel) &&
- is_hardware_domain(d));
-}
-
static int read_msr(unsigned int reg, uint64_t *val,
struct x86_emulate_ctxt *ctxt)
{
return X86EMUL_OKAY;
break;
- case MSR_IA32_PERF_CTL:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
- break;
- if ( likely(!is_cpufreq_controller(currd)) ||
- wrmsr_safe(reg, val) == 0 )
- return X86EMUL_OKAY;
- break;
-
case MSR_IA32_THERM_CONTROL:
case MSR_IA32_ENERGY_PERF_BIAS:
if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
FREQCTL_none, FREQCTL_dom0_kernel, FREQCTL_xen
} cpufreq_controller;
+static always_inline bool is_cpufreq_controller(const struct domain *d)
+{
+ /*
+ * A PV dom0 can be nominated as the cpufreq controller, instead of using
+ * Xen's cpufreq driver, at which point dom0 gets direct access to certain
+ * MSRs.
+ *
+ * This interface only works when dom0 is identity pinned and has the same
+ * number of vCPUs as pCPUs on the system.
+ *
+ * It would be far better to paravirtualise the interface.
+ */
+ return (is_pv_domain(d) && is_hardware_domain(d) &&
+ cpufreq_controller == FREQCTL_dom0_kernel);
+}
+
#define CPUPOOLID_NONE -1
struct cpupool *cpupool_get_by_id(int poolid);