aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-07-29 08:47:54 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:50:48 -0400
commite8508940a88691ad3d1c46608cd968eb4be9cbc5 (patch)
treec14d6cbc9c947cdbf69a255f04d44024a79ed6e6 /arch/powerpc/kvm/book3s.c
parentbeb03f14da9ceff76ff08cbb8af064b52dc21f7e (diff)
KVM: PPC: Magic Page Book3s support
We need to override EA as well as PA lookups for the magic page. When the guest tells us to project it, the magic page overrides any guest mappings. In order to reflect that, we need to hook into all the MMU layers of KVM to force map the magic page if necessary. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm/book3s.c')
-rw-r--r--arch/powerpc/kvm/book3s.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 0ed5376df82c..eee97b5a7400 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -419,6 +419,25 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
419 } 419 }
420} 420}
421 421
422pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn)
423{
424 ulong mp_pa = vcpu->arch.magic_page_pa;
425
426 /* Magic page override */
427 if (unlikely(mp_pa) &&
428 unlikely(((gfn << PAGE_SHIFT) & KVM_PAM) ==
429 ((mp_pa & PAGE_MASK) & KVM_PAM))) {
430 ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK;
431 pfn_t pfn;
432
433 pfn = (pfn_t)virt_to_phys((void*)shared_page) >> PAGE_SHIFT;
434 get_page(pfn_to_page(pfn));
435 return pfn;
436 }
437
438 return gfn_to_pfn(vcpu->kvm, gfn);
439}
440
422/* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To 441/* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To
423 * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to 442 * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to
424 * emulate 32 bytes dcbz length. 443 * emulate 32 bytes dcbz length.
@@ -554,6 +573,13 @@ mmio:
554 573
555static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn) 574static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
556{ 575{
576 ulong mp_pa = vcpu->arch.magic_page_pa;
577
578 if (unlikely(mp_pa) &&
579 unlikely((mp_pa & KVM_PAM) >> PAGE_SHIFT == gfn)) {
580 return 1;
581 }
582
557 return kvm_is_visible_gfn(vcpu->kvm, gfn); 583 return kvm_is_visible_gfn(vcpu->kvm, gfn);
558} 584}
559 585
@@ -1257,6 +1283,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
1257 struct kvmppc_vcpu_book3s *vcpu_book3s; 1283 struct kvmppc_vcpu_book3s *vcpu_book3s;
1258 struct kvm_vcpu *vcpu; 1284 struct kvm_vcpu *vcpu;
1259 int err = -ENOMEM; 1285 int err = -ENOMEM;
1286 unsigned long p;
1260 1287
1261 vcpu_book3s = vmalloc(sizeof(struct kvmppc_vcpu_book3s)); 1288 vcpu_book3s = vmalloc(sizeof(struct kvmppc_vcpu_book3s));
1262 if (!vcpu_book3s) 1289 if (!vcpu_book3s)
@@ -1274,8 +1301,10 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
1274 if (err) 1301 if (err)
1275 goto free_shadow_vcpu; 1302 goto free_shadow_vcpu;
1276 1303
1277 vcpu->arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO); 1304 p = __get_free_page(GFP_KERNEL|__GFP_ZERO);
1278 if (!vcpu->arch.shared) 1305 /* the real shared page fills the last 4k of our page */
1306 vcpu->arch.shared = (void*)(p + PAGE_SIZE - 4096);
1307 if (!p)
1279 goto uninit_vcpu; 1308 goto uninit_vcpu;
1280 1309
1281 vcpu->arch.host_retip = kvm_return_point; 1310 vcpu->arch.host_retip = kvm_return_point;
@@ -1322,7 +1351,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
1322{ 1351{
1323 struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); 1352 struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
1324 1353
1325 free_page((unsigned long)vcpu->arch.shared); 1354 free_page((unsigned long)vcpu->arch.shared & PAGE_MASK);
1326 kvm_vcpu_uninit(vcpu); 1355 kvm_vcpu_uninit(vcpu);
1327 kfree(vcpu_book3s->shadow_vcpu); 1356 kfree(vcpu_book3s->shadow_vcpu);
1328 vfree(vcpu_book3s); 1357 vfree(vcpu_book3s);