aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorSheng Yang <sheng@linux.intel.com>2008-10-09 04:01:55 -0400
committerAvi Kivity <avi@redhat.com>2008-12-31 09:51:44 -0500
commit468d472f3f65100d5fb88c8d45043c85b874c294 (patch)
tree6b82d3f738879827a2836aba8c54391e7a743588 /arch/x86/kvm/vmx.c
parent0bed3b568b68e5835ef5da888a372b9beabf7544 (diff)
KVM: VMX: Add PAT support for EPT
GUEST_PAT support is a new feature introduced by Intel Core i7 architecture. With this, cpu would save/load guest and host PAT automatically, for EPT memory type in guest depends on MSR_IA32_CR_PAT. Also add save/restore for MSR_IA32_CR_PAT. Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 2180109d794c..b4c95a501cca 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -962,6 +962,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
962 pr_unimpl(vcpu, "unimplemented perfctr wrmsr: 0x%x data 0x%llx\n", msr_index, data); 962 pr_unimpl(vcpu, "unimplemented perfctr wrmsr: 0x%x data 0x%llx\n", msr_index, data);
963 963
964 break; 964 break;
965 case MSR_IA32_CR_PAT:
966 if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
967 vmcs_write64(GUEST_IA32_PAT, data);
968 vcpu->arch.pat = data;
969 break;
970 }
971 /* Otherwise falls through to kvm_set_msr_common */
965 default: 972 default:
966 vmx_load_host_state(vmx); 973 vmx_load_host_state(vmx);
967 msr = find_msr_entry(vmx, msr_index); 974 msr = find_msr_entry(vmx, msr_index);
@@ -1181,12 +1188,13 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
1181#ifdef CONFIG_X86_64 1188#ifdef CONFIG_X86_64
1182 min |= VM_EXIT_HOST_ADDR_SPACE_SIZE; 1189 min |= VM_EXIT_HOST_ADDR_SPACE_SIZE;
1183#endif 1190#endif
1184 opt = 0; 1191 opt = VM_EXIT_SAVE_IA32_PAT | VM_EXIT_LOAD_IA32_PAT;
1185 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS, 1192 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,
1186 &_vmexit_control) < 0) 1193 &_vmexit_control) < 0)
1187 return -EIO; 1194 return -EIO;
1188 1195
1189 min = opt = 0; 1196 min = 0;
1197 opt = VM_ENTRY_LOAD_IA32_PAT;
1190 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS, 1198 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
1191 &_vmentry_control) < 0) 1199 &_vmentry_control) < 0)
1192 return -EIO; 1200 return -EIO;
@@ -2092,8 +2100,9 @@ static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
2092 */ 2100 */
2093static int vmx_vcpu_setup(struct vcpu_vmx *vmx) 2101static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
2094{ 2102{
2095 u32 host_sysenter_cs; 2103 u32 host_sysenter_cs, msr_low, msr_high;
2096 u32 junk; 2104 u32 junk;
2105 u64 host_pat;
2097 unsigned long a; 2106 unsigned long a;
2098 struct descriptor_table dt; 2107 struct descriptor_table dt;
2099 int i; 2108 int i;
@@ -2181,6 +2190,20 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
2181 rdmsrl(MSR_IA32_SYSENTER_EIP, a); 2190 rdmsrl(MSR_IA32_SYSENTER_EIP, a);
2182 vmcs_writel(HOST_IA32_SYSENTER_EIP, a); /* 22.2.3 */ 2191 vmcs_writel(HOST_IA32_SYSENTER_EIP, a); /* 22.2.3 */
2183 2192
2193 if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
2194 rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
2195 host_pat = msr_low | ((u64) msr_high << 32);
2196 vmcs_write64(HOST_IA32_PAT, host_pat);
2197 }
2198 if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
2199 rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
2200 host_pat = msr_low | ((u64) msr_high << 32);
2201 /* Write the default value follow host pat */
2202 vmcs_write64(GUEST_IA32_PAT, host_pat);
2203 /* Keep arch.pat sync with GUEST_IA32_PAT */
2204 vmx->vcpu.arch.pat = host_pat;
2205 }
2206
2184 for (i = 0; i < NR_VMX_MSR; ++i) { 2207 for (i = 0; i < NR_VMX_MSR; ++i) {
2185 u32 index = vmx_msr_index[i]; 2208 u32 index = vmx_msr_index[i];
2186 u32 data_low, data_high; 2209 u32 data_low, data_high;