aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorNadav Har'El <nyh@il.ibm.com>2011-05-25 16:03:55 -0400
committerAvi Kivity <avi@redhat.com>2011-07-12 04:45:10 -0400
commita9d30f33dd21b67b2f4db09f3dfe63a7c390d1b3 (patch)
treefabac8174f7dbf9322f593ee9e45632d4ae26379 /arch/x86/kvm/vmx.c
parent5e1746d6205d1efa3193cc0c67aa2d15e54799bd (diff)
KVM: nVMX: Introduce vmcs12: a VMCS structure for L1
An implementation of VMX needs to define a VMCS structure. This structure is kept in guest memory, but is opaque to the guest (who can only read or write it with VMX instructions). This patch starts to define the VMCS structure which our nested VMX implementation will present to L1. We call it "vmcs12", as it is the VMCS that L1 keeps for its L2 guest. We will add more content to this structure in later patches. This patch also adds the notion (as required by the VMX spec) of L1's "current VMCS", and finally includes utility functions for mapping the guest-allocated VMCSs in host memory. Signed-off-by: Nadav Har'El <nyh@il.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index eda2cb619c25..914dc4e9b37f 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -145,12 +145,53 @@ struct shared_msr_entry {
145}; 145};
146 146
147/* 147/*
148 * struct vmcs12 describes the state that our guest hypervisor (L1) keeps for a
149 * single nested guest (L2), hence the name vmcs12. Any VMX implementation has
150 * a VMCS structure, and vmcs12 is our emulated VMX's VMCS. This structure is
151 * stored in guest memory specified by VMPTRLD, but is opaque to the guest,
152 * which must access it using VMREAD/VMWRITE/VMCLEAR instructions.
153 * More than one of these structures may exist, if L1 runs multiple L2 guests.
154 * nested_vmx_run() will use the data here to build a vmcs02: a VMCS for the
155 * underlying hardware which will be used to run L2.
156 * This structure is packed to ensure that its layout is identical across
157 * machines (necessary for live migration).
158 * If there are changes in this struct, VMCS12_REVISION must be changed.
159 */
160struct __packed vmcs12 {
161 /* According to the Intel spec, a VMCS region must start with the
162 * following two fields. Then follow implementation-specific data.
163 */
164 u32 revision_id;
165 u32 abort;
166};
167
168/*
169 * VMCS12_REVISION is an arbitrary id that should be changed if the content or
170 * layout of struct vmcs12 is changed. MSR_IA32_VMX_BASIC returns this id, and
171 * VMPTRLD verifies that the VMCS region that L1 is loading contains this id.
172 */
173#define VMCS12_REVISION 0x11e57ed0
174
175/*
176 * VMCS12_SIZE is the number of bytes L1 should allocate for the VMXON region
177 * and any VMCS region. Although only sizeof(struct vmcs12) are used by the
178 * current implementation, 4K are reserved to avoid future complications.
179 */
180#define VMCS12_SIZE 0x1000
181
182/*
148 * The nested_vmx structure is part of vcpu_vmx, and holds information we need 183 * The nested_vmx structure is part of vcpu_vmx, and holds information we need
149 * for correct emulation of VMX (i.e., nested VMX) on this vcpu. 184 * for correct emulation of VMX (i.e., nested VMX) on this vcpu.
150 */ 185 */
151struct nested_vmx { 186struct nested_vmx {
152 /* Has the level1 guest done vmxon? */ 187 /* Has the level1 guest done vmxon? */
153 bool vmxon; 188 bool vmxon;
189
190 /* The guest-physical address of the current VMCS L1 keeps for L2 */
191 gpa_t current_vmptr;
192 /* The host-usable pointer to the above */
193 struct page *current_vmcs12_page;
194 struct vmcs12 *current_vmcs12;
154}; 195};
155 196
156struct vcpu_vmx { 197struct vcpu_vmx {
@@ -231,6 +272,31 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
231 return container_of(vcpu, struct vcpu_vmx, vcpu); 272 return container_of(vcpu, struct vcpu_vmx, vcpu);
232} 273}
233 274
275static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
276{
277 return to_vmx(vcpu)->nested.current_vmcs12;
278}
279
280static struct page *nested_get_page(struct kvm_vcpu *vcpu, gpa_t addr)
281{
282 struct page *page = gfn_to_page(vcpu->kvm, addr >> PAGE_SHIFT);
283 if (is_error_page(page)) {
284 kvm_release_page_clean(page);
285 return NULL;
286 }
287 return page;
288}
289
290static void nested_release_page(struct page *page)
291{
292 kvm_release_page_dirty(page);
293}
294
295static void nested_release_page_clean(struct page *page)
296{
297 kvm_release_page_clean(page);
298}
299
234static u64 construct_eptp(unsigned long root_hpa); 300static u64 construct_eptp(unsigned long root_hpa);
235static void kvm_cpu_vmxon(u64 addr); 301static void kvm_cpu_vmxon(u64 addr);
236static void kvm_cpu_vmxoff(void); 302static void kvm_cpu_vmxoff(void);
@@ -4039,6 +4105,12 @@ static void free_nested(struct vcpu_vmx *vmx)
4039 if (!vmx->nested.vmxon) 4105 if (!vmx->nested.vmxon)
4040 return; 4106 return;
4041 vmx->nested.vmxon = false; 4107 vmx->nested.vmxon = false;
4108 if (vmx->nested.current_vmptr != -1ull) {
4109 kunmap(vmx->nested.current_vmcs12_page);
4110 nested_release_page(vmx->nested.current_vmcs12_page);
4111 vmx->nested.current_vmptr = -1ull;
4112 vmx->nested.current_vmcs12 = NULL;
4113 }
4042} 4114}
4043 4115
4044/* Emulate the VMXOFF instruction */ 4116/* Emulate the VMXOFF instruction */
@@ -4543,6 +4615,9 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
4543 goto free_vmcs; 4615 goto free_vmcs;
4544 } 4616 }
4545 4617
4618 vmx->nested.current_vmptr = -1ull;
4619 vmx->nested.current_vmcs12 = NULL;
4620
4546 return &vmx->vcpu; 4621 return &vmx->vcpu;
4547 4622
4548free_vmcs: 4623free_vmcs: