aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/x86/kvm/vmx.c29
-rw-r--r--arch/x86/kvm/vmx.h7
-rw-r--r--arch/x86/kvm/x86.c2
3 files changed, 34 insertions, 4 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;
diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h
index ec5edc339da6..18598afe52eb 100644
--- a/arch/x86/kvm/vmx.h
+++ b/arch/x86/kvm/vmx.h
@@ -63,10 +63,13 @@
63 63
64#define VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200 64#define VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200
65#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 65#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000
66#define VM_EXIT_SAVE_IA32_PAT 0x00040000
67#define VM_EXIT_LOAD_IA32_PAT 0x00080000
66 68
67#define VM_ENTRY_IA32E_MODE 0x00000200 69#define VM_ENTRY_IA32E_MODE 0x00000200
68#define VM_ENTRY_SMM 0x00000400 70#define VM_ENTRY_SMM 0x00000400
69#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 71#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800
72#define VM_ENTRY_LOAD_IA32_PAT 0x00004000
70 73
71/* VMCS Encodings */ 74/* VMCS Encodings */
72enum vmcs_field { 75enum vmcs_field {
@@ -112,6 +115,8 @@ enum vmcs_field {
112 VMCS_LINK_POINTER_HIGH = 0x00002801, 115 VMCS_LINK_POINTER_HIGH = 0x00002801,
113 GUEST_IA32_DEBUGCTL = 0x00002802, 116 GUEST_IA32_DEBUGCTL = 0x00002802,
114 GUEST_IA32_DEBUGCTL_HIGH = 0x00002803, 117 GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
118 GUEST_IA32_PAT = 0x00002804,
119 GUEST_IA32_PAT_HIGH = 0x00002805,
115 GUEST_PDPTR0 = 0x0000280a, 120 GUEST_PDPTR0 = 0x0000280a,
116 GUEST_PDPTR0_HIGH = 0x0000280b, 121 GUEST_PDPTR0_HIGH = 0x0000280b,
117 GUEST_PDPTR1 = 0x0000280c, 122 GUEST_PDPTR1 = 0x0000280c,
@@ -120,6 +125,8 @@ enum vmcs_field {
120 GUEST_PDPTR2_HIGH = 0x0000280f, 125 GUEST_PDPTR2_HIGH = 0x0000280f,
121 GUEST_PDPTR3 = 0x00002810, 126 GUEST_PDPTR3 = 0x00002810,
122 GUEST_PDPTR3_HIGH = 0x00002811, 127 GUEST_PDPTR3_HIGH = 0x00002811,
128 HOST_IA32_PAT = 0x00002c00,
129 HOST_IA32_PAT_HIGH = 0x00002c01,
123 PIN_BASED_VM_EXEC_CONTROL = 0x00004000, 130 PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
124 CPU_BASED_VM_EXEC_CONTROL = 0x00004002, 131 CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
125 EXCEPTION_BITMAP = 0x00004004, 132 EXCEPTION_BITMAP = 0x00004004,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f5b2334c6bda..0edf75339f3a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -452,7 +452,7 @@ static u32 msrs_to_save[] = {
452 MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, 452 MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
453#endif 453#endif
454 MSR_IA32_TIME_STAMP_COUNTER, MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, 454 MSR_IA32_TIME_STAMP_COUNTER, MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
455 MSR_IA32_PERF_STATUS, 455 MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT
456}; 456};
457 457
458static unsigned num_msrs_to_save; 458static unsigned num_msrs_to_save;