diff options
author | Avi Kivity <avi@qumranet.com> | 2007-01-05 19:36:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2007-01-06 02:55:24 -0500 |
commit | 1342d3536d6a12541ceb276da15f043db90716eb (patch) | |
tree | fefac89864ed7b34b466237e5c02fc783242b80e /drivers/kvm | |
parent | 6bcbd6aba00fced696fc99f1a4fcd7ac7d42d6ef (diff) |
[PATCH] KVM: MMU: Load the pae pdptrs on cr3 change like the processor does
In pae mode, a load of cr3 loads the four third-level page table entries in
addition to cr3 itself.
Signed-off-by: Avi Kivity <avi@qumranet.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/kvm')
-rw-r--r-- | drivers/kvm/kvm.h | 1 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 29 |
2 files changed, 20 insertions, 10 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index b65511ed4388..8323f4009362 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -185,6 +185,7 @@ struct kvm_vcpu { | |||
185 | unsigned long cr3; | 185 | unsigned long cr3; |
186 | unsigned long cr4; | 186 | unsigned long cr4; |
187 | unsigned long cr8; | 187 | unsigned long cr8; |
188 | u64 pdptrs[4]; /* pae */ | ||
188 | u64 shadow_efer; | 189 | u64 shadow_efer; |
189 | u64 apic_base; | 190 | u64 apic_base; |
190 | int nmsrs; | 191 | int nmsrs; |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index f2a6b6f0e929..4512d8c39c84 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -298,14 +298,17 @@ static void inject_gp(struct kvm_vcpu *vcpu) | |||
298 | kvm_arch_ops->inject_gp(vcpu, 0); | 298 | kvm_arch_ops->inject_gp(vcpu, 0); |
299 | } | 299 | } |
300 | 300 | ||
301 | static int pdptrs_have_reserved_bits_set(struct kvm_vcpu *vcpu, | 301 | /* |
302 | unsigned long cr3) | 302 | * Load the pae pdptrs. Return true is they are all valid. |
303 | */ | ||
304 | static int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3) | ||
303 | { | 305 | { |
304 | gfn_t pdpt_gfn = cr3 >> PAGE_SHIFT; | 306 | gfn_t pdpt_gfn = cr3 >> PAGE_SHIFT; |
305 | unsigned offset = (cr3 & (PAGE_SIZE-1)) >> 5; | 307 | unsigned offset = ((cr3 & (PAGE_SIZE-1)) >> 5) << 2; |
306 | int i; | 308 | int i; |
307 | u64 pdpte; | 309 | u64 pdpte; |
308 | u64 *pdpt; | 310 | u64 *pdpt; |
311 | int ret; | ||
309 | struct kvm_memory_slot *memslot; | 312 | struct kvm_memory_slot *memslot; |
310 | 313 | ||
311 | spin_lock(&vcpu->kvm->lock); | 314 | spin_lock(&vcpu->kvm->lock); |
@@ -313,16 +316,23 @@ static int pdptrs_have_reserved_bits_set(struct kvm_vcpu *vcpu, | |||
313 | /* FIXME: !memslot - emulate? 0xff? */ | 316 | /* FIXME: !memslot - emulate? 0xff? */ |
314 | pdpt = kmap_atomic(gfn_to_page(memslot, pdpt_gfn), KM_USER0); | 317 | pdpt = kmap_atomic(gfn_to_page(memslot, pdpt_gfn), KM_USER0); |
315 | 318 | ||
319 | ret = 1; | ||
316 | for (i = 0; i < 4; ++i) { | 320 | for (i = 0; i < 4; ++i) { |
317 | pdpte = pdpt[offset + i]; | 321 | pdpte = pdpt[offset + i]; |
318 | if ((pdpte & 1) && (pdpte & 0xfffffff0000001e6ull)) | 322 | if ((pdpte & 1) && (pdpte & 0xfffffff0000001e6ull)) { |
319 | break; | 323 | ret = 0; |
324 | goto out; | ||
325 | } | ||
320 | } | 326 | } |
321 | 327 | ||
328 | for (i = 0; i < 4; ++i) | ||
329 | vcpu->pdptrs[i] = pdpt[offset + i]; | ||
330 | |||
331 | out: | ||
322 | kunmap_atomic(pdpt, KM_USER0); | 332 | kunmap_atomic(pdpt, KM_USER0); |
323 | spin_unlock(&vcpu->kvm->lock); | 333 | spin_unlock(&vcpu->kvm->lock); |
324 | 334 | ||
325 | return i != 4; | 335 | return ret; |
326 | } | 336 | } |
327 | 337 | ||
328 | void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | 338 | void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) |
@@ -368,8 +378,7 @@ void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | |||
368 | } | 378 | } |
369 | } else | 379 | } else |
370 | #endif | 380 | #endif |
371 | if (is_pae(vcpu) && | 381 | if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->cr3)) { |
372 | pdptrs_have_reserved_bits_set(vcpu, vcpu->cr3)) { | ||
373 | printk(KERN_DEBUG "set_cr0: #GP, pdptrs " | 382 | printk(KERN_DEBUG "set_cr0: #GP, pdptrs " |
374 | "reserved bits\n"); | 383 | "reserved bits\n"); |
375 | inject_gp(vcpu); | 384 | inject_gp(vcpu); |
@@ -411,7 +420,7 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | |||
411 | return; | 420 | return; |
412 | } | 421 | } |
413 | } else if (is_paging(vcpu) && !is_pae(vcpu) && (cr4 & CR4_PAE_MASK) | 422 | } else if (is_paging(vcpu) && !is_pae(vcpu) && (cr4 & CR4_PAE_MASK) |
414 | && pdptrs_have_reserved_bits_set(vcpu, vcpu->cr3)) { | 423 | && !load_pdptrs(vcpu, vcpu->cr3)) { |
415 | printk(KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n"); | 424 | printk(KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n"); |
416 | inject_gp(vcpu); | 425 | inject_gp(vcpu); |
417 | } | 426 | } |
@@ -443,7 +452,7 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) | |||
443 | return; | 452 | return; |
444 | } | 453 | } |
445 | if (is_paging(vcpu) && is_pae(vcpu) && | 454 | if (is_paging(vcpu) && is_pae(vcpu) && |
446 | pdptrs_have_reserved_bits_set(vcpu, cr3)) { | 455 | !load_pdptrs(vcpu, cr3)) { |
447 | printk(KERN_DEBUG "set_cr3: #GP, pdptrs " | 456 | printk(KERN_DEBUG "set_cr3: #GP, pdptrs " |
448 | "reserved bits\n"); | 457 | "reserved bits\n"); |
449 | inject_gp(vcpu); | 458 | inject_gp(vcpu); |