[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200930052336.GD29405@linux.intel.com>
Date: Tue, 29 Sep 2020 22:24:10 -0700
From: Sean Christopherson <sean.j.christopherson@...el.com>
To: Ben Gardon <bgardon@...gle.com>
Cc: linux-kernel@...r.kernel.org, kvm@...r.kernel.org,
Cannon Matthews <cannonmatthews@...gle.com>,
Paolo Bonzini <pbonzini@...hat.com>,
Peter Xu <peterx@...hat.com>, Peter Shier <pshier@...gle.com>,
Peter Feiner <pfeiner@...gle.com>,
Junaid Shahid <junaids@...gle.com>,
Jim Mattson <jmattson@...gle.com>,
Yulei Zhang <yulei.kernel@...il.com>,
Wanpeng Li <kernellwp@...il.com>,
Vitaly Kuznetsov <vkuznets@...hat.com>,
Xiao Guangrong <xiaoguangrong.eric@...il.com>
Subject: Re: [PATCH 02/22] kvm: mmu: Introduce tdp_iter
On Fri, Sep 25, 2020 at 02:22:42PM -0700, Ben Gardon wrote:
> diff --git a/arch/x86/kvm/mmu/tdp_iter.c b/arch/x86/kvm/mmu/tdp_iter.c
> new file mode 100644
> index 0000000000000..ee90d62d2a9b1
> --- /dev/null
> +++ b/arch/x86/kvm/mmu/tdp_iter.c
> @@ -0,0 +1,163 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#include "mmu_internal.h"
> +#include "tdp_iter.h"
> +
> +/*
> + * Recalculates the pointer to the SPTE for the current GFN and level and
> + * reread the SPTE.
> + */
> +static void tdp_iter_refresh_sptep(struct tdp_iter *iter)
> +{
> + iter->sptep = iter->pt_path[iter->level - 1] +
> + SHADOW_PT_INDEX(iter->gfn << PAGE_SHIFT, iter->level);
> + iter->old_spte = READ_ONCE(*iter->sptep);
> +}
> +
> +/*
> + * Sets a TDP iterator to walk a pre-order traversal of the paging structure
> + * rooted at root_pt, starting with the walk to translate goal_gfn.
> + */
> +void tdp_iter_start(struct tdp_iter *iter, u64 *root_pt, int root_level,
> + gfn_t goal_gfn)
> +{
> + WARN_ON(root_level < 1);
> + WARN_ON(root_level > PT64_ROOT_MAX_LEVEL);
> +
> + iter->goal_gfn = goal_gfn;
> + iter->root_level = root_level;
> + iter->level = root_level;
> + iter->pt_path[iter->level - 1] = root_pt;
> +
> + iter->gfn = iter->goal_gfn -
> + (iter->goal_gfn % KVM_PAGES_PER_HPAGE(iter->level));
Maybe use the params, if only to avoid the line wrap?
iter->gfn = goal_gfn - (goal_gfn % KVM_PAGES_PER_HPAGE(root_level));
Actually, peeking further into the file, this calculation is repeated in both
try_step_up and try_step_down, probably worth adding a helper of some form.
> + tdp_iter_refresh_sptep(iter);
> +
> + iter->valid = true;
> +}
> +
> +/*
> + * Given an SPTE and its level, returns a pointer containing the host virtual
> + * address of the child page table referenced by the SPTE. Returns null if
> + * there is no such entry.
> + */
> +u64 *spte_to_child_pt(u64 spte, int level)
> +{
> + u64 *pt;
> + /* There's no child entry if this entry isn't present */
> + if (!is_shadow_present_pte(spte))
> + return NULL;
> +
> + /* There is no child page table if this is a leaf entry. */
> + if (is_last_spte(spte, level))
> + return NULL;
I'd collapse the checks and their comments.
> +
> + pt = (u64 *)__va(spte_to_pfn(spte) << PAGE_SHIFT);
> + return pt;
No need for the local variable or the explicit cast.
/* There's no child if this entry is non-present or a leaf entry. */
if (!is_shadow_present_pte(spte) || is_last_spte(spte, level))
return NULL;
return __va(spte_to_pfn(spte) << PAGE_SHIFT);
> +}
...
> +void tdp_iter_next(struct tdp_iter *iter)
> +{
> + bool done;
> +
> + done = try_step_down(iter);
> + if (done)
> + return;
> +
> + done = try_step_side(iter);
> + while (!done) {
> + if (!try_step_up(iter)) {
> + iter->valid = false;
> + break;
> + }
> + done = try_step_side(iter);
> + }
At the risk of being too clever:
bool done;
if (try_step_down(iter))
return;
do {
done = try_step_side(iter);
} while (!done && try_step_up(iter));
iter->valid = done;
> +}
Powered by blists - more mailing lists