diff options
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rm_mmu.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index fc3da3208fda..7a57ea49172d 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c | |||
@@ -600,6 +600,28 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags, | |||
600 | asm volatile("tlbiel %0" : : "r" (rb)); | 600 | asm volatile("tlbiel %0" : : "r" (rb)); |
601 | asm volatile("ptesync" : : : "memory"); | 601 | asm volatile("ptesync" : : : "memory"); |
602 | } | 602 | } |
603 | /* | ||
604 | * If the host has this page as readonly but the guest | ||
605 | * wants to make it read/write, reduce the permissions. | ||
606 | * Checking the host permissions involves finding the | ||
607 | * memslot and then the Linux PTE for the page. | ||
608 | */ | ||
609 | if (hpte_is_writable(r) && kvm->arch.using_mmu_notifiers) { | ||
610 | unsigned long psize, gfn, hva; | ||
611 | struct kvm_memory_slot *memslot; | ||
612 | pgd_t *pgdir = vcpu->arch.pgdir; | ||
613 | pte_t pte; | ||
614 | |||
615 | psize = hpte_page_size(v, r); | ||
616 | gfn = ((r & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT; | ||
617 | memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn); | ||
618 | if (memslot) { | ||
619 | hva = __gfn_to_hva_memslot(memslot, gfn); | ||
620 | pte = lookup_linux_pte(pgdir, hva, 1, &psize); | ||
621 | if (pte_present(pte) && !pte_write(pte)) | ||
622 | r = hpte_make_readonly(r); | ||
623 | } | ||
624 | } | ||
603 | } | 625 | } |
604 | hpte[1] = r; | 626 | hpte[1] = r; |
605 | eieio(); | 627 | eieio(); |