From f42a0f71532b121bd40dd4c8bf13b17a6d64b7e7 Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Fri, 8 Oct 2021 11:08:02 +0100 Subject: [PATCH] ANDROID: KVM: arm64: Provide a helper to compute the size of stage-2 PGDs We will soon need to donate memory to the hypervisor in protected mode when creating guest VMs. The amount of memory to be donated will depend on the size of the (potentially concatenated) stage-2 PGD for that guest, among other things. To prepare the ground for this donation, introduce a helper in the KVM page-table library allowing to compute the size of a stage-2 PGD given a VTCR. Signed-off-by: Quentin Perret Bug: 209580772 Change-Id: I266f85d17415e72eb574afdb1d8b622d87b9fcc3 Signed-off-by: Will Deacon --- arch/arm64/include/asm/kvm_pgtable.h | 8 ++++++++ arch/arm64/kvm/hyp/pgtable.c | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h index 9f339dffbc1a..2d6b5058f7d3 100644 --- a/arch/arm64/include/asm/kvm_pgtable.h +++ b/arch/arm64/include/asm/kvm_pgtable.h @@ -288,6 +288,14 @@ u64 kvm_pgtable_hyp_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size); */ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift); +/* + * kvm_pgtable_stage2_pgd_size() - Helper to compute size of a stage-2 PGD + * @vtcr: Content of the VTCR register. + * + * Return: the size (in bytes) of the stage-2 PGD + */ +size_t kvm_pgtable_stage2_pgd_size(u64 vtcr); + /** * __kvm_pgtable_stage2_init() - Initialise a guest stage-2 page-table. * @pgt: Uninitialised page-table structure to initialise. diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index afbebef34044..c8a5c9cb20ef 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -1209,6 +1209,15 @@ int __kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu, return 0; } +size_t kvm_pgtable_stage2_pgd_size(u64 vtcr) +{ + u32 ia_bits = VTCR_EL2_IPA(vtcr); + u32 sl0 = FIELD_GET(VTCR_EL2_SL0_MASK, vtcr); + u32 start_level = VTCR_EL2_TGRAN_SL0_BASE - sl0; + + return kvm_pgd_pages(ia_bits, start_level) * PAGE_SIZE; +} + static int stage2_free_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep, enum kvm_pgtable_walk_flags flag, void * const arg)