Skip to content

Commit 639e459

Browse files
dgibsonpaulusmack
authored andcommitted
KVM: PPC: Book3S HV: Create kvmppc_unmap_hpte_helper()
The kvm_unmap_rmapp() function, called from certain MMU notifiers, is used to force all guest mappings of a particular host page to be set ABSENT, and removed from the reverse mappings. For HPT resizing, we will have some cases where we want to set just a single guest HPTE ABSENT and remove its reverse mappings. To prepare with this, we split out the logic from kvm_unmap_rmapp() to evict a single HPTE, moving it to a new helper function. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 parent f98a8bf commit 639e459

File tree

1 file changed

+44
-33
lines changed

1 file changed

+44
-33
lines changed

arch/powerpc/kvm/book3s_64_mmu_hv.c

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -742,13 +742,53 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
742742
return kvm_handle_hva_range(kvm, hva, hva + 1, handler);
743743
}
744744

745+
/* Must be called with both HPTE and rmap locked */
746+
static void kvmppc_unmap_hpte(struct kvm *kvm, unsigned long i,
747+
unsigned long *rmapp, unsigned long gfn)
748+
{
749+
__be64 *hptep = (__be64 *) (kvm->arch.hpt.virt + (i << 4));
750+
struct revmap_entry *rev = kvm->arch.hpt.rev;
751+
unsigned long j, h;
752+
unsigned long ptel, psize, rcbits;
753+
754+
j = rev[i].forw;
755+
if (j == i) {
756+
/* chain is now empty */
757+
*rmapp &= ~(KVMPPC_RMAP_PRESENT | KVMPPC_RMAP_INDEX);
758+
} else {
759+
/* remove i from chain */
760+
h = rev[i].back;
761+
rev[h].forw = j;
762+
rev[j].back = h;
763+
rev[i].forw = rev[i].back = i;
764+
*rmapp = (*rmapp & ~KVMPPC_RMAP_INDEX) | j;
765+
}
766+
767+
/* Now check and modify the HPTE */
768+
ptel = rev[i].guest_rpte;
769+
psize = hpte_page_size(be64_to_cpu(hptep[0]), ptel);
770+
if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) &&
771+
hpte_rpn(ptel, psize) == gfn) {
772+
hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
773+
kvmppc_invalidate_hpte(kvm, hptep, i);
774+
hptep[1] &= ~cpu_to_be64(HPTE_R_KEY_HI | HPTE_R_KEY_LO);
775+
/* Harvest R and C */
776+
rcbits = be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
777+
*rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT;
778+
if (rcbits & HPTE_R_C)
779+
kvmppc_update_rmap_change(rmapp, psize);
780+
if (rcbits & ~rev[i].guest_rpte) {
781+
rev[i].guest_rpte = ptel | rcbits;
782+
note_hpte_modification(kvm, &rev[i]);
783+
}
784+
}
785+
}
786+
745787
static int kvm_unmap_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
746788
unsigned long gfn)
747789
{
748-
struct revmap_entry *rev = kvm->arch.hpt.rev;
749-
unsigned long h, i, j;
790+
unsigned long i;
750791
__be64 *hptep;
751-
unsigned long ptel, psize, rcbits;
752792
unsigned long *rmapp;
753793

754794
rmapp = &memslot->arch.rmap[gfn - memslot->base_gfn];
@@ -773,37 +813,8 @@ static int kvm_unmap_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
773813
cpu_relax();
774814
continue;
775815
}
776-
j = rev[i].forw;
777-
if (j == i) {
778-
/* chain is now empty */
779-
*rmapp &= ~(KVMPPC_RMAP_PRESENT | KVMPPC_RMAP_INDEX);
780-
} else {
781-
/* remove i from chain */
782-
h = rev[i].back;
783-
rev[h].forw = j;
784-
rev[j].back = h;
785-
rev[i].forw = rev[i].back = i;
786-
*rmapp = (*rmapp & ~KVMPPC_RMAP_INDEX) | j;
787-
}
788816

789-
/* Now check and modify the HPTE */
790-
ptel = rev[i].guest_rpte;
791-
psize = hpte_page_size(be64_to_cpu(hptep[0]), ptel);
792-
if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) &&
793-
hpte_rpn(ptel, psize) == gfn) {
794-
hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
795-
kvmppc_invalidate_hpte(kvm, hptep, i);
796-
hptep[1] &= ~cpu_to_be64(HPTE_R_KEY_HI | HPTE_R_KEY_LO);
797-
/* Harvest R and C */
798-
rcbits = be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
799-
*rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT;
800-
if (rcbits & HPTE_R_C)
801-
kvmppc_update_rmap_change(rmapp, psize);
802-
if (rcbits & ~rev[i].guest_rpte) {
803-
rev[i].guest_rpte = ptel | rcbits;
804-
note_hpte_modification(kvm, &rev[i]);
805-
}
806-
}
817+
kvmppc_unmap_hpte(kvm, i, rmapp, gfn);
807818
unlock_rmap(rmapp);
808819
__unlock_hpte(hptep, be64_to_cpu(hptep[0]));
809820
}

0 commit comments

Comments
 (0)