[PATCH v5 1/5] KVM: arm64: Pass walk flags to kvm_pgtable_get_leaf()
Jack Thomson
jackabt.amazon at gmail.com
Fri Jun 12 09:23:49 PDT 2026
From: Jack Thomson <jackabt at amazon.com>
Allow callers of kvm_pgtable_get_leaf() to specify the page-table walk
flags, in preparation for performing walks under the MMU read lock.
Reading a stage-2 leaf while only holding the read lock requires
KVM_PGTABLE_WALK_SHARED: parallel faults (which also only hold the read
lock) can unlink table pages and free them via RCU, so the walker must
be inside an RCU read-side critical section, which the shared walk flag
provides via kvm_pgtable_walk_begin().
All existing callers either hold the write lock, walk with interrupts
disabled, or run at hyp where shared walks are rejected; they keep the
current behaviour by passing no flags.
No functional change intended.
Signed-off-by: Jack Thomson <jackabt at amazon.com>
---
arch/arm64/include/asm/kvm_pgtable.h | 5 ++++-
arch/arm64/kvm/hyp/nvhe/mem_protect.c | 10 +++++-----
arch/arm64/kvm/hyp/pgtable.c | 5 +++--
arch/arm64/kvm/mmu.c | 2 +-
arch/arm64/kvm/nested.c | 2 +-
5 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
index 41a8687938eb..d0167f7dfbee 100644
--- a/arch/arm64/include/asm/kvm_pgtable.h
+++ b/arch/arm64/include/asm/kvm_pgtable.h
@@ -859,6 +859,8 @@ int kvm_pgtable_walk(struct kvm_pgtable *pgt, u64 addr, u64 size,
* @addr: Input address for the start of the walk.
* @ptep: Pointer to storage for the retrieved PTE.
* @level: Pointer to storage for the level of the retrieved PTE.
+ * @flags: Flags to control the page-table walk
+ * (see struct kvm_pgtable_visit_ctx).
*
* The offset of @addr within a page is ignored.
*
@@ -869,7 +871,8 @@ int kvm_pgtable_walk(struct kvm_pgtable *pgt, u64 addr, u64 size,
* Return: 0 on success, negative error code on failure.
*/
int kvm_pgtable_get_leaf(struct kvm_pgtable *pgt, u64 addr,
- kvm_pte_t *ptep, s8 *level);
+ kvm_pte_t *ptep, s8 *level,
+ enum kvm_pgtable_walk_flags flags);
/**
* kvm_pgtable_stage2_pte_prot() - Retrieve the protection attributes of a
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 25f04629014e..3b765c9ff7e8 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -522,7 +522,7 @@ static int host_stage2_adjust_range(u64 addr, struct kvm_mem_range *range)
int ret;
hyp_assert_lock_held(&host_mmu.lock);
- ret = kvm_pgtable_get_leaf(&host_mmu.pgt, addr, &pte, &level);
+ ret = kvm_pgtable_get_leaf(&host_mmu.pgt, addr, &pte, &level, 0);
if (ret)
return ret;
@@ -890,7 +890,7 @@ static int get_valid_guest_pte(struct pkvm_hyp_vm *vm, u64 ipa, kvm_pte_t *ptep,
s8 level;
int ret;
- ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level);
+ ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level, 0);
if (ret)
return ret;
if (guest_pte_is_poisoned(pte))
@@ -939,7 +939,7 @@ int __pkvm_vcpu_in_poison_fault(struct pkvm_hyp_vcpu *hyp_vcpu)
ipa |= FAR_TO_FIPA_OFFSET(kvm_vcpu_get_hfar(&hyp_vcpu->vcpu));
guest_lock_component(vm);
- ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level);
+ ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level, 0);
if (ret)
goto unlock;
@@ -1293,7 +1293,7 @@ static int host_stage2_get_guest_info(phys_addr_t phys, struct pkvm_hyp_vm **vm,
return -EPERM;
}
- ret = kvm_pgtable_get_leaf(&host_mmu.pgt, phys, &pte, &level);
+ ret = kvm_pgtable_get_leaf(&host_mmu.pgt, phys, &pte, &level, 0);
if (ret)
return ret;
@@ -1522,7 +1522,7 @@ static int __check_host_shared_guest(struct pkvm_hyp_vm *vm, u64 *__phys, u64 ip
s8 level;
int ret;
- ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level);
+ ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level, 0);
if (ret)
return ret;
if (!kvm_pte_valid(pte))
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index 0c1defa5fb0f..6a839a32e246 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -298,12 +298,13 @@ static int leaf_walker(const struct kvm_pgtable_visit_ctx *ctx,
}
int kvm_pgtable_get_leaf(struct kvm_pgtable *pgt, u64 addr,
- kvm_pte_t *ptep, s8 *level)
+ kvm_pte_t *ptep, s8 *level,
+ enum kvm_pgtable_walk_flags flags)
{
struct leaf_walk_data data;
struct kvm_pgtable_walker walker = {
.cb = leaf_walker,
- .flags = KVM_PGTABLE_WALK_LEAF,
+ .flags = flags | KVM_PGTABLE_WALK_LEAF,
.arg = &data,
};
int ret;
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 4da9281312eb..c720f07cb82e 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -839,7 +839,7 @@ static int get_user_mapping_size(struct kvm *kvm, u64 addr)
* IPI-ing threads).
*/
local_irq_save(flags);
- ret = kvm_pgtable_get_leaf(&pgt, addr, &pte, &level);
+ ret = kvm_pgtable_get_leaf(&pgt, addr, &pte, &level, 0);
local_irq_restore(flags);
if (ret)
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 38f672e94087..e45aed6d9e65 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -559,7 +559,7 @@ static u8 get_guest_mapping_ttl(struct kvm_s2_mmu *mmu, u64 addr)
return 0;
tmp &= ~(sz - 1);
- if (kvm_pgtable_get_leaf(mmu->pgt, tmp, &pte, NULL))
+ if (kvm_pgtable_get_leaf(mmu->pgt, tmp, &pte, NULL, 0))
goto again;
if (!(pte & PTE_VALID))
goto again;
--
2.43.0
More information about the linux-arm-kernel
mailing list