# HG changeset patch # User Keir Fraser # Date 1232623303 0 # Node ID d52921c18c3d0171bccb4651cca8412f2fff2dd9 # Parent 9f9ba1a7cc924fbc547e05ea21071becafe5e2c2 vmx: utilise the GUEST_PAT and HOST_PAT vmcs area Signed-off-by: Xin Li Signed-off-by: Xiaohui Xin --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -166,14 +166,15 @@ static void vmx_init_vmcs_config(void) #endif min = VM_EXIT_ACK_INTR_ON_EXIT; - opt = 0; + opt = VM_EXIT_SAVE_GUEST_PAT | VM_EXIT_LOAD_HOST_PAT; #ifdef __x86_64__ min |= VM_EXIT_IA32E_MODE; #endif _vmx_vmexit_control = adjust_vmx_controls( min, opt, MSR_IA32_VMX_EXIT_CTLS); - min = opt = 0; + min = 0; + opt = VM_ENTRY_LOAD_GUEST_PAT; _vmx_vmentry_control = adjust_vmx_controls( min, opt, MSR_IA32_VMX_ENTRY_CTLS); @@ -518,8 +519,6 @@ static int construct_vmcs(struct vcpu *v /* VMCS controls. */ __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); - __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); - __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control); v->arch.hvm_vmx.exec_control = vmx_cpu_based_exec_control; v->arch.hvm_vmx.secondary_exec_control = vmx_secondary_exec_control; @@ -533,9 +532,15 @@ static int construct_vmcs(struct vcpu *v else { v->arch.hvm_vmx.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT; + vmx_vmexit_control &= ~(VM_EXIT_SAVE_GUEST_PAT | + VM_EXIT_LOAD_HOST_PAT); + vmx_vmentry_control &= ~VM_ENTRY_LOAD_GUEST_PAT; } __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); + __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); + __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control); + if ( cpu_has_vmx_secondary_exec_control ) __vmwrite(SECONDARY_VM_EXEC_CONTROL, v->arch.hvm_vmx.secondary_exec_control); @@ -557,6 +562,8 @@ static int construct_vmcs(struct vcpu *v vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_CS); vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_ESP); vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_EIP); + if ( cpu_has_vmx_pat && paging_mode_hap(d) ) + vmx_disable_intercept_for_msr(v, MSR_IA32_CR_PAT); } /* I/O access bitmap. */ @@ -688,6 +695,21 @@ static int construct_vmcs(struct vcpu *v __vmwrite(VIRTUAL_PROCESSOR_ID, v->arch.hvm_vmx.vpid); } + if ( cpu_has_vmx_pat && paging_mode_hap(d) ) + { + u64 host_pat, guest_pat; + + rdmsrl(MSR_IA32_CR_PAT, host_pat); + guest_pat = 0x7040600070406ULL; + + __vmwrite(HOST_PAT, host_pat); + __vmwrite(GUEST_PAT, guest_pat); +#ifdef __i386__ + __vmwrite(HOST_PAT_HIGH, host_pat >> 32); + __vmwrite(GUEST_PAT_HIGH, guest_pat >> 32); +#endif + } + vmx_vmcs_exit(v); paging_update_paging_modes(v); /* will update HOST & GUEST_CR3 as reqd */ @@ -968,6 +990,8 @@ void vmcs_dump_vcpu(struct vcpu *v) vmx_dump_sel("LDTR", x86_seg_ldtr); vmx_dump_sel("IDTR", x86_seg_idtr); vmx_dump_sel("TR", x86_seg_tr); + printk("Guest PAT = 0x%08x%08x\n", + (uint32_t)vmr(GUEST_PAT_HIGH), (uint32_t)vmr(GUEST_PAT)); x = (unsigned long long)vmr(TSC_OFFSET_HIGH) << 32; x |= (uint32_t)vmr(TSC_OFFSET); printk("TSC Offset = %016llx\n", x); @@ -1006,6 +1030,8 @@ void vmcs_dump_vcpu(struct vcpu *v) (unsigned long long)vmr(HOST_SYSENTER_ESP), (int)vmr(HOST_SYSENTER_CS), (unsigned long long)vmr(HOST_SYSENTER_EIP)); + printk("Host PAT = 0x%08x%08x\n", + (uint32_t)vmr(HOST_PAT_HIGH), (uint32_t)vmr(HOST_PAT)); printk("*** Control State ***\n"); printk("PinBased=%08x CPUBased=%08x SecondaryExec=%08x\n", --- a/xen/include/asm-x86/hvm/vmx/vmcs.h +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h @@ -150,11 +150,14 @@ extern u32 vmx_pin_based_exec_control; #define VM_EXIT_IA32E_MODE 0x00000200 #define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 +#define VM_EXIT_SAVE_GUEST_PAT 0x00040000 +#define VM_EXIT_LOAD_HOST_PAT 0x00080000 extern u32 vmx_vmexit_control; #define VM_ENTRY_IA32E_MODE 0x00000200 #define VM_ENTRY_SMM 0x00000400 #define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 +#define VM_ENTRY_LOAD_GUEST_PAT 0x00004000 extern u32 vmx_vmentry_control; #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 @@ -181,6 +184,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT) #define cpu_has_vmx_vpid \ (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_VPID) +#define cpu_has_vmx_pat \ + (vmx_vmentry_control & VM_ENTRY_LOAD_GUEST_PAT) /* GUEST_INTERRUPTIBILITY_INFO flags. */ #define VMX_INTR_SHADOW_STI 0x00000001 @@ -232,6 +237,8 @@ enum vmcs_field { VMCS_LINK_POINTER_HIGH = 0x00002801, GUEST_IA32_DEBUGCTL = 0x00002802, GUEST_IA32_DEBUGCTL_HIGH = 0x00002803, + GUEST_PAT = 0x00002804, + GUEST_PAT_HIGH = 0x00002805, GUEST_PDPTR0 = 0x0000280a, GUEST_PDPTR0_HIGH = 0x0000280b, GUEST_PDPTR1 = 0x0000280c, @@ -240,6 +247,8 @@ enum vmcs_field { GUEST_PDPTR2_HIGH = 0x0000280f, GUEST_PDPTR3 = 0x00002810, GUEST_PDPTR3_HIGH = 0x00002811, + HOST_PAT = 0x00002c00, + HOST_PAT_HIGH = 0x00002c01, PIN_BASED_VM_EXEC_CONTROL = 0x00004000, CPU_BASED_VM_EXEC_CONTROL = 0x00004002, EXCEPTION_BITMAP = 0x00004004,