[PATCH v5 01/14] KVM: arm64: Combine visitor arguments into a context structure
Ben Gardon
bgardon at google.com
Wed Nov 9 14:23:08 PST 2022
On Mon, Nov 7, 2022 at 1:57 PM Oliver Upton <oliver.upton at linux.dev> wrote:
>
> Passing new arguments by value to the visitor callbacks is extremely
> inflexible for stuffing new parameters used by only some of the
> visitors. Use a context structure instead and pass the pointer through
> to the visitor callback.
>
> While at it, redefine the 'flags' parameter to the visitor to contain
> the bit indicating the phase of the walk. Pass the entire set of flags
> through the context structure such that the walker can communicate
> additional state to the visitor callback.
>
> No functional change intended.
>
> Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
This looks good to me. It's all fairly mechanical and I don't see any
problems. I was a little confused by the walk context flags passed via
visit, because they seem somewhat redundant if the leaf-ness can be
determined by looking at the PTE, but perhaps that's not always
possible.
Reviewed-by: Ben Gardon <bgardon at google.com>
> ---
> arch/arm64/include/asm/kvm_pgtable.h | 15 +-
> arch/arm64/kvm/hyp/nvhe/mem_protect.c | 10 +-
> arch/arm64/kvm/hyp/nvhe/setup.c | 16 +-
> arch/arm64/kvm/hyp/pgtable.c | 269 +++++++++++++-------------
> 4 files changed, 154 insertions(+), 156 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
> index 3252eb50ecfe..607f9bb8aab4 100644
> --- a/arch/arm64/include/asm/kvm_pgtable.h
> +++ b/arch/arm64/include/asm/kvm_pgtable.h
> @@ -199,10 +199,17 @@ enum kvm_pgtable_walk_flags {
> KVM_PGTABLE_WALK_TABLE_POST = BIT(2),
> };
>
> -typedef int (*kvm_pgtable_visitor_fn_t)(u64 addr, u64 end, u32 level,
> - kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag,
> - void * const arg);
> +struct kvm_pgtable_visit_ctx {
> + kvm_pte_t *ptep;
> + void *arg;
> + u64 addr;
> + u64 end;
> + u32 level;
> + enum kvm_pgtable_walk_flags flags;
> +};
> +
> +typedef int (*kvm_pgtable_visitor_fn_t)(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit);
>
> /**
> * struct kvm_pgtable_walker - Hook into a page-table walk.
> diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> index 1e78acf9662e..8f5b6a36a039 100644
> --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> @@ -417,13 +417,11 @@ struct check_walk_data {
> enum pkvm_page_state (*get_page_state)(kvm_pte_t pte);
> };
>
> -static int __check_page_state_visitor(u64 addr, u64 end, u32 level,
> - kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag,
> - void * const arg)
> +static int __check_page_state_visitor(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> - struct check_walk_data *d = arg;
> - kvm_pte_t pte = *ptep;
> + struct check_walk_data *d = ctx->arg;
> + kvm_pte_t pte = *ctx->ptep;
>
> if (kvm_pte_valid(pte) && !addr_is_memory(kvm_pte_to_phys(pte)))
> return -EINVAL;
> diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
> index e8d4ea2fcfa0..a293cf5eba1b 100644
> --- a/arch/arm64/kvm/hyp/nvhe/setup.c
> +++ b/arch/arm64/kvm/hyp/nvhe/setup.c
> @@ -186,15 +186,13 @@ static void hpool_put_page(void *addr)
> hyp_put_page(&hpool, addr);
> }
>
> -static int finalize_host_mappings_walker(u64 addr, u64 end, u32 level,
> - kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag,
> - void * const arg)
> +static int finalize_host_mappings_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> - struct kvm_pgtable_mm_ops *mm_ops = arg;
> + struct kvm_pgtable_mm_ops *mm_ops = ctx->arg;
> enum kvm_pgtable_prot prot;
> enum pkvm_page_state state;
> - kvm_pte_t pte = *ptep;
> + kvm_pte_t pte = *ctx->ptep;
> phys_addr_t phys;
>
> if (!kvm_pte_valid(pte))
> @@ -205,11 +203,11 @@ static int finalize_host_mappings_walker(u64 addr, u64 end, u32 level,
> * was unable to access the hyp_vmemmap and so the buddy allocator has
> * initialised the refcount to '1'.
> */
> - mm_ops->get_page(ptep);
> - if (flag != KVM_PGTABLE_WALK_LEAF)
> + mm_ops->get_page(ctx->ptep);
> + if (visit != KVM_PGTABLE_WALK_LEAF)
> return 0;
>
> - if (level != (KVM_PGTABLE_MAX_LEVELS - 1))
> + if (ctx->level != (KVM_PGTABLE_MAX_LEVELS - 1))
> return -EINVAL;
>
> phys = kvm_pte_to_phys(pte);
> diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
> index cdf8e76b0be1..900c8b9c0cfc 100644
> --- a/arch/arm64/kvm/hyp/pgtable.c
> +++ b/arch/arm64/kvm/hyp/pgtable.c
> @@ -64,20 +64,20 @@ static bool kvm_phys_is_valid(u64 phys)
> return phys < BIT(id_aa64mmfr0_parange_to_phys_shift(ID_AA64MMFR0_EL1_PARANGE_MAX));
> }
>
> -static bool kvm_block_mapping_supported(u64 addr, u64 end, u64 phys, u32 level)
> +static bool kvm_block_mapping_supported(const struct kvm_pgtable_visit_ctx *ctx, u64 phys)
> {
> - u64 granule = kvm_granule_size(level);
> + u64 granule = kvm_granule_size(ctx->level);
>
> - if (!kvm_level_supports_block_mapping(level))
> + if (!kvm_level_supports_block_mapping(ctx->level))
> return false;
>
> - if (granule > (end - addr))
> + if (granule > (ctx->end - ctx->addr))
> return false;
>
> if (kvm_phys_is_valid(phys) && !IS_ALIGNED(phys, granule))
> return false;
>
> - return IS_ALIGNED(addr, granule);
> + return IS_ALIGNED(ctx->addr, granule);
> }
>
> static u32 kvm_pgtable_idx(struct kvm_pgtable_walk_data *data, u32 level)
> @@ -172,12 +172,12 @@ static kvm_pte_t kvm_init_invalid_leaf_owner(u8 owner_id)
> return FIELD_PREP(KVM_INVALID_PTE_OWNER_MASK, owner_id);
> }
>
> -static int kvm_pgtable_visitor_cb(struct kvm_pgtable_walk_data *data, u64 addr,
> - u32 level, kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag)
> +static int kvm_pgtable_visitor_cb(struct kvm_pgtable_walk_data *data,
> + const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> struct kvm_pgtable_walker *walker = data->walker;
> - return walker->cb(addr, data->end, level, ptep, flag, walker->arg);
> + return walker->cb(ctx, visit);
> }
>
> static int __kvm_pgtable_walk(struct kvm_pgtable_walk_data *data,
> @@ -186,20 +186,24 @@ static int __kvm_pgtable_walk(struct kvm_pgtable_walk_data *data,
> static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data,
> kvm_pte_t *ptep, u32 level)
> {
> + enum kvm_pgtable_walk_flags flags = data->walker->flags;
> + struct kvm_pgtable_visit_ctx ctx = {
> + .ptep = ptep,
> + .arg = data->walker->arg,
> + .addr = data->addr,
> + .end = data->end,
> + .level = level,
> + .flags = flags,
> + };
> int ret = 0;
> - u64 addr = data->addr;
> kvm_pte_t *childp, pte = *ptep;
> bool table = kvm_pte_table(pte, level);
> - enum kvm_pgtable_walk_flags flags = data->walker->flags;
>
> - if (table && (flags & KVM_PGTABLE_WALK_TABLE_PRE)) {
> - ret = kvm_pgtable_visitor_cb(data, addr, level, ptep,
> - KVM_PGTABLE_WALK_TABLE_PRE);
> - }
> + if (table && (ctx.flags & KVM_PGTABLE_WALK_TABLE_PRE))
> + ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_TABLE_PRE);
>
> - if (!table && (flags & KVM_PGTABLE_WALK_LEAF)) {
> - ret = kvm_pgtable_visitor_cb(data, addr, level, ptep,
> - KVM_PGTABLE_WALK_LEAF);
> + if (!table && (ctx.flags & KVM_PGTABLE_WALK_LEAF)) {
> + ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_LEAF);
> pte = *ptep;
> table = kvm_pte_table(pte, level);
> }
> @@ -218,10 +222,8 @@ static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data,
> if (ret)
> goto out;
>
> - if (flags & KVM_PGTABLE_WALK_TABLE_POST) {
> - ret = kvm_pgtable_visitor_cb(data, addr, level, ptep,
> - KVM_PGTABLE_WALK_TABLE_POST);
> - }
> + if (ctx.flags & KVM_PGTABLE_WALK_TABLE_POST)
> + ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_TABLE_POST);
>
> out:
> return ret;
> @@ -292,13 +294,13 @@ struct leaf_walk_data {
> u32 level;
> };
>
> -static int leaf_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag, void * const arg)
> +static int leaf_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> - struct leaf_walk_data *data = arg;
> + struct leaf_walk_data *data = ctx->arg;
>
> - data->pte = *ptep;
> - data->level = level;
> + data->pte = *ctx->ptep;
> + data->level = ctx->level;
>
> return 0;
> }
> @@ -383,47 +385,47 @@ enum kvm_pgtable_prot kvm_pgtable_hyp_pte_prot(kvm_pte_t pte)
> return prot;
> }
>
> -static bool hyp_map_walker_try_leaf(u64 addr, u64 end, u32 level,
> - kvm_pte_t *ptep, struct hyp_map_data *data)
> +static bool hyp_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx,
> + struct hyp_map_data *data)
> {
> - kvm_pte_t new, old = *ptep;
> - u64 granule = kvm_granule_size(level), phys = data->phys;
> + kvm_pte_t new, old = *ctx->ptep;
> + u64 granule = kvm_granule_size(ctx->level), phys = data->phys;
>
> - if (!kvm_block_mapping_supported(addr, end, phys, level))
> + if (!kvm_block_mapping_supported(ctx, phys))
> return false;
>
> data->phys += granule;
> - new = kvm_init_valid_leaf_pte(phys, data->attr, level);
> + new = kvm_init_valid_leaf_pte(phys, data->attr, ctx->level);
> if (old == new)
> return true;
> if (!kvm_pte_valid(old))
> - data->mm_ops->get_page(ptep);
> + data->mm_ops->get_page(ctx->ptep);
> else if (WARN_ON((old ^ new) & ~KVM_PTE_LEAF_ATTR_HI_SW))
> return false;
>
> - smp_store_release(ptep, new);
> + smp_store_release(ctx->ptep, new);
> return true;
> }
>
> -static int hyp_map_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag, void * const arg)
> +static int hyp_map_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> kvm_pte_t *childp;
> - struct hyp_map_data *data = arg;
> + struct hyp_map_data *data = ctx->arg;
> struct kvm_pgtable_mm_ops *mm_ops = data->mm_ops;
>
> - if (hyp_map_walker_try_leaf(addr, end, level, ptep, arg))
> + if (hyp_map_walker_try_leaf(ctx, data))
> return 0;
>
> - if (WARN_ON(level == KVM_PGTABLE_MAX_LEVELS - 1))
> + if (WARN_ON(ctx->level == KVM_PGTABLE_MAX_LEVELS - 1))
> return -EINVAL;
>
> childp = (kvm_pte_t *)mm_ops->zalloc_page(NULL);
> if (!childp)
> return -ENOMEM;
>
> - kvm_set_table_pte(ptep, childp, mm_ops);
> - mm_ops->get_page(ptep);
> + kvm_set_table_pte(ctx->ptep, childp, mm_ops);
> + mm_ops->get_page(ctx->ptep);
> return 0;
> }
>
> @@ -456,39 +458,39 @@ struct hyp_unmap_data {
> 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)
> +static int hyp_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> - kvm_pte_t pte = *ptep, *childp = NULL;
> - u64 granule = kvm_granule_size(level);
> - struct hyp_unmap_data *data = arg;
> + kvm_pte_t pte = *ctx->ptep, *childp = NULL;
> + u64 granule = kvm_granule_size(ctx->level);
> + struct hyp_unmap_data *data = ctx->arg;
> struct kvm_pgtable_mm_ops *mm_ops = data->mm_ops;
>
> if (!kvm_pte_valid(pte))
> return -EINVAL;
>
> - if (kvm_pte_table(pte, level)) {
> + if (kvm_pte_table(pte, ctx->level)) {
> childp = kvm_pte_follow(pte, mm_ops);
>
> if (mm_ops->page_count(childp) != 1)
> return 0;
>
> - kvm_clear_pte(ptep);
> + kvm_clear_pte(ctx->ptep);
> dsb(ishst);
> - __tlbi_level(vae2is, __TLBI_VADDR(addr, 0), level);
> + __tlbi_level(vae2is, __TLBI_VADDR(ctx->addr, 0), ctx->level);
> } else {
> - if (end - addr < granule)
> + if (ctx->end - ctx->addr < granule)
> return -EINVAL;
>
> - kvm_clear_pte(ptep);
> + kvm_clear_pte(ctx->ptep);
> dsb(ishst);
> - __tlbi_level(vale2is, __TLBI_VADDR(addr, 0), level);
> + __tlbi_level(vale2is, __TLBI_VADDR(ctx->addr, 0), ctx->level);
> data->unmapped += granule;
> }
>
> dsb(ish);
> isb();
> - mm_ops->put_page(ptep);
> + mm_ops->put_page(ctx->ptep);
>
> if (childp)
> mm_ops->put_page(childp);
> @@ -532,18 +534,18 @@ int kvm_pgtable_hyp_init(struct kvm_pgtable *pgt, u32 va_bits,
> return 0;
> }
>
> -static int hyp_free_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag, void * const arg)
> +static int hyp_free_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> - struct kvm_pgtable_mm_ops *mm_ops = arg;
> - kvm_pte_t pte = *ptep;
> + struct kvm_pgtable_mm_ops *mm_ops = ctx->arg;
> + kvm_pte_t pte = *ctx->ptep;
>
> if (!kvm_pte_valid(pte))
> return 0;
>
> - mm_ops->put_page(ptep);
> + mm_ops->put_page(ctx->ptep);
>
> - if (kvm_pte_table(pte, level))
> + if (kvm_pte_table(pte, ctx->level))
> mm_ops->put_page(kvm_pte_follow(pte, mm_ops));
>
> return 0;
> @@ -682,19 +684,19 @@ static bool stage2_pte_is_counted(kvm_pte_t pte)
> return !!pte;
> }
>
> -static void stage2_put_pte(kvm_pte_t *ptep, struct kvm_s2_mmu *mmu, u64 addr,
> - u32 level, struct kvm_pgtable_mm_ops *mm_ops)
> +static void stage2_put_pte(const struct kvm_pgtable_visit_ctx *ctx, struct kvm_s2_mmu *mmu,
> + struct kvm_pgtable_mm_ops *mm_ops)
> {
> /*
> * Clear the existing PTE, and perform break-before-make with
> * TLB maintenance if it was valid.
> */
> - if (kvm_pte_valid(*ptep)) {
> - kvm_clear_pte(ptep);
> - kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, addr, level);
> + if (kvm_pte_valid(*ctx->ptep)) {
> + kvm_clear_pte(ctx->ptep);
> + kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, ctx->level);
> }
>
> - mm_ops->put_page(ptep);
> + mm_ops->put_page(ctx->ptep);
> }
>
> static bool stage2_pte_cacheable(struct kvm_pgtable *pgt, kvm_pte_t pte)
> @@ -708,29 +710,28 @@ static bool stage2_pte_executable(kvm_pte_t pte)
> return !(pte & KVM_PTE_LEAF_ATTR_HI_S2_XN);
> }
>
> -static bool stage2_leaf_mapping_allowed(u64 addr, u64 end, u32 level,
> +static bool stage2_leaf_mapping_allowed(const struct kvm_pgtable_visit_ctx *ctx,
> struct stage2_map_data *data)
> {
> - if (data->force_pte && (level < (KVM_PGTABLE_MAX_LEVELS - 1)))
> + if (data->force_pte && (ctx->level < (KVM_PGTABLE_MAX_LEVELS - 1)))
> return false;
>
> - return kvm_block_mapping_supported(addr, end, data->phys, level);
> + return kvm_block_mapping_supported(ctx, data->phys);
> }
>
> -static int stage2_map_walker_try_leaf(u64 addr, u64 end, u32 level,
> - kvm_pte_t *ptep,
> +static int stage2_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx,
> struct stage2_map_data *data)
> {
> - kvm_pte_t new, old = *ptep;
> - u64 granule = kvm_granule_size(level), phys = data->phys;
> + kvm_pte_t new, old = *ctx->ptep;
> + u64 granule = kvm_granule_size(ctx->level), phys = data->phys;
> struct kvm_pgtable *pgt = data->mmu->pgt;
> struct kvm_pgtable_mm_ops *mm_ops = data->mm_ops;
>
> - if (!stage2_leaf_mapping_allowed(addr, end, level, data))
> + if (!stage2_leaf_mapping_allowed(ctx, data))
> return -E2BIG;
>
> if (kvm_phys_is_valid(phys))
> - new = kvm_init_valid_leaf_pte(phys, data->attr, level);
> + new = kvm_init_valid_leaf_pte(phys, data->attr, ctx->level);
> else
> new = kvm_init_invalid_leaf_owner(data->owner_id);
>
> @@ -744,7 +745,7 @@ static int stage2_map_walker_try_leaf(u64 addr, u64 end, u32 level,
> if (!stage2_pte_needs_update(old, new))
> return -EAGAIN;
>
> - stage2_put_pte(ptep, data->mmu, addr, level, mm_ops);
> + stage2_put_pte(ctx, data->mmu, mm_ops);
> }
>
> /* Perform CMOs before installation of the guest stage-2 PTE */
> @@ -755,26 +756,25 @@ static int stage2_map_walker_try_leaf(u64 addr, u64 end, u32 level,
> if (mm_ops->icache_inval_pou && stage2_pte_executable(new))
> mm_ops->icache_inval_pou(kvm_pte_follow(new, mm_ops), granule);
>
> - smp_store_release(ptep, new);
> + smp_store_release(ctx->ptep, new);
> if (stage2_pte_is_counted(new))
> - mm_ops->get_page(ptep);
> + mm_ops->get_page(ctx->ptep);
> if (kvm_phys_is_valid(phys))
> data->phys += granule;
> return 0;
> }
>
> -static int stage2_map_walk_table_pre(u64 addr, u64 end, u32 level,
> - kvm_pte_t *ptep,
> +static int stage2_map_walk_table_pre(const struct kvm_pgtable_visit_ctx *ctx,
> struct stage2_map_data *data)
> {
> if (data->anchor)
> return 0;
>
> - if (!stage2_leaf_mapping_allowed(addr, end, level, data))
> + if (!stage2_leaf_mapping_allowed(ctx, data))
> return 0;
>
> - data->childp = kvm_pte_follow(*ptep, data->mm_ops);
> - kvm_clear_pte(ptep);
> + data->childp = kvm_pte_follow(*ctx->ptep, data->mm_ops);
> + kvm_clear_pte(ctx->ptep);
>
> /*
> * Invalidate the whole stage-2, as we may have numerous leaf
> @@ -782,29 +782,29 @@ static int stage2_map_walk_table_pre(u64 addr, u64 end, u32 level,
> * individually.
> */
> kvm_call_hyp(__kvm_tlb_flush_vmid, data->mmu);
> - data->anchor = ptep;
> + data->anchor = ctx->ptep;
> return 0;
> }
>
> -static int stage2_map_walk_leaf(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> +static int stage2_map_walk_leaf(const struct kvm_pgtable_visit_ctx *ctx,
> struct stage2_map_data *data)
> {
> struct kvm_pgtable_mm_ops *mm_ops = data->mm_ops;
> - kvm_pte_t *childp, pte = *ptep;
> + kvm_pte_t *childp, pte = *ctx->ptep;
> int ret;
>
> if (data->anchor) {
> if (stage2_pte_is_counted(pte))
> - mm_ops->put_page(ptep);
> + mm_ops->put_page(ctx->ptep);
>
> return 0;
> }
>
> - ret = stage2_map_walker_try_leaf(addr, end, level, ptep, data);
> + ret = stage2_map_walker_try_leaf(ctx, data);
> if (ret != -E2BIG)
> return ret;
>
> - if (WARN_ON(level == KVM_PGTABLE_MAX_LEVELS - 1))
> + if (WARN_ON(ctx->level == KVM_PGTABLE_MAX_LEVELS - 1))
> return -EINVAL;
>
> if (!data->memcache)
> @@ -820,16 +820,15 @@ static int stage2_map_walk_leaf(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> * will be mapped lazily.
> */
> if (stage2_pte_is_counted(pte))
> - stage2_put_pte(ptep, data->mmu, addr, level, mm_ops);
> + stage2_put_pte(ctx, data->mmu, mm_ops);
>
> - kvm_set_table_pte(ptep, childp, mm_ops);
> - mm_ops->get_page(ptep);
> + kvm_set_table_pte(ctx->ptep, childp, mm_ops);
> + mm_ops->get_page(ctx->ptep);
>
> return 0;
> }
>
> -static int stage2_map_walk_table_post(u64 addr, u64 end, u32 level,
> - kvm_pte_t *ptep,
> +static int stage2_map_walk_table_post(const struct kvm_pgtable_visit_ctx *ctx,
> struct stage2_map_data *data)
> {
> struct kvm_pgtable_mm_ops *mm_ops = data->mm_ops;
> @@ -839,17 +838,17 @@ static int stage2_map_walk_table_post(u64 addr, u64 end, u32 level,
> if (!data->anchor)
> return 0;
>
> - if (data->anchor == ptep) {
> + if (data->anchor == ctx->ptep) {
> childp = data->childp;
> data->anchor = NULL;
> data->childp = NULL;
> - ret = stage2_map_walk_leaf(addr, end, level, ptep, data);
> + ret = stage2_map_walk_leaf(ctx, data);
> } else {
> - childp = kvm_pte_follow(*ptep, mm_ops);
> + childp = kvm_pte_follow(*ctx->ptep, mm_ops);
> }
>
> mm_ops->put_page(childp);
> - mm_ops->put_page(ptep);
> + mm_ops->put_page(ctx->ptep);
>
> return ret;
> }
> @@ -873,18 +872,18 @@ static int stage2_map_walk_table_post(u64 addr, u64 end, u32 level,
> * the page-table, installing the block entry when it revisits the anchor
> * pointer and clearing the anchor to NULL.
> */
> -static int stage2_map_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag, void * const arg)
> +static int stage2_map_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> - struct stage2_map_data *data = arg;
> + struct stage2_map_data *data = ctx->arg;
>
> - switch (flag) {
> + switch (visit) {
> case KVM_PGTABLE_WALK_TABLE_PRE:
> - return stage2_map_walk_table_pre(addr, end, level, ptep, data);
> + return stage2_map_walk_table_pre(ctx, data);
> case KVM_PGTABLE_WALK_LEAF:
> - return stage2_map_walk_leaf(addr, end, level, ptep, data);
> + return stage2_map_walk_leaf(ctx, data);
> case KVM_PGTABLE_WALK_TABLE_POST:
> - return stage2_map_walk_table_post(addr, end, level, ptep, data);
> + return stage2_map_walk_table_post(ctx, data);
> }
>
> return -EINVAL;
> @@ -949,25 +948,24 @@ int kvm_pgtable_stage2_set_owner(struct kvm_pgtable *pgt, u64 addr, u64 size,
> return ret;
> }
>
> -static int stage2_unmap_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag,
> - void * const arg)
> +static int stage2_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> - struct kvm_pgtable *pgt = arg;
> + struct kvm_pgtable *pgt = ctx->arg;
> struct kvm_s2_mmu *mmu = pgt->mmu;
> struct kvm_pgtable_mm_ops *mm_ops = pgt->mm_ops;
> - kvm_pte_t pte = *ptep, *childp = NULL;
> + kvm_pte_t pte = *ctx->ptep, *childp = NULL;
> bool need_flush = false;
>
> if (!kvm_pte_valid(pte)) {
> if (stage2_pte_is_counted(pte)) {
> - kvm_clear_pte(ptep);
> - mm_ops->put_page(ptep);
> + kvm_clear_pte(ctx->ptep);
> + mm_ops->put_page(ctx->ptep);
> }
> return 0;
> }
>
> - if (kvm_pte_table(pte, level)) {
> + if (kvm_pte_table(pte, ctx->level)) {
> childp = kvm_pte_follow(pte, mm_ops);
>
> if (mm_ops->page_count(childp) != 1)
> @@ -981,11 +979,11 @@ static int stage2_unmap_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> * block entry and rely on the remaining portions being faulted
> * back lazily.
> */
> - stage2_put_pte(ptep, mmu, addr, level, mm_ops);
> + stage2_put_pte(ctx, mmu, mm_ops);
>
> if (need_flush && mm_ops->dcache_clean_inval_poc)
> mm_ops->dcache_clean_inval_poc(kvm_pte_follow(pte, mm_ops),
> - kvm_granule_size(level));
> + kvm_granule_size(ctx->level));
>
> if (childp)
> mm_ops->put_page(childp);
> @@ -1012,18 +1010,17 @@ struct stage2_attr_data {
> struct kvm_pgtable_mm_ops *mm_ops;
> };
>
> -static int stage2_attr_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag,
> - void * const arg)
> +static int stage2_attr_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> - kvm_pte_t pte = *ptep;
> - struct stage2_attr_data *data = arg;
> + kvm_pte_t pte = *ctx->ptep;
> + struct stage2_attr_data *data = ctx->arg;
> struct kvm_pgtable_mm_ops *mm_ops = data->mm_ops;
>
> if (!kvm_pte_valid(pte))
> return 0;
>
> - data->level = level;
> + data->level = ctx->level;
> data->pte = pte;
> pte &= ~data->attr_clr;
> pte |= data->attr_set;
> @@ -1039,10 +1036,10 @@ static int stage2_attr_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> * stage-2 PTE if we are going to add executable permission.
> */
> if (mm_ops->icache_inval_pou &&
> - stage2_pte_executable(pte) && !stage2_pte_executable(*ptep))
> + stage2_pte_executable(pte) && !stage2_pte_executable(*ctx->ptep))
> mm_ops->icache_inval_pou(kvm_pte_follow(pte, mm_ops),
> - kvm_granule_size(level));
> - WRITE_ONCE(*ptep, pte);
> + kvm_granule_size(ctx->level));
> + WRITE_ONCE(*ctx->ptep, pte);
> }
>
> return 0;
> @@ -1140,20 +1137,19 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
> return ret;
> }
>
> -static int stage2_flush_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag,
> - void * const arg)
> +static int stage2_flush_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> - struct kvm_pgtable *pgt = arg;
> + struct kvm_pgtable *pgt = ctx->arg;
> struct kvm_pgtable_mm_ops *mm_ops = pgt->mm_ops;
> - kvm_pte_t pte = *ptep;
> + kvm_pte_t pte = *ctx->ptep;
>
> if (!kvm_pte_valid(pte) || !stage2_pte_cacheable(pgt, pte))
> return 0;
>
> if (mm_ops->dcache_clean_inval_poc)
> mm_ops->dcache_clean_inval_poc(kvm_pte_follow(pte, mm_ops),
> - kvm_granule_size(level));
> + kvm_granule_size(ctx->level));
> return 0;
> }
>
> @@ -1200,19 +1196,18 @@ int __kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu,
> return 0;
> }
>
> -static int stage2_free_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
> - enum kvm_pgtable_walk_flags flag,
> - void * const arg)
> +static int stage2_free_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> {
> - struct kvm_pgtable_mm_ops *mm_ops = arg;
> - kvm_pte_t pte = *ptep;
> + struct kvm_pgtable_mm_ops *mm_ops = ctx->arg;
> + kvm_pte_t pte = *ctx->ptep;
>
> if (!stage2_pte_is_counted(pte))
> return 0;
>
> - mm_ops->put_page(ptep);
> + mm_ops->put_page(ctx->ptep);
>
> - if (kvm_pte_table(pte, level))
> + if (kvm_pte_table(pte, ctx->level))
> mm_ops->put_page(kvm_pte_follow(pte, mm_ops));
>
> return 0;
> --
> 2.38.1.431.g37b22c650d-goog
>
More information about the linux-arm-kernel
mailing list