diff options
Diffstat (limited to 'arch/powerpc/kvm/book3s.c')
-rw-r--r-- | arch/powerpc/kvm/book3s.c | 35 |
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 | ||
422 | pfn_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 | ||
555 | static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn) | 574 | static 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); |