From: "Jan Beulich" <JBeulich@suse.com>
To: xen-devel <xen-devel@lists.xenproject.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: [PATCH 13/17] x86/PV: split out dealing with MSRs from privileged instruction handling
Date: Thu, 08 Sep 2016 07:18:08 -0600 [thread overview]
Message-ID: <57D18130020000780010D1DA@prv-mh.provo.novell.com> (raw)
In-Reply-To: <57D17C78020000780010D127@prv-mh.provo.novell.com>
[-- Attachment #1: Type: text/plain, Size: 25181 bytes --]
This is in preparation for using the generic emulator here.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -2373,6 +2373,332 @@ static inline uint64_t guest_misc_enable
return val;
}
+static inline bool is_cpufreq_controller(const struct domain *d)
+{
+ return ((cpufreq_controller == FREQCTL_dom0_kernel) &&
+ is_hardware_domain(d));
+}
+
+static int priv_op_read_msr(unsigned int reg, uint64_t *val,
+ struct x86_emulate_ctxt *ctxt)
+{
+ const struct vcpu *curr = current;
+ const struct domain *currd = curr->domain;
+ bool vpmu_msr = false;
+
+ switch ( reg )
+ {
+ int rc;
+
+ case MSR_FS_BASE:
+ if ( is_pv_32bit_domain(currd) )
+ break;
+ *val = cpu_has_fsgsbase ? __rdfsbase() : curr->arch.pv_vcpu.fs_base;
+ return X86EMUL_OKAY;
+
+ case MSR_GS_BASE:
+ if ( is_pv_32bit_domain(currd) )
+ break;
+ *val = cpu_has_fsgsbase ? __rdgsbase()
+ : curr->arch.pv_vcpu.gs_base_kernel;
+ return X86EMUL_OKAY;
+
+ case MSR_SHADOW_GS_BASE:
+ if ( is_pv_32bit_domain(currd) )
+ break;
+ *val = curr->arch.pv_vcpu.gs_base_user;
+ return X86EMUL_OKAY;
+
+ case MSR_K7_FID_VID_CTL:
+ case MSR_K7_FID_VID_STATUS:
+ case MSR_K8_PSTATE_LIMIT:
+ case MSR_K8_PSTATE_CTRL:
+ case MSR_K8_PSTATE_STATUS:
+ case MSR_K8_PSTATE0:
+ case MSR_K8_PSTATE1:
+ case MSR_K8_PSTATE2:
+ case MSR_K8_PSTATE3:
+ case MSR_K8_PSTATE4:
+ case MSR_K8_PSTATE5:
+ case MSR_K8_PSTATE6:
+ case MSR_K8_PSTATE7:
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
+ break;
+ if ( unlikely(is_cpufreq_controller(currd)) )
+ goto normal;
+ *val = 0;
+ return X86EMUL_OKAY;
+
+ case MSR_IA32_UCODE_REV:
+ BUILD_BUG_ON(MSR_IA32_UCODE_REV != MSR_AMD_PATCHLEVEL);
+ if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+ {
+ if ( wrmsr_safe(MSR_IA32_UCODE_REV, 0) )
+ break;
+ sync_core();
+ }
+ goto normal;
+
+ case MSR_IA32_MISC_ENABLE:
+ if ( rdmsr_safe(reg, *val) )
+ break;
+ *val = guest_misc_enable(*val);
+ return X86EMUL_OKAY;
+
+ case MSR_AMD64_DR0_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
+ break;
+ *val = curr->arch.pv_vcpu.dr_mask[0];
+ return X86EMUL_OKAY;
+
+ case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
+ break;
+ *val = curr->arch.pv_vcpu.dr_mask[reg - MSR_AMD64_DR1_ADDRESS_MASK + 1];
+ return X86EMUL_OKAY;
+
+ case MSR_IA32_PERF_CAPABILITIES:
+ /* No extra capabilities are supported. */
+ *val = 0;
+ return X86EMUL_OKAY;
+
+ case MSR_P6_PERFCTR(0)...MSR_P6_PERFCTR(7):
+ case MSR_P6_EVNTSEL(0)...MSR_P6_EVNTSEL(3):
+ case MSR_CORE_PERF_FIXED_CTR0...MSR_CORE_PERF_FIXED_CTR2:
+ case MSR_CORE_PERF_FIXED_CTR_CTRL...MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+ if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+ {
+ vpmu_msr = true;
+ /* fall through */
+ case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5:
+ case MSR_K7_EVNTSEL0...MSR_K7_PERFCTR3:
+ if ( vpmu_msr || (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) )
+ {
+ /* Don't leak PMU MSRs to unprivileged domains. */
+ if ( (vpmu_mode & XENPMU_MODE_ALL) &&
+ !is_hardware_domain(currd) )
+ *val = 0;
+ else if ( vpmu_do_rdmsr(reg, val) )
+ break;
+ return X86EMUL_OKAY;
+ }
+ }
+ /* fall through */
+ default:
+ if ( rdmsr_hypervisor_regs(reg, val) )
+ return X86EMUL_OKAY;
+
+ rc = vmce_rdmsr(reg, val);
+ if ( rc < 0 )
+ break;
+ if ( rc )
+ return X86EMUL_OKAY;
+ /* fall through */
+ case MSR_EFER:
+ normal:
+ /* Everyone can read the MSR space. */
+ /* gdprintk(XENLOG_WARNING, "Domain attempted RDMSR %08x\n", reg); */
+ if ( rdmsr_safe(reg, *val) )
+ break;
+ return X86EMUL_OKAY;
+ }
+
+ return X86EMUL_UNHANDLEABLE;
+}
+
+#include "x86_64/mmconfig.h"
+
+static int priv_op_write_msr(unsigned int reg, uint64_t val,
+ struct x86_emulate_ctxt *ctxt)
+{
+ struct vcpu *curr = current;
+ const struct domain *currd = curr->domain;
+ bool vpmu_msr = false;
+
+ switch ( reg )
+ {
+ uint64_t temp;
+ int rc;
+
+ case MSR_FS_BASE:
+ if ( is_pv_32bit_domain(currd) )
+ break;
+ wrfsbase(val);
+ curr->arch.pv_vcpu.fs_base = val;
+ return X86EMUL_OKAY;
+
+ case MSR_GS_BASE:
+ if ( is_pv_32bit_domain(currd) )
+ break;
+ wrgsbase(val);
+ curr->arch.pv_vcpu.gs_base_kernel = val;
+ return X86EMUL_OKAY;
+
+ case MSR_SHADOW_GS_BASE:
+ if ( is_pv_32bit_domain(currd) ||
+ wrmsr_safe(MSR_SHADOW_GS_BASE, val) )
+ break;
+ curr->arch.pv_vcpu.gs_base_user = val;
+ return X86EMUL_OKAY;
+
+ case MSR_K7_FID_VID_STATUS:
+ case MSR_K7_FID_VID_CTL:
+ case MSR_K8_PSTATE_LIMIT:
+ case MSR_K8_PSTATE_CTRL:
+ case MSR_K8_PSTATE_STATUS:
+ case MSR_K8_PSTATE0:
+ case MSR_K8_PSTATE1:
+ case MSR_K8_PSTATE2:
+ case MSR_K8_PSTATE3:
+ case MSR_K8_PSTATE4:
+ case MSR_K8_PSTATE5:
+ case MSR_K8_PSTATE6:
+ case MSR_K8_PSTATE7:
+ case MSR_K8_HWCR:
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
+ break;
+ if ( likely(!is_cpufreq_controller(currd)) ||
+ wrmsr_safe(reg, val) == 0 )
+ return X86EMUL_OKAY;
+ break;
+
+ case MSR_AMD64_NB_CFG:
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ||
+ boot_cpu_data.x86 < 0x10 || boot_cpu_data.x86 > 0x17 )
+ break;
+ if ( !is_hardware_domain(currd) || !is_pinned_vcpu(curr) )
+ return X86EMUL_OKAY;
+ if ( (rdmsr_safe(MSR_AMD64_NB_CFG, temp) != 0) ||
+ ((val ^ temp) & ~(1ULL << AMD64_NB_CFG_CF8_EXT_ENABLE_BIT)) )
+ goto invalid;
+ if ( wrmsr_safe(MSR_AMD64_NB_CFG, val) == 0 )
+ return X86EMUL_OKAY;
+ break;
+
+ case MSR_FAM10H_MMIO_CONF_BASE:
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ||
+ boot_cpu_data.x86 < 0x10 || boot_cpu_data.x86 > 0x17 )
+ break;
+ if ( !is_hardware_domain(currd) || !is_pinned_vcpu(curr) )
+ return X86EMUL_OKAY;
+ if ( rdmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, temp) != 0 )
+ break;
+ if ( (pci_probe & PCI_PROBE_MASK) == PCI_PROBE_MMCONF ?
+ temp != val :
+ ((temp ^ val) &
+ ~(FAM10H_MMIO_CONF_ENABLE |
+ (FAM10H_MMIO_CONF_BUSRANGE_MASK <<
+ FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
+ ((u64)FAM10H_MMIO_CONF_BASE_MASK <<
+ FAM10H_MMIO_CONF_BASE_SHIFT))) )
+ goto invalid;
+ if ( wrmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, val) == 0 )
+ return X86EMUL_OKAY;
+ break;
+
+ case MSR_IA32_UCODE_REV:
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
+ break;
+ if ( !is_hardware_domain(currd) || !is_pinned_vcpu(curr) )
+ return X86EMUL_OKAY;
+ if ( rdmsr_safe(reg, temp) )
+ break;
+ if ( val )
+ goto invalid;
+ return X86EMUL_OKAY;
+
+ case MSR_IA32_MISC_ENABLE:
+ if ( rdmsr_safe(reg, temp) )
+ break;
+ if ( val != guest_misc_enable(temp) )
+ goto invalid;
+ return X86EMUL_OKAY;
+
+ case MSR_IA32_MPERF:
+ case MSR_IA32_APERF:
+ if ( (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) &&
+ (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) )
+ break;
+ if ( likely(!is_cpufreq_controller(currd)) ||
+ wrmsr_safe(reg, val) == 0 )
+ 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 )
+ break;
+ if ( !is_hardware_domain(currd) || !is_pinned_vcpu(curr) ||
+ wrmsr_safe(reg, val) == 0 )
+ return X86EMUL_OKAY;
+ break;
+
+ case MSR_AMD64_DR0_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) || (val >> 32) )
+ break;
+ curr->arch.pv_vcpu.dr_mask[0] = val;
+ if ( curr->arch.debugreg[7] & DR7_ACTIVE_MASK )
+ wrmsrl(MSR_AMD64_DR0_ADDRESS_MASK, val);
+ return X86EMUL_OKAY;
+
+ case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) || (val >> 32) )
+ break;
+ curr->arch.pv_vcpu.dr_mask[reg - MSR_AMD64_DR1_ADDRESS_MASK + 1] = val;
+ if ( curr->arch.debugreg[7] & DR7_ACTIVE_MASK )
+ wrmsrl(reg, val);
+ return X86EMUL_OKAY;
+
+ case MSR_P6_PERFCTR(0)...MSR_P6_PERFCTR(7):
+ case MSR_P6_EVNTSEL(0)...MSR_P6_EVNTSEL(3):
+ case MSR_CORE_PERF_FIXED_CTR0...MSR_CORE_PERF_FIXED_CTR2:
+ case MSR_CORE_PERF_FIXED_CTR_CTRL...MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+ if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+ {
+ vpmu_msr = true;
+ case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5:
+ case MSR_K7_EVNTSEL0...MSR_K7_PERFCTR3:
+ if ( vpmu_msr || (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) )
+ {
+ if ( (vpmu_mode & XENPMU_MODE_ALL) &&
+ !is_hardware_domain(currd) )
+ return X86EMUL_OKAY;
+
+ if ( vpmu_do_wrmsr(reg, val, 0) )
+ break;
+ return X86EMUL_OKAY;
+ }
+ }
+ /* fall through */
+ default:
+ if ( wrmsr_hypervisor_regs(reg, val) == 1 )
+ return X86EMUL_OKAY;
+
+ rc = vmce_wrmsr(reg, val);
+ if ( rc < 0 )
+ break;
+ if ( rc )
+ return X86EMUL_OKAY;
+
+ if ( (rdmsr_safe(reg, temp) != 0) || (val != temp) )
+ invalid:
+ gdprintk(XENLOG_WARNING,
+ "Domain attempted WRMSR %08x from 0x%016"PRIx64" to 0x%016"PRIx64"\n",
+ reg, temp, val);
+ return X86EMUL_OKAY;
+ }
+
+ return X86EMUL_UNHANDLEABLE;
+}
+
/* Instruction fetch with error handling. */
#define insn_fetch(type, base, eip, limit) \
({ unsigned long _rc, _ptr = (base) + (eip); \
@@ -2388,14 +2714,6 @@ static inline uint64_t guest_misc_enable
} \
(eip) += sizeof(_x); _x; })
-static int is_cpufreq_controller(struct domain *d)
-{
- return ((cpufreq_controller == FREQCTL_dom0_kernel) &&
- is_hardware_domain(d));
-}
-
-#include "x86_64/mmconfig.h"
-
static int emulate_privileged_op(struct cpu_user_regs *regs)
{
struct vcpu *v = current;
@@ -2420,7 +2738,6 @@ static int emulate_privileged_op(struct
char *io_emul_stub = NULL;
void (*io_emul)(struct cpu_user_regs *);
uint64_t val;
- bool_t vpmu_msr;
if ( !read_descriptor(regs->cs, v, &code_base, &code_limit, &ar, 1) )
goto fail;
@@ -2821,188 +3138,11 @@ static int emulate_privileged_op(struct
goto fail;
break;
- case 0x30: /* WRMSR */ {
- uint32_t eax = regs->eax;
- uint32_t edx = regs->edx;
- uint64_t msr_content = ((uint64_t)edx << 32) | eax;
- vpmu_msr = 0;
- switch ( regs->_ecx )
- {
- case MSR_FS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- wrfsbase(msr_content);
- v->arch.pv_vcpu.fs_base = msr_content;
- break;
- case MSR_GS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- wrgsbase(msr_content);
- v->arch.pv_vcpu.gs_base_kernel = msr_content;
- break;
- case MSR_SHADOW_GS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- if ( wrmsr_safe(MSR_SHADOW_GS_BASE, msr_content) )
- goto fail;
- v->arch.pv_vcpu.gs_base_user = msr_content;
- break;
- case MSR_K7_FID_VID_STATUS:
- case MSR_K7_FID_VID_CTL:
- case MSR_K8_PSTATE_LIMIT:
- case MSR_K8_PSTATE_CTRL:
- case MSR_K8_PSTATE_STATUS:
- case MSR_K8_PSTATE0:
- case MSR_K8_PSTATE1:
- case MSR_K8_PSTATE2:
- case MSR_K8_PSTATE3:
- case MSR_K8_PSTATE4:
- case MSR_K8_PSTATE5:
- case MSR_K8_PSTATE6:
- case MSR_K8_PSTATE7:
- case MSR_K8_HWCR:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
- goto fail;
- if ( !is_cpufreq_controller(currd) )
- break;
- if ( wrmsr_safe(regs->ecx, msr_content) != 0 )
- goto fail;
- break;
- case MSR_AMD64_NB_CFG:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ||
- boot_cpu_data.x86 < 0x10 || boot_cpu_data.x86 > 0x17 )
- goto fail;
- if ( !is_hardware_domain(currd) || !is_pinned_vcpu(v) )
- break;
- if ( (rdmsr_safe(MSR_AMD64_NB_CFG, val) != 0) ||
- (eax != (uint32_t)val) ||
- ((edx ^ (val >> 32)) & ~(1 << (AMD64_NB_CFG_CF8_EXT_ENABLE_BIT - 32))) )
- goto invalid;
- if ( wrmsr_safe(MSR_AMD64_NB_CFG, msr_content) != 0 )
- goto fail;
- break;
- case MSR_FAM10H_MMIO_CONF_BASE:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ||
- boot_cpu_data.x86 < 0x10 || boot_cpu_data.x86 > 0x17 )
- goto fail;
- if ( !is_hardware_domain(currd) || !is_pinned_vcpu(v) )
- break;
- if ( (rdmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, val) != 0) )
- goto fail;
- if (
- (pci_probe & PCI_PROBE_MASK) == PCI_PROBE_MMCONF ?
- val != msr_content :
- ((val ^ msr_content) &
- ~( FAM10H_MMIO_CONF_ENABLE |
- (FAM10H_MMIO_CONF_BUSRANGE_MASK <<
- FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
- ((u64)FAM10H_MMIO_CONF_BASE_MASK <<
- FAM10H_MMIO_CONF_BASE_SHIFT))) )
- goto invalid;
- if ( wrmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, msr_content) != 0 )
- goto fail;
- break;
- case MSR_IA32_UCODE_REV:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
- goto fail;
- if ( !is_hardware_domain(currd) || !is_pinned_vcpu(v) )
- break;
- if ( rdmsr_safe(regs->ecx, val) )
- goto fail;
- if ( msr_content )
- goto invalid;
- break;
- case MSR_IA32_MISC_ENABLE:
- if ( rdmsr_safe(regs->ecx, val) )
- goto fail;
- val = guest_misc_enable(val);
- if ( msr_content != val )
- goto invalid;
- break;
- case MSR_IA32_MPERF:
- case MSR_IA32_APERF:
- if (( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ) &&
- ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ) )
- goto fail;
- if ( !is_cpufreq_controller(currd) )
- break;
- if ( wrmsr_safe(regs->ecx, msr_content ) != 0 )
- goto fail;
- break;
- case MSR_IA32_PERF_CTL:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
- goto fail;
- if ( !is_cpufreq_controller(currd) )
- break;
- if ( wrmsr_safe(regs->ecx, msr_content) != 0 )
- goto fail;
- break;
- case MSR_IA32_THERM_CONTROL:
- case MSR_IA32_ENERGY_PERF_BIAS:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
- goto fail;
- if ( !is_hardware_domain(currd) || !is_pinned_vcpu(v) )
- break;
- if ( wrmsr_safe(regs->ecx, msr_content) != 0 )
- goto fail;
- break;
-
- case MSR_AMD64_DR0_ADDRESS_MASK:
- if ( !boot_cpu_has(X86_FEATURE_DBEXT) || (msr_content >> 32) )
- goto fail;
- v->arch.pv_vcpu.dr_mask[0] = msr_content;
- if ( v->arch.debugreg[7] & DR7_ACTIVE_MASK )
- wrmsrl(MSR_AMD64_DR0_ADDRESS_MASK, msr_content);
- break;
- case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
- if ( !boot_cpu_has(X86_FEATURE_DBEXT) || (msr_content >> 32) )
- goto fail;
- v->arch.pv_vcpu.dr_mask
- [regs->_ecx - MSR_AMD64_DR1_ADDRESS_MASK + 1] = msr_content;
- if ( v->arch.debugreg[7] & DR7_ACTIVE_MASK )
- wrmsrl(regs->_ecx, msr_content);
- break;
- case MSR_P6_PERFCTR(0)...MSR_P6_PERFCTR(7):
- case MSR_P6_EVNTSEL(0)...MSR_P6_EVNTSEL(3):
- case MSR_CORE_PERF_FIXED_CTR0...MSR_CORE_PERF_FIXED_CTR2:
- case MSR_CORE_PERF_FIXED_CTR_CTRL...MSR_CORE_PERF_GLOBAL_OVF_CTRL:
- if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
- {
- vpmu_msr = 1;
- case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5:
- case MSR_K7_EVNTSEL0...MSR_K7_PERFCTR3:
- if ( vpmu_msr || (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) )
- {
- if ( (vpmu_mode & XENPMU_MODE_ALL) &&
- !is_hardware_domain(v->domain) )
- break;
-
- if ( vpmu_do_wrmsr(regs->ecx, msr_content, 0) )
- goto fail;
- break;
- }
- }
- /*FALLTHROUGH*/
-
- default:
- if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) == 1 )
- break;
-
- rc = vmce_wrmsr(regs->ecx, msr_content);
- if ( rc < 0 )
- goto fail;
- if ( rc )
- break;
-
- if ( (rdmsr_safe(regs->ecx, val) != 0) || (msr_content != val) )
- invalid:
- gdprintk(XENLOG_WARNING, "Domain attempted WRMSR %p from "
- "0x%016"PRIx64" to 0x%016"PRIx64".\n",
- _p(regs->ecx), val, msr_content);
- break;
- }
+ case 0x30: /* WRMSR */
+ if ( priv_op_write_msr(regs->_ecx, (regs->rdx << 32) | regs->_eax,
+ NULL) != X86EMUL_OKAY )
+ goto fail;
break;
- }
case 0x31: /* RDTSC */
if ( (v->arch.pv_vcpu.ctrlreg[4] & X86_CR4_TSD) &&
@@ -3018,130 +3158,11 @@ static int emulate_privileged_op(struct
break;
case 0x32: /* RDMSR */
- vpmu_msr = 0;
- switch ( regs->_ecx )
- {
- case MSR_FS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- val = cpu_has_fsgsbase ? __rdfsbase() : v->arch.pv_vcpu.fs_base;
- goto rdmsr_writeback;
- case MSR_GS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- val = cpu_has_fsgsbase ? __rdgsbase()
- : v->arch.pv_vcpu.gs_base_kernel;
- goto rdmsr_writeback;
- case MSR_SHADOW_GS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- val = v->arch.pv_vcpu.gs_base_user;
- goto rdmsr_writeback;
- case MSR_K7_FID_VID_CTL:
- case MSR_K7_FID_VID_STATUS:
- case MSR_K8_PSTATE_LIMIT:
- case MSR_K8_PSTATE_CTRL:
- case MSR_K8_PSTATE_STATUS:
- case MSR_K8_PSTATE0:
- case MSR_K8_PSTATE1:
- case MSR_K8_PSTATE2:
- case MSR_K8_PSTATE3:
- case MSR_K8_PSTATE4:
- case MSR_K8_PSTATE5:
- case MSR_K8_PSTATE6:
- case MSR_K8_PSTATE7:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
- goto fail;
- if ( !is_cpufreq_controller(currd) )
- {
- regs->eax = regs->edx = 0;
- break;
- }
- goto rdmsr_normal;
- case MSR_IA32_UCODE_REV:
- BUILD_BUG_ON(MSR_IA32_UCODE_REV != MSR_AMD_PATCHLEVEL);
- if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
- {
- if ( wrmsr_safe(MSR_IA32_UCODE_REV, 0) )
- goto fail;
- sync_core();
- }
- goto rdmsr_normal;
- case MSR_IA32_MISC_ENABLE:
- if ( rdmsr_safe(regs->ecx, val) )
- goto fail;
- val = guest_misc_enable(val);
- goto rdmsr_writeback;
-
- case MSR_AMD64_DR0_ADDRESS_MASK:
- if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
- goto fail;
- regs->eax = v->arch.pv_vcpu.dr_mask[0];
- regs->edx = 0;
- break;
- case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
- if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
- goto fail;
- regs->eax = v->arch.pv_vcpu.dr_mask
- [regs->_ecx - MSR_AMD64_DR1_ADDRESS_MASK + 1];
- regs->edx = 0;
- break;
- case MSR_IA32_PERF_CAPABILITIES:
- /* No extra capabilities are supported */
- regs->eax = regs->edx = 0;
- break;
- case MSR_P6_PERFCTR(0)...MSR_P6_PERFCTR(7):
- case MSR_P6_EVNTSEL(0)...MSR_P6_EVNTSEL(3):
- case MSR_CORE_PERF_FIXED_CTR0...MSR_CORE_PERF_FIXED_CTR2:
- case MSR_CORE_PERF_FIXED_CTR_CTRL...MSR_CORE_PERF_GLOBAL_OVF_CTRL:
- if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
- {
- vpmu_msr = 1;
- case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5:
- case MSR_K7_EVNTSEL0...MSR_K7_PERFCTR3:
- if ( vpmu_msr || (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) )
- {
-
- if ( (vpmu_mode & XENPMU_MODE_ALL) &&
- !is_hardware_domain(v->domain) )
- {
- /* Don't leak PMU MSRs to unprivileged domains */
- regs->eax = regs->edx = 0;
- break;
- }
-
- if ( vpmu_do_rdmsr(regs->ecx, &val) )
- goto fail;
-
- regs->eax = (uint32_t)val;
- regs->edx = (uint32_t)(val >> 32);
- break;
- }
- }
- /*FALLTHROUGH*/
-
- default:
- if ( rdmsr_hypervisor_regs(regs->ecx, &val) )
- goto rdmsr_writeback;
-
- rc = vmce_rdmsr(regs->ecx, &val);
- if ( rc < 0 )
- goto fail;
- if ( rc )
- goto rdmsr_writeback;
-
- case MSR_EFER:
- rdmsr_normal:
- /* Everyone can read the MSR space. */
- /* gdprintk(XENLOG_WARNING,"Domain attempted RDMSR %p.\n",
- _p(regs->ecx));*/
- if ( rdmsr_safe(regs->ecx, val) )
- goto fail;
+ if ( priv_op_read_msr(regs->_ecx, &val, NULL) != X86EMUL_OKAY )
+ goto fail;
rdmsr_writeback:
- regs->eax = (uint32_t)val;
- regs->edx = (uint32_t)(val >> 32);
- break;
- }
+ regs->eax = (uint32_t)val;
+ regs->edx = (uint32_t)(val >> 32);
break;
case 0xa2: /* CPUID */
[-- Attachment #2: x86-PV-priv-op-split-MSR.patch --]
[-- Type: text/plain, Size: 25253 bytes --]
x86/PV: split out dealing with MSRs from privileged instruction handling
This is in preparation for using the generic emulator here.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -2373,6 +2373,332 @@ static inline uint64_t guest_misc_enable
return val;
}
+static inline bool is_cpufreq_controller(const struct domain *d)
+{
+ return ((cpufreq_controller == FREQCTL_dom0_kernel) &&
+ is_hardware_domain(d));
+}
+
+static int priv_op_read_msr(unsigned int reg, uint64_t *val,
+ struct x86_emulate_ctxt *ctxt)
+{
+ const struct vcpu *curr = current;
+ const struct domain *currd = curr->domain;
+ bool vpmu_msr = false;
+
+ switch ( reg )
+ {
+ int rc;
+
+ case MSR_FS_BASE:
+ if ( is_pv_32bit_domain(currd) )
+ break;
+ *val = cpu_has_fsgsbase ? __rdfsbase() : curr->arch.pv_vcpu.fs_base;
+ return X86EMUL_OKAY;
+
+ case MSR_GS_BASE:
+ if ( is_pv_32bit_domain(currd) )
+ break;
+ *val = cpu_has_fsgsbase ? __rdgsbase()
+ : curr->arch.pv_vcpu.gs_base_kernel;
+ return X86EMUL_OKAY;
+
+ case MSR_SHADOW_GS_BASE:
+ if ( is_pv_32bit_domain(currd) )
+ break;
+ *val = curr->arch.pv_vcpu.gs_base_user;
+ return X86EMUL_OKAY;
+
+ case MSR_K7_FID_VID_CTL:
+ case MSR_K7_FID_VID_STATUS:
+ case MSR_K8_PSTATE_LIMIT:
+ case MSR_K8_PSTATE_CTRL:
+ case MSR_K8_PSTATE_STATUS:
+ case MSR_K8_PSTATE0:
+ case MSR_K8_PSTATE1:
+ case MSR_K8_PSTATE2:
+ case MSR_K8_PSTATE3:
+ case MSR_K8_PSTATE4:
+ case MSR_K8_PSTATE5:
+ case MSR_K8_PSTATE6:
+ case MSR_K8_PSTATE7:
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
+ break;
+ if ( unlikely(is_cpufreq_controller(currd)) )
+ goto normal;
+ *val = 0;
+ return X86EMUL_OKAY;
+
+ case MSR_IA32_UCODE_REV:
+ BUILD_BUG_ON(MSR_IA32_UCODE_REV != MSR_AMD_PATCHLEVEL);
+ if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+ {
+ if ( wrmsr_safe(MSR_IA32_UCODE_REV, 0) )
+ break;
+ sync_core();
+ }
+ goto normal;
+
+ case MSR_IA32_MISC_ENABLE:
+ if ( rdmsr_safe(reg, *val) )
+ break;
+ *val = guest_misc_enable(*val);
+ return X86EMUL_OKAY;
+
+ case MSR_AMD64_DR0_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
+ break;
+ *val = curr->arch.pv_vcpu.dr_mask[0];
+ return X86EMUL_OKAY;
+
+ case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
+ break;
+ *val = curr->arch.pv_vcpu.dr_mask[reg - MSR_AMD64_DR1_ADDRESS_MASK + 1];
+ return X86EMUL_OKAY;
+
+ case MSR_IA32_PERF_CAPABILITIES:
+ /* No extra capabilities are supported. */
+ *val = 0;
+ return X86EMUL_OKAY;
+
+ case MSR_P6_PERFCTR(0)...MSR_P6_PERFCTR(7):
+ case MSR_P6_EVNTSEL(0)...MSR_P6_EVNTSEL(3):
+ case MSR_CORE_PERF_FIXED_CTR0...MSR_CORE_PERF_FIXED_CTR2:
+ case MSR_CORE_PERF_FIXED_CTR_CTRL...MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+ if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+ {
+ vpmu_msr = true;
+ /* fall through */
+ case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5:
+ case MSR_K7_EVNTSEL0...MSR_K7_PERFCTR3:
+ if ( vpmu_msr || (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) )
+ {
+ /* Don't leak PMU MSRs to unprivileged domains. */
+ if ( (vpmu_mode & XENPMU_MODE_ALL) &&
+ !is_hardware_domain(currd) )
+ *val = 0;
+ else if ( vpmu_do_rdmsr(reg, val) )
+ break;
+ return X86EMUL_OKAY;
+ }
+ }
+ /* fall through */
+ default:
+ if ( rdmsr_hypervisor_regs(reg, val) )
+ return X86EMUL_OKAY;
+
+ rc = vmce_rdmsr(reg, val);
+ if ( rc < 0 )
+ break;
+ if ( rc )
+ return X86EMUL_OKAY;
+ /* fall through */
+ case MSR_EFER:
+ normal:
+ /* Everyone can read the MSR space. */
+ /* gdprintk(XENLOG_WARNING, "Domain attempted RDMSR %08x\n", reg); */
+ if ( rdmsr_safe(reg, *val) )
+ break;
+ return X86EMUL_OKAY;
+ }
+
+ return X86EMUL_UNHANDLEABLE;
+}
+
+#include "x86_64/mmconfig.h"
+
+static int priv_op_write_msr(unsigned int reg, uint64_t val,
+ struct x86_emulate_ctxt *ctxt)
+{
+ struct vcpu *curr = current;
+ const struct domain *currd = curr->domain;
+ bool vpmu_msr = false;
+
+ switch ( reg )
+ {
+ uint64_t temp;
+ int rc;
+
+ case MSR_FS_BASE:
+ if ( is_pv_32bit_domain(currd) )
+ break;
+ wrfsbase(val);
+ curr->arch.pv_vcpu.fs_base = val;
+ return X86EMUL_OKAY;
+
+ case MSR_GS_BASE:
+ if ( is_pv_32bit_domain(currd) )
+ break;
+ wrgsbase(val);
+ curr->arch.pv_vcpu.gs_base_kernel = val;
+ return X86EMUL_OKAY;
+
+ case MSR_SHADOW_GS_BASE:
+ if ( is_pv_32bit_domain(currd) ||
+ wrmsr_safe(MSR_SHADOW_GS_BASE, val) )
+ break;
+ curr->arch.pv_vcpu.gs_base_user = val;
+ return X86EMUL_OKAY;
+
+ case MSR_K7_FID_VID_STATUS:
+ case MSR_K7_FID_VID_CTL:
+ case MSR_K8_PSTATE_LIMIT:
+ case MSR_K8_PSTATE_CTRL:
+ case MSR_K8_PSTATE_STATUS:
+ case MSR_K8_PSTATE0:
+ case MSR_K8_PSTATE1:
+ case MSR_K8_PSTATE2:
+ case MSR_K8_PSTATE3:
+ case MSR_K8_PSTATE4:
+ case MSR_K8_PSTATE5:
+ case MSR_K8_PSTATE6:
+ case MSR_K8_PSTATE7:
+ case MSR_K8_HWCR:
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
+ break;
+ if ( likely(!is_cpufreq_controller(currd)) ||
+ wrmsr_safe(reg, val) == 0 )
+ return X86EMUL_OKAY;
+ break;
+
+ case MSR_AMD64_NB_CFG:
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ||
+ boot_cpu_data.x86 < 0x10 || boot_cpu_data.x86 > 0x17 )
+ break;
+ if ( !is_hardware_domain(currd) || !is_pinned_vcpu(curr) )
+ return X86EMUL_OKAY;
+ if ( (rdmsr_safe(MSR_AMD64_NB_CFG, temp) != 0) ||
+ ((val ^ temp) & ~(1ULL << AMD64_NB_CFG_CF8_EXT_ENABLE_BIT)) )
+ goto invalid;
+ if ( wrmsr_safe(MSR_AMD64_NB_CFG, val) == 0 )
+ return X86EMUL_OKAY;
+ break;
+
+ case MSR_FAM10H_MMIO_CONF_BASE:
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ||
+ boot_cpu_data.x86 < 0x10 || boot_cpu_data.x86 > 0x17 )
+ break;
+ if ( !is_hardware_domain(currd) || !is_pinned_vcpu(curr) )
+ return X86EMUL_OKAY;
+ if ( rdmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, temp) != 0 )
+ break;
+ if ( (pci_probe & PCI_PROBE_MASK) == PCI_PROBE_MMCONF ?
+ temp != val :
+ ((temp ^ val) &
+ ~(FAM10H_MMIO_CONF_ENABLE |
+ (FAM10H_MMIO_CONF_BUSRANGE_MASK <<
+ FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
+ ((u64)FAM10H_MMIO_CONF_BASE_MASK <<
+ FAM10H_MMIO_CONF_BASE_SHIFT))) )
+ goto invalid;
+ if ( wrmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, val) == 0 )
+ return X86EMUL_OKAY;
+ break;
+
+ case MSR_IA32_UCODE_REV:
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
+ break;
+ if ( !is_hardware_domain(currd) || !is_pinned_vcpu(curr) )
+ return X86EMUL_OKAY;
+ if ( rdmsr_safe(reg, temp) )
+ break;
+ if ( val )
+ goto invalid;
+ return X86EMUL_OKAY;
+
+ case MSR_IA32_MISC_ENABLE:
+ if ( rdmsr_safe(reg, temp) )
+ break;
+ if ( val != guest_misc_enable(temp) )
+ goto invalid;
+ return X86EMUL_OKAY;
+
+ case MSR_IA32_MPERF:
+ case MSR_IA32_APERF:
+ if ( (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) &&
+ (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) )
+ break;
+ if ( likely(!is_cpufreq_controller(currd)) ||
+ wrmsr_safe(reg, val) == 0 )
+ 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 )
+ break;
+ if ( !is_hardware_domain(currd) || !is_pinned_vcpu(curr) ||
+ wrmsr_safe(reg, val) == 0 )
+ return X86EMUL_OKAY;
+ break;
+
+ case MSR_AMD64_DR0_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) || (val >> 32) )
+ break;
+ curr->arch.pv_vcpu.dr_mask[0] = val;
+ if ( curr->arch.debugreg[7] & DR7_ACTIVE_MASK )
+ wrmsrl(MSR_AMD64_DR0_ADDRESS_MASK, val);
+ return X86EMUL_OKAY;
+
+ case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
+ if ( !boot_cpu_has(X86_FEATURE_DBEXT) || (val >> 32) )
+ break;
+ curr->arch.pv_vcpu.dr_mask[reg - MSR_AMD64_DR1_ADDRESS_MASK + 1] = val;
+ if ( curr->arch.debugreg[7] & DR7_ACTIVE_MASK )
+ wrmsrl(reg, val);
+ return X86EMUL_OKAY;
+
+ case MSR_P6_PERFCTR(0)...MSR_P6_PERFCTR(7):
+ case MSR_P6_EVNTSEL(0)...MSR_P6_EVNTSEL(3):
+ case MSR_CORE_PERF_FIXED_CTR0...MSR_CORE_PERF_FIXED_CTR2:
+ case MSR_CORE_PERF_FIXED_CTR_CTRL...MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+ if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+ {
+ vpmu_msr = true;
+ case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5:
+ case MSR_K7_EVNTSEL0...MSR_K7_PERFCTR3:
+ if ( vpmu_msr || (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) )
+ {
+ if ( (vpmu_mode & XENPMU_MODE_ALL) &&
+ !is_hardware_domain(currd) )
+ return X86EMUL_OKAY;
+
+ if ( vpmu_do_wrmsr(reg, val, 0) )
+ break;
+ return X86EMUL_OKAY;
+ }
+ }
+ /* fall through */
+ default:
+ if ( wrmsr_hypervisor_regs(reg, val) == 1 )
+ return X86EMUL_OKAY;
+
+ rc = vmce_wrmsr(reg, val);
+ if ( rc < 0 )
+ break;
+ if ( rc )
+ return X86EMUL_OKAY;
+
+ if ( (rdmsr_safe(reg, temp) != 0) || (val != temp) )
+ invalid:
+ gdprintk(XENLOG_WARNING,
+ "Domain attempted WRMSR %08x from 0x%016"PRIx64" to 0x%016"PRIx64"\n",
+ reg, temp, val);
+ return X86EMUL_OKAY;
+ }
+
+ return X86EMUL_UNHANDLEABLE;
+}
+
/* Instruction fetch with error handling. */
#define insn_fetch(type, base, eip, limit) \
({ unsigned long _rc, _ptr = (base) + (eip); \
@@ -2388,14 +2714,6 @@ static inline uint64_t guest_misc_enable
} \
(eip) += sizeof(_x); _x; })
-static int is_cpufreq_controller(struct domain *d)
-{
- return ((cpufreq_controller == FREQCTL_dom0_kernel) &&
- is_hardware_domain(d));
-}
-
-#include "x86_64/mmconfig.h"
-
static int emulate_privileged_op(struct cpu_user_regs *regs)
{
struct vcpu *v = current;
@@ -2420,7 +2738,6 @@ static int emulate_privileged_op(struct
char *io_emul_stub = NULL;
void (*io_emul)(struct cpu_user_regs *);
uint64_t val;
- bool_t vpmu_msr;
if ( !read_descriptor(regs->cs, v, &code_base, &code_limit, &ar, 1) )
goto fail;
@@ -2821,188 +3138,11 @@ static int emulate_privileged_op(struct
goto fail;
break;
- case 0x30: /* WRMSR */ {
- uint32_t eax = regs->eax;
- uint32_t edx = regs->edx;
- uint64_t msr_content = ((uint64_t)edx << 32) | eax;
- vpmu_msr = 0;
- switch ( regs->_ecx )
- {
- case MSR_FS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- wrfsbase(msr_content);
- v->arch.pv_vcpu.fs_base = msr_content;
- break;
- case MSR_GS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- wrgsbase(msr_content);
- v->arch.pv_vcpu.gs_base_kernel = msr_content;
- break;
- case MSR_SHADOW_GS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- if ( wrmsr_safe(MSR_SHADOW_GS_BASE, msr_content) )
- goto fail;
- v->arch.pv_vcpu.gs_base_user = msr_content;
- break;
- case MSR_K7_FID_VID_STATUS:
- case MSR_K7_FID_VID_CTL:
- case MSR_K8_PSTATE_LIMIT:
- case MSR_K8_PSTATE_CTRL:
- case MSR_K8_PSTATE_STATUS:
- case MSR_K8_PSTATE0:
- case MSR_K8_PSTATE1:
- case MSR_K8_PSTATE2:
- case MSR_K8_PSTATE3:
- case MSR_K8_PSTATE4:
- case MSR_K8_PSTATE5:
- case MSR_K8_PSTATE6:
- case MSR_K8_PSTATE7:
- case MSR_K8_HWCR:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
- goto fail;
- if ( !is_cpufreq_controller(currd) )
- break;
- if ( wrmsr_safe(regs->ecx, msr_content) != 0 )
- goto fail;
- break;
- case MSR_AMD64_NB_CFG:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ||
- boot_cpu_data.x86 < 0x10 || boot_cpu_data.x86 > 0x17 )
- goto fail;
- if ( !is_hardware_domain(currd) || !is_pinned_vcpu(v) )
- break;
- if ( (rdmsr_safe(MSR_AMD64_NB_CFG, val) != 0) ||
- (eax != (uint32_t)val) ||
- ((edx ^ (val >> 32)) & ~(1 << (AMD64_NB_CFG_CF8_EXT_ENABLE_BIT - 32))) )
- goto invalid;
- if ( wrmsr_safe(MSR_AMD64_NB_CFG, msr_content) != 0 )
- goto fail;
- break;
- case MSR_FAM10H_MMIO_CONF_BASE:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ||
- boot_cpu_data.x86 < 0x10 || boot_cpu_data.x86 > 0x17 )
- goto fail;
- if ( !is_hardware_domain(currd) || !is_pinned_vcpu(v) )
- break;
- if ( (rdmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, val) != 0) )
- goto fail;
- if (
- (pci_probe & PCI_PROBE_MASK) == PCI_PROBE_MMCONF ?
- val != msr_content :
- ((val ^ msr_content) &
- ~( FAM10H_MMIO_CONF_ENABLE |
- (FAM10H_MMIO_CONF_BUSRANGE_MASK <<
- FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
- ((u64)FAM10H_MMIO_CONF_BASE_MASK <<
- FAM10H_MMIO_CONF_BASE_SHIFT))) )
- goto invalid;
- if ( wrmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, msr_content) != 0 )
- goto fail;
- break;
- case MSR_IA32_UCODE_REV:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
- goto fail;
- if ( !is_hardware_domain(currd) || !is_pinned_vcpu(v) )
- break;
- if ( rdmsr_safe(regs->ecx, val) )
- goto fail;
- if ( msr_content )
- goto invalid;
- break;
- case MSR_IA32_MISC_ENABLE:
- if ( rdmsr_safe(regs->ecx, val) )
- goto fail;
- val = guest_misc_enable(val);
- if ( msr_content != val )
- goto invalid;
- break;
- case MSR_IA32_MPERF:
- case MSR_IA32_APERF:
- if (( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ) &&
- ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ) )
- goto fail;
- if ( !is_cpufreq_controller(currd) )
- break;
- if ( wrmsr_safe(regs->ecx, msr_content ) != 0 )
- goto fail;
- break;
- case MSR_IA32_PERF_CTL:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
- goto fail;
- if ( !is_cpufreq_controller(currd) )
- break;
- if ( wrmsr_safe(regs->ecx, msr_content) != 0 )
- goto fail;
- break;
- case MSR_IA32_THERM_CONTROL:
- case MSR_IA32_ENERGY_PERF_BIAS:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
- goto fail;
- if ( !is_hardware_domain(currd) || !is_pinned_vcpu(v) )
- break;
- if ( wrmsr_safe(regs->ecx, msr_content) != 0 )
- goto fail;
- break;
-
- case MSR_AMD64_DR0_ADDRESS_MASK:
- if ( !boot_cpu_has(X86_FEATURE_DBEXT) || (msr_content >> 32) )
- goto fail;
- v->arch.pv_vcpu.dr_mask[0] = msr_content;
- if ( v->arch.debugreg[7] & DR7_ACTIVE_MASK )
- wrmsrl(MSR_AMD64_DR0_ADDRESS_MASK, msr_content);
- break;
- case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
- if ( !boot_cpu_has(X86_FEATURE_DBEXT) || (msr_content >> 32) )
- goto fail;
- v->arch.pv_vcpu.dr_mask
- [regs->_ecx - MSR_AMD64_DR1_ADDRESS_MASK + 1] = msr_content;
- if ( v->arch.debugreg[7] & DR7_ACTIVE_MASK )
- wrmsrl(regs->_ecx, msr_content);
- break;
- case MSR_P6_PERFCTR(0)...MSR_P6_PERFCTR(7):
- case MSR_P6_EVNTSEL(0)...MSR_P6_EVNTSEL(3):
- case MSR_CORE_PERF_FIXED_CTR0...MSR_CORE_PERF_FIXED_CTR2:
- case MSR_CORE_PERF_FIXED_CTR_CTRL...MSR_CORE_PERF_GLOBAL_OVF_CTRL:
- if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
- {
- vpmu_msr = 1;
- case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5:
- case MSR_K7_EVNTSEL0...MSR_K7_PERFCTR3:
- if ( vpmu_msr || (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) )
- {
- if ( (vpmu_mode & XENPMU_MODE_ALL) &&
- !is_hardware_domain(v->domain) )
- break;
-
- if ( vpmu_do_wrmsr(regs->ecx, msr_content, 0) )
- goto fail;
- break;
- }
- }
- /*FALLTHROUGH*/
-
- default:
- if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) == 1 )
- break;
-
- rc = vmce_wrmsr(regs->ecx, msr_content);
- if ( rc < 0 )
- goto fail;
- if ( rc )
- break;
-
- if ( (rdmsr_safe(regs->ecx, val) != 0) || (msr_content != val) )
- invalid:
- gdprintk(XENLOG_WARNING, "Domain attempted WRMSR %p from "
- "0x%016"PRIx64" to 0x%016"PRIx64".\n",
- _p(regs->ecx), val, msr_content);
- break;
- }
+ case 0x30: /* WRMSR */
+ if ( priv_op_write_msr(regs->_ecx, (regs->rdx << 32) | regs->_eax,
+ NULL) != X86EMUL_OKAY )
+ goto fail;
break;
- }
case 0x31: /* RDTSC */
if ( (v->arch.pv_vcpu.ctrlreg[4] & X86_CR4_TSD) &&
@@ -3018,130 +3158,11 @@ static int emulate_privileged_op(struct
break;
case 0x32: /* RDMSR */
- vpmu_msr = 0;
- switch ( regs->_ecx )
- {
- case MSR_FS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- val = cpu_has_fsgsbase ? __rdfsbase() : v->arch.pv_vcpu.fs_base;
- goto rdmsr_writeback;
- case MSR_GS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- val = cpu_has_fsgsbase ? __rdgsbase()
- : v->arch.pv_vcpu.gs_base_kernel;
- goto rdmsr_writeback;
- case MSR_SHADOW_GS_BASE:
- if ( is_pv_32bit_domain(currd) )
- goto fail;
- val = v->arch.pv_vcpu.gs_base_user;
- goto rdmsr_writeback;
- case MSR_K7_FID_VID_CTL:
- case MSR_K7_FID_VID_STATUS:
- case MSR_K8_PSTATE_LIMIT:
- case MSR_K8_PSTATE_CTRL:
- case MSR_K8_PSTATE_STATUS:
- case MSR_K8_PSTATE0:
- case MSR_K8_PSTATE1:
- case MSR_K8_PSTATE2:
- case MSR_K8_PSTATE3:
- case MSR_K8_PSTATE4:
- case MSR_K8_PSTATE5:
- case MSR_K8_PSTATE6:
- case MSR_K8_PSTATE7:
- if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
- goto fail;
- if ( !is_cpufreq_controller(currd) )
- {
- regs->eax = regs->edx = 0;
- break;
- }
- goto rdmsr_normal;
- case MSR_IA32_UCODE_REV:
- BUILD_BUG_ON(MSR_IA32_UCODE_REV != MSR_AMD_PATCHLEVEL);
- if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
- {
- if ( wrmsr_safe(MSR_IA32_UCODE_REV, 0) )
- goto fail;
- sync_core();
- }
- goto rdmsr_normal;
- case MSR_IA32_MISC_ENABLE:
- if ( rdmsr_safe(regs->ecx, val) )
- goto fail;
- val = guest_misc_enable(val);
- goto rdmsr_writeback;
-
- case MSR_AMD64_DR0_ADDRESS_MASK:
- if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
- goto fail;
- regs->eax = v->arch.pv_vcpu.dr_mask[0];
- regs->edx = 0;
- break;
- case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
- if ( !boot_cpu_has(X86_FEATURE_DBEXT) )
- goto fail;
- regs->eax = v->arch.pv_vcpu.dr_mask
- [regs->_ecx - MSR_AMD64_DR1_ADDRESS_MASK + 1];
- regs->edx = 0;
- break;
- case MSR_IA32_PERF_CAPABILITIES:
- /* No extra capabilities are supported */
- regs->eax = regs->edx = 0;
- break;
- case MSR_P6_PERFCTR(0)...MSR_P6_PERFCTR(7):
- case MSR_P6_EVNTSEL(0)...MSR_P6_EVNTSEL(3):
- case MSR_CORE_PERF_FIXED_CTR0...MSR_CORE_PERF_FIXED_CTR2:
- case MSR_CORE_PERF_FIXED_CTR_CTRL...MSR_CORE_PERF_GLOBAL_OVF_CTRL:
- if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
- {
- vpmu_msr = 1;
- case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5:
- case MSR_K7_EVNTSEL0...MSR_K7_PERFCTR3:
- if ( vpmu_msr || (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) )
- {
-
- if ( (vpmu_mode & XENPMU_MODE_ALL) &&
- !is_hardware_domain(v->domain) )
- {
- /* Don't leak PMU MSRs to unprivileged domains */
- regs->eax = regs->edx = 0;
- break;
- }
-
- if ( vpmu_do_rdmsr(regs->ecx, &val) )
- goto fail;
-
- regs->eax = (uint32_t)val;
- regs->edx = (uint32_t)(val >> 32);
- break;
- }
- }
- /*FALLTHROUGH*/
-
- default:
- if ( rdmsr_hypervisor_regs(regs->ecx, &val) )
- goto rdmsr_writeback;
-
- rc = vmce_rdmsr(regs->ecx, &val);
- if ( rc < 0 )
- goto fail;
- if ( rc )
- goto rdmsr_writeback;
-
- case MSR_EFER:
- rdmsr_normal:
- /* Everyone can read the MSR space. */
- /* gdprintk(XENLOG_WARNING,"Domain attempted RDMSR %p.\n",
- _p(regs->ecx));*/
- if ( rdmsr_safe(regs->ecx, val) )
- goto fail;
+ if ( priv_op_read_msr(regs->_ecx, &val, NULL) != X86EMUL_OKAY )
+ goto fail;
rdmsr_writeback:
- regs->eax = (uint32_t)val;
- regs->edx = (uint32_t)(val >> 32);
- break;
- }
+ regs->eax = (uint32_t)val;
+ regs->edx = (uint32_t)(val >> 32);
break;
case 0xa2: /* CPUID */
[-- Attachment #3: Type: text/plain, Size: 127 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
next prev parent reply other threads:[~2016-09-08 13:18 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-08 12:58 [PATCH 00/17] x86: split insn emulator decode and execution Jan Beulich
2016-09-08 13:04 ` [PATCH 01/17] x86emul: split instruction decoding from execution Jan Beulich
2016-09-09 18:35 ` Andrew Cooper
2016-09-12 7:20 ` Jan Beulich
2016-09-08 13:07 ` [PATCH 02/17] x86emul: fetch all insn bytes during the decode phase Jan Beulich
2016-09-13 18:44 ` Andrew Cooper
2016-09-14 9:55 ` Jan Beulich
2016-09-23 14:48 ` Andrew Cooper
2016-09-23 15:04 ` Jan Beulich
2016-09-08 13:08 ` [PATCH 04/17] x86emul: track only rIP in emulator state Jan Beulich
2016-09-08 13:23 ` Jan Beulich
2016-09-08 13:09 ` [PATCH 03/17] " Jan Beulich
2016-09-13 19:09 ` Andrew Cooper
2016-09-14 9:58 ` Jan Beulich
2016-09-08 13:10 ` [PATCH 04/17] x86emul: complete decoding of two-byte instructions Jan Beulich
2016-09-14 14:22 ` Andrew Cooper
2016-09-14 15:05 ` Jan Beulich
2016-09-23 16:34 ` Andrew Cooper
2016-09-26 7:34 ` Jan Beulich
2016-09-27 13:28 ` Andrew Cooper
2016-09-27 13:51 ` Jan Beulich
2016-09-08 13:11 ` [PATCH 05/17] x86emul: add XOP decoding Jan Beulich
2016-09-14 16:11 ` Andrew Cooper
2016-09-14 16:21 ` Jan Beulich
2016-09-23 17:01 ` Andrew Cooper
2016-09-08 13:12 ` [PATCH 06/17] x86emul: add EVEX decoding Jan Beulich
2016-09-14 17:05 ` Andrew Cooper
2016-09-15 6:26 ` Jan Beulich
2016-09-08 13:13 ` [PATCH 07/17] x86emul: move x86_execute() common epilogue code Jan Beulich
2016-09-08 13:28 ` Jan Beulich
2016-09-14 17:13 ` Andrew Cooper
2016-09-08 13:14 ` [PATCH 08/17] x86emul: generate and make use of canonical opcode representation Jan Beulich
2016-09-14 17:30 ` Andrew Cooper
2016-09-15 6:43 ` Jan Beulich
2016-09-27 14:03 ` Andrew Cooper
2016-09-28 7:24 ` Jan Beulich
2016-09-08 13:14 ` [PATCH 09/17] SVM: use generic instruction decoding Jan Beulich
2016-09-14 17:56 ` Andrew Cooper
2016-09-15 6:55 ` Jan Beulich
2016-09-27 13:42 ` Andrew Cooper
2016-09-27 13:56 ` Jan Beulich
2016-09-27 15:53 ` Andrew Cooper
2016-09-08 13:16 ` [PATCH 10/17] x86/32on64: use generic instruction decoding for call gate emulation Jan Beulich
2016-09-08 13:17 ` [PATCH 11/17] x86/PV: split out dealing with CRn from privileged instruction handling Jan Beulich
2016-09-08 13:17 ` [PATCH 12/17] x86/PV: split out dealing with DRn " Jan Beulich
2016-09-08 13:18 ` Jan Beulich [this message]
2016-09-08 13:18 ` [PATCH 14/17] x86emul: support XSETBV Jan Beulich
2016-09-08 13:19 ` [PATCH 15/17] x86emul: sort opcode 0f01 special case switch() statement Jan Beulich
2016-09-08 13:20 ` [PATCH 16/17] x86/PV: use generic emulator for privileged instruction handling Jan Beulich
2016-09-08 13:21 ` [PATCH 17/17] x86emul: don't assume a memory operand Jan Beulich
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=57D18130020000780010D1DA@prv-mh.provo.novell.com \
--to=jbeulich@suse.com \
--cc=andrew.cooper3@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).