On Wed, 1 Dec 2021 at 17:04, 'Quentin Perret' via kernel-team <kernel-team@xxxxxxxxxxx> wrote: > > From: Will Deacon <will@xxxxxxxxxx> > > Implement kvm_pgtable_hyp_unmap() which can be used to remove hypervisor > stage-1 mappings at EL2. > > Signed-off-by: Will Deacon <will@xxxxxxxxxx> > Signed-off-by: Quentin Perret <qperret@xxxxxxxxxx> > --- > arch/arm64/include/asm/kvm_pgtable.h | 21 ++++++++++ > arch/arm64/kvm/hyp/pgtable.c | 63 ++++++++++++++++++++++++++++ > 2 files changed, 84 insertions(+) > > diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h > index 027783829584..9d076f36401d 100644 > --- a/arch/arm64/include/asm/kvm_pgtable.h > +++ b/arch/arm64/include/asm/kvm_pgtable.h > @@ -251,6 +251,27 @@ void kvm_pgtable_hyp_destroy(struct kvm_pgtable *pgt); > int kvm_pgtable_hyp_map(struct kvm_pgtable *pgt, u64 addr, u64 size, u64 phys, > enum kvm_pgtable_prot prot); > > +/** > + * kvm_pgtable_hyp_unmap() - Remove a mapping from a hypervisor stage-1 page-table. > + * @pgt: Page-table structure initialised by kvm_pgtable_hyp_init(). > + * @addr: Virtual address from which to remove the mapping. > + * @size: Size of the mapping. > + * > + * The offset of @addr within a page is ignored, @size is rounded-up to > + * the next page boundary and @phys is rounded-down to the previous page > + * boundary. > + * > + * TLB invalidation is performed for each page-table entry cleared during the > + * unmapping operation and the reference count for the page-table page > + * containing the cleared entry is decremented, with unreferenced pages being > + * freed. The unmapping operation will stop early if it encounters either an > + * invalid page-table entry or a valid block mapping which maps beyond the range > + * being unmapped. How is the caller expected to break up the block mapping? Why not handle that within this function? > > + * > + * Return: Number of bytes unmapped, which may be 0. > + */ > +u64 kvm_pgtable_hyp_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size); > + > /** > * kvm_get_vtcr() - Helper to construct VTCR_EL2 > * @mmfr0: Sanitized value of SYS_ID_AA64MMFR0_EL1 register. > diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c > index 768a58835153..6ad4cb2d6947 100644 > --- a/arch/arm64/kvm/hyp/pgtable.c > +++ b/arch/arm64/kvm/hyp/pgtable.c > @@ -463,6 +463,69 @@ int kvm_pgtable_hyp_map(struct kvm_pgtable *pgt, u64 addr, u64 size, u64 phys, > return ret; > } > > +struct hyp_unmap_data { > + u64 unmapped; > + struct kvm_pgtable_mm_ops *mm_ops; > +}; > + > +static int hyp_unmap_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep, > + enum kvm_pgtable_walk_flags flag, void * const arg) > +{ > + kvm_pte_t pte = *ptep, *childp = NULL; > + u64 granule = kvm_granule_size(level); > + struct hyp_unmap_data *data = arg; > + struct kvm_pgtable_mm_ops *mm_ops = data->mm_ops; > + > + if (!kvm_pte_valid(pte)) > + return -EINVAL; > + > + if (kvm_pte_table(pte, level)) { > + childp = kvm_pte_follow(pte, mm_ops); > + > + if (mm_ops->page_count(childp) != 1) > + return 0; > + > + kvm_clear_pte(ptep); > + dsb(ishst); > + __tlbi_level(vae2is, __TLBI_VADDR(addr, 0), level); > + } else { > + if (end - addr < granule) > + return -EINVAL; > + > + kvm_clear_pte(ptep); > + dsb(ishst); > + __tlbi_level(vale2is, __TLBI_VADDR(addr, 0), level); > + data->unmapped += granule; > + } > + > + dsb(ish); > + isb(); > + mm_ops->put_page(ptep); > + > + if (childp) > + mm_ops->put_page(childp); > + > + return 0; > +} > + > +u64 kvm_pgtable_hyp_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size) > +{ > + struct hyp_unmap_data unmap_data = { > + .mm_ops = pgt->mm_ops, > + }; > + struct kvm_pgtable_walker walker = { > + .cb = hyp_unmap_walker, > + .arg = &unmap_data, > + .flags = KVM_PGTABLE_WALK_LEAF | KVM_PGTABLE_WALK_TABLE_POST, > + }; > + > + if (!pgt->mm_ops->page_count) > + return 0; > + > + kvm_pgtable_walk(pgt, addr, size, &walker); > + return unmap_data.unmapped; > +} > + > int kvm_pgtable_hyp_init(struct kvm_pgtable *pgt, u32 va_bits, > struct kvm_pgtable_mm_ops *mm_ops) > { > -- > 2.34.0.rc2.393.gf8c9666880-goog > > -- > To unsubscribe from this group and stop receiving emails from it, send an email to kernel-team+unsubscribe@xxxxxxxxxxx. >
Attachment:
smime.p7s
Description: S/MIME Cryptographic Signature
_______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/mailman/listinfo/kvmarm