[RFC PATCH 1/2] KVM: arm64: Introduce S2 walker SKIP return options
Leonardo Bras
leo.bras at arm.com
Fri May 15 12:59:02 PDT 2026
Introduce S2 walker return values:
- SKIP_CHILDREN: skip walking the children of the current node
- SKIP_SIBLINGS: skip waling the siblings of the current node
Also, modify __kvm_pgtable_visit() to fulfil the hing on above return
values. Current walkers should not be impacted
Signed-off-by: Leonardo Bras <leo.bras at arm.com>
---
arch/arm64/kvm/hyp/pgtable.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index 0c1defa5fb0f..4e43339522bb 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -12,20 +12,26 @@
#include <asm/stage2_pgtable.h>
struct kvm_pgtable_walk_data {
struct kvm_pgtable_walker *walker;
const u64 start;
u64 addr;
const u64 end;
};
+/* Positive walker return values point levels to skip */
+enum walker_return{
+ SKIP_CHILDREN = 1,
+ SKIP_SIBLINGS
+};
+
static bool kvm_pgtable_walk_skip_bbm_tlbi(const struct kvm_pgtable_visit_ctx *ctx)
{
return unlikely(ctx->flags & KVM_PGTABLE_WALK_SKIP_BBM_TLBI);
}
static bool kvm_pgtable_walk_skip_cmo(const struct kvm_pgtable_visit_ctx *ctx)
{
return unlikely(ctx->flags & KVM_PGTABLE_WALK_SKIP_CMO);
}
@@ -134,21 +140,21 @@ static bool kvm_pgtable_walk_continue(const struct kvm_pgtable_walker *walker,
* update a PTE. In the context of a fault handler this is interpreted
* as a signal to retry guest execution.
*
* Ignore the return code altogether for walkers outside a fault handler
* (e.g. write protecting a range of memory) and chug along with the
* page table walk.
*/
if (r == -EAGAIN)
return walker->flags & KVM_PGTABLE_WALK_IGNORE_EAGAIN;
- return !r;
+ return r >= 0;
}
static int __kvm_pgtable_walk(struct kvm_pgtable_walk_data *data,
struct kvm_pgtable_mm_ops *mm_ops, kvm_pteref_t pgtable, s8 level);
static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data,
struct kvm_pgtable_mm_ops *mm_ops,
kvm_pteref_t pteref, s8 level)
{
enum kvm_pgtable_walk_flags flags = data->walker->flags;
@@ -185,23 +191,29 @@ static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data,
* into a newly installed or replaced table.
*/
if (reload) {
ctx.old = READ_ONCE(*ptep);
table = kvm_pte_table(ctx.old, level);
}
if (!kvm_pgtable_walk_continue(data->walker, ret))
goto out;
- if (!table) {
- data->addr = ALIGN_DOWN(data->addr, kvm_granule_size(level));
- data->addr += kvm_granule_size(level);
+ if (!table || ret >= SKIP_CHILDREN) {
+ u64 size;
+
+ if (ret == SKIP_SIBLINGS) /* Skip siblings */
+ size = kvm_granule_size(level - 1);
+ else /* Skip children */
+ size = kvm_granule_size(level);
+
+ data->addr = ALIGN_DOWN(data->addr, size) + size;
goto out;
}
childp = (kvm_pteref_t)kvm_pte_follow(ctx.old, mm_ops);
ret = __kvm_pgtable_walk(data, mm_ops, childp, level + 1);
if (!kvm_pgtable_walk_continue(data->walker, ret))
goto out;
if (ctx.flags & KVM_PGTABLE_WALK_TABLE_POST)
ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_TABLE_POST);
--
2.54.0
More information about the linux-arm-kernel
mailing list