hv: intercept IA32_PAT MSR

Preparing for emulating guest's CR0.CD and CR0.NW bits:
 - Intercept both rdmsr and wrmsr for IA32_PAT
 - Track guest's IA32_PAT MSR with vcpu.arch_vcpu.contexts.ia32_pat

Signed-off-by: Zide Chen <zide.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Zide Chen 2018-06-19 15:03:14 -07:00 committed by lijinxia
parent 873e90cd9a
commit 6801d826e2
5 changed files with 58 additions and 0 deletions

View File

@ -13,6 +13,7 @@ static const uint32_t emulated_msrs[] = {
MSR_IA32_BIOS_UPDT_TRIG, /* Enable MSR_IA32_BIOS_UPDT_TRIG */
MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
MSR_IA32_TIME_STAMP_COUNTER,
MSR_IA32_PAT,
/* following MSR not emulated now */
/*
@ -205,6 +206,11 @@ int rdmsr_vmexit_handler(struct vcpu *vcpu)
v = exec_vmread(VMX_GUEST_IA32_SYSENTER_EIP);
break;
}
case MSR_IA32_PAT:
{
v = vmx_rdmsr_pat(vcpu);
break;
}
case MSR_IA32_TSC_AUX:
{
v = vcpu->arch_vcpu.msr_tsc_aux;
@ -330,6 +336,11 @@ int wrmsr_vmexit_handler(struct vcpu *vcpu)
exec_vmwrite(VMX_GUEST_IA32_SYSENTER_EIP, v);
break;
}
case MSR_IA32_PAT:
{
vmx_wrmsr_pat(vcpu, v);
break;
}
case MSR_IA32_GS_BASE:
{
exec_vmwrite(VMX_GUEST_GS_BASE, v);

View File

@ -299,7 +299,40 @@ static void init_cr0_cr4_host_mask(__unused struct vcpu *vcpu)
exec_vmwrite(VMX_CR4_MASK, cr4_host_mask);
/* Output CR4 mask value */
pr_dbg("CR4 mask value: 0x%x", cr4_host_mask);
}
uint64_t vmx_rdmsr_pat(struct vcpu *vcpu)
{
struct run_context *context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
/*
* note: if context->cr0.CD is set, the actual value in guest's
* IA32_PAT MSR is PAT_ALL_UC_VALUE, which may be different from
* the saved value context->ia32_pat
*/
return context->ia32_pat;
}
int vmx_wrmsr_pat(struct vcpu *vcpu, uint64_t value)
{
uint32_t field, i;
struct run_context *context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
for (i = 0; i < 8; i++) {
field = (value >> (i * 8)) & 0xffU;
if ((PAT_MEM_TYPE_INVALID(field) ||
(PAT_FIELD_RSV_BITS & field) != 0U)) {
pr_err("invalid guest IA32_PAT: 0x%016llx", value);
vcpu_inject_gp(vcpu, 0);
return -EINVAL;
}
}
context->ia32_pat = value;
exec_vmwrite(VMX_GUEST_IA32_PAT_FULL, value);
return 0;
}
/*
@ -875,6 +908,7 @@ static void init_guest_state(struct vcpu *vcpu)
value32);
value64 = PAT_POWER_ON_VALUE;
cur_context->ia32_pat = value64;
exec_vmwrite64(VMX_GUEST_IA32_PAT_FULL, value64);
pr_dbg("VMX_GUEST_IA32_PAT: 0x%016llx ",
value64);

View File

@ -28,6 +28,7 @@ enum {
IDX_BIOS_UPDT_TRIG,
IDX_BIOS_SIGN_ID,
IDX_TSC,
IDX_PAT,
IDX_MAX_MSR
};

View File

@ -509,6 +509,15 @@
#define PAT_MEM_TYPE_WP 0x05U /* write protected */
#define PAT_MEM_TYPE_WB 0x06U /* writeback */
#define PAT_MEM_TYPE_UCM 0x07U /* uncached minus */
#define PAT_MEM_TYPE_INVALID(x) (((x) != PAT_MEM_TYPE_UC) && \
((x) != PAT_MEM_TYPE_WC) && \
((x) != PAT_MEM_TYPE_WT) && \
((x) != PAT_MEM_TYPE_WP) && \
((x) != PAT_MEM_TYPE_WB) && \
((x) != PAT_MEM_TYPE_UCM))
/* 5 high-order bits in every field are reserved */
#define PAT_FIELD_RSV_BITS (0xF8U)
/* MTRR memory type definitions */
#define MTRR_MEM_TYPE_UC 0x00U /* uncached */

View File

@ -414,6 +414,9 @@ int vmx_restart(uint16_t pcpu_id);
int exec_vmclear(void *addr);
int exec_vmptrld(void *addr);
uint64_t vmx_rdmsr_pat(struct vcpu *vcpu);
int vmx_wrmsr_pat(struct vcpu *vcpu, uint64_t value);
int vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0);
int vmx_write_cr3(struct vcpu *vcpu, uint64_t cr3);
int vmx_write_cr4(struct vcpu *vcpu, uint64_t cr4);