From: ddugger@redhat.com <ddugger@redhat.com> Date: Tue, 21 Apr 2009 13:01:24 -0600 Subject: [xen] utilise the GUEST_PAT and HOST_PAT vmcs area Message-id: 200904211901.n3LJ1OM0028384@sobek.n0ano.com O-Subject: [RHEL5.4 PATCH 2/6 V2] BZ496873: Utilise the GUEST_PAT and HOST_PAT vmcs area for EPT and VT-d enabled both. Bugzilla: 496873 RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com> RH-Acked-by: Chris Lalancette <clalance@redhat.com> RH-Acked-by: Rik van Riel <riel@redhat.com> RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com> RH-Acked-by: Justin M. Forbes <jforbes@redhat.com> The trunk includes "disable_intercept_for_msr(MSR_IA32_CR_PAT)" is different from xen-unstable, since the whole disable_intercept_for_msr() is substitute with vmx_disable_intercept_from_msr() and related much to the msr_bitmap. And at start_vmx() time, the paging mode may not be intialised yet, so we use vmx_function_table.hap_supported to indicate if the EPT mode is enabled or not. Upstream Status: Accepted (CS 19072) Signed-off-by: Xiaohui Xin <xiaohui.xin@intel.com> Signed-off-by: Gerd Hoffman <kraxel@redhat.com> Signed-off-by: Don Dugger <donald.d.dugger@intel.com> Yet Another Resend - resolve the conflicting BZs between the Subject line (correct) and the message body (incorrect). diff --git a/arch/x86/hvm/vmx/vmcs.c b/arch/x86/hvm/vmx/vmcs.c index 8a119d4..015e2be 100644 --- a/arch/x86/hvm/vmx/vmcs.c +++ b/arch/x86/hvm/vmx/vmcs.c @@ -140,14 +140,15 @@ void vmx_init_vmcs_config(void) } 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_MSR); - min = opt = 0; + min = 0; + opt = VM_ENTRY_LOAD_GUEST_PAT; _vmx_vmentry_control = adjust_vmx_controls( min, opt, MSR_IA32_VMX_ENTRY_CTLS_MSR); @@ -362,8 +363,6 @@ static void 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; @@ -377,9 +376,15 @@ static void 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); @@ -568,6 +573,21 @@ static void construct_vmcs(struct vcpu *v) __vmwrite(GUEST_TR_BASE, 0); __vmwrite(GUEST_TR_LIMIT, 0xff); + 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 */ @@ -714,6 +734,10 @@ void vmcs_dump_vcpu(void) print_section("Natural 64-bit Host-State Fields", 0x6c00, 0x6c16, 2); printk("secondary exec control = 0x%08x\n", (uint32_t)__vmread(SECONDARY_VM_EXEC_CONTROL)); + printk("Guest PAT = 0x%08x%08x\n", + (uint32_t)__vmread(GUEST_PAT_HIGH), (uint32_t)__vmread(GUEST_PAT)); + printk("Host PAT = 0x%08x%08x\n", + (uint32_t)__vmread(HOST_PAT_HIGH), (uint32_t)__vmread(HOST_PAT)); printk("EPT pointer = 0x%08x%08x\n", (uint32_t)__vmread(EPT_POINTER_HIGH), (uint32_t)__vmread(EPT_POINTER)); printk("virtual processor ID = 0x%04x\n", diff --git a/arch/x86/hvm/vmx/vmx.c b/arch/x86/hvm/vmx/vmx.c index 51ec1f8..13a4462 100644 --- a/arch/x86/hvm/vmx/vmx.c +++ b/arch/x86/hvm/vmx/vmx.c @@ -1471,6 +1471,9 @@ int start_vmx(void) disable_intercept_for_msr(MSR_IA32_SYSENTER_CS); disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP); disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP); + if ( cpu_has_vmx_pat && + vmx_function_table.hap_supported ) + disable_intercept_for_msr(MSR_IA32_CR_PAT); } return 1; diff --git a/include/asm-x86/hvm/vmx/vmcs.h b/include/asm-x86/hvm/vmx/vmcs.h index ade7a5a..029c7a9 100644 --- a/include/asm-x86/hvm/vmx/vmcs.h +++ b/include/asm-x86/hvm/vmx/vmcs.h @@ -139,11 +139,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 @@ -165,7 +168,8 @@ extern u32 vmx_secondary_exec_control; (vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) #define cpu_has_vmx_ept \ (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT) - +#define cpu_has_vmx_pat \ + (vmx_vmentry_control & VM_ENTRY_LOAD_GUEST_PAT) #define cpu_has_vmx_vpid \ (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_VPID) @@ -221,6 +225,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, @@ -229,6 +235,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,