Skip to content

Commit 32b48bf

Browse files
npigginmpe
authored andcommitted
KVM: PPC: Book3S HV: Fix conversion to gfn-based MMU notifier callbacks
Commit b1c5356 ("KVM: PPC: Convert to the gfn-based MMU notifier callbacks") causes unmap_gfn_range and age_gfn callbacks to only work on the first gfn in the range. It also makes the aging callbacks call into both radix and hash aging functions for radix guests. Fix this. Add warnings for the single-gfn calls that have been converted to range callbacks, in case they ever receieve ranges greater than 1. Fixes: b1c5356 ("KVM: PPC: Convert to the gfn-based MMU notifier callbacks") Reported-by: Bharata B Rao <[email protected]> Signed-off-by: Nicholas Piggin <[email protected]> Tested-by: Bharata B Rao <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent c6b05f4 commit 32b48bf

File tree

3 files changed

+36
-17
lines changed

3 files changed

+36
-17
lines changed

arch/powerpc/include/asm/kvm_book3s.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ extern void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd,
210210
unsigned int lpid);
211211
extern int kvmppc_radix_init(void);
212212
extern void kvmppc_radix_exit(void);
213-
extern bool kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
213+
extern void kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
214214
unsigned long gfn);
215215
extern bool kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
216216
unsigned long gfn);

arch/powerpc/kvm/book3s_64_mmu_hv.c

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ static void kvmppc_unmap_hpte(struct kvm *kvm, unsigned long i,
795795
}
796796
}
797797

798-
static bool kvm_unmap_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
798+
static void kvm_unmap_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
799799
unsigned long gfn)
800800
{
801801
unsigned long i;
@@ -829,15 +829,21 @@ static bool kvm_unmap_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
829829
unlock_rmap(rmapp);
830830
__unlock_hpte(hptep, be64_to_cpu(hptep[0]));
831831
}
832-
return false;
833832
}
834833

835834
bool kvm_unmap_gfn_range_hv(struct kvm *kvm, struct kvm_gfn_range *range)
836835
{
837-
if (kvm_is_radix(kvm))
838-
return kvm_unmap_radix(kvm, range->slot, range->start);
836+
gfn_t gfn;
837+
838+
if (kvm_is_radix(kvm)) {
839+
for (gfn = range->start; gfn < range->end; gfn++)
840+
kvm_unmap_radix(kvm, range->slot, gfn);
841+
} else {
842+
for (gfn = range->start; gfn < range->end; gfn++)
843+
kvm_unmap_rmapp(kvm, range->slot, range->start);
844+
}
839845

840-
return kvm_unmap_rmapp(kvm, range->slot, range->start);
846+
return false;
841847
}
842848

843849
void kvmppc_core_flush_memslot_hv(struct kvm *kvm,
@@ -924,10 +930,18 @@ static bool kvm_age_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
924930

925931
bool kvm_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range)
926932
{
927-
if (kvm_is_radix(kvm))
928-
kvm_age_radix(kvm, range->slot, range->start);
933+
gfn_t gfn;
934+
bool ret = false;
929935

930-
return kvm_age_rmapp(kvm, range->slot, range->start);
936+
if (kvm_is_radix(kvm)) {
937+
for (gfn = range->start; gfn < range->end; gfn++)
938+
ret |= kvm_age_radix(kvm, range->slot, gfn);
939+
} else {
940+
for (gfn = range->start; gfn < range->end; gfn++)
941+
ret |= kvm_age_rmapp(kvm, range->slot, gfn);
942+
}
943+
944+
return ret;
931945
}
932946

933947
static bool kvm_test_age_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
@@ -965,18 +979,24 @@ static bool kvm_test_age_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
965979

966980
bool kvm_test_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range)
967981
{
968-
if (kvm_is_radix(kvm))
969-
kvm_test_age_radix(kvm, range->slot, range->start);
982+
WARN_ON(range->start + 1 != range->end);
970983

971-
return kvm_test_age_rmapp(kvm, range->slot, range->start);
984+
if (kvm_is_radix(kvm))
985+
return kvm_test_age_radix(kvm, range->slot, range->start);
986+
else
987+
return kvm_test_age_rmapp(kvm, range->slot, range->start);
972988
}
973989

974990
bool kvm_set_spte_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range)
975991
{
992+
WARN_ON(range->start + 1 != range->end);
993+
976994
if (kvm_is_radix(kvm))
977-
return kvm_unmap_radix(kvm, range->slot, range->start);
995+
kvm_unmap_radix(kvm, range->slot, range->start);
996+
else
997+
kvm_unmap_rmapp(kvm, range->slot, range->start);
978998

979-
return kvm_unmap_rmapp(kvm, range->slot, range->start);
999+
return false;
9801000
}
9811001

9821002
static int vcpus_running(struct kvm *kvm)

arch/powerpc/kvm/book3s_64_mmu_radix.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,7 @@ int kvmppc_book3s_radix_page_fault(struct kvm_vcpu *vcpu,
993993
}
994994

995995
/* Called with kvm->mmu_lock held */
996-
bool kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
996+
void kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
997997
unsigned long gfn)
998998
{
999999
pte_t *ptep;
@@ -1002,14 +1002,13 @@ bool kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
10021002

10031003
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE) {
10041004
uv_page_inval(kvm->arch.lpid, gpa, PAGE_SHIFT);
1005-
return false;
1005+
return;
10061006
}
10071007

10081008
ptep = find_kvm_secondary_pte(kvm, gpa, &shift);
10091009
if (ptep && pte_present(*ptep))
10101010
kvmppc_unmap_pte(kvm, ptep, gpa, shift, memslot,
10111011
kvm->arch.lpid);
1012-
return false;
10131012
}
10141013

10151014
/* Called with kvm->mmu_lock held */

0 commit comments

Comments
 (0)