Message ID | 20210622175739.3610207-26-seanjc@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: x86/mmu: Bug fixes and summer cleaning | expand |
On 22/06/21 19:57, Sean Christopherson wrote: > +static inline bool is_##reg##_##name(struct kvm_mmu *mmu) \ What do you think about calling these is_mmu_##name? The point of having these helpers is that the register doesn't count, and they return the effective value (e.g. false in most EPT cases). Paolo > +{ \ > + return !!(mmu->mmu_role. base_or_ext . reg##_##name); \ > +} > +BUILD_MMU_ROLE_ACCESSOR(ext, cr0, pg); > +BUILD_MMU_ROLE_ACCESSOR(base, cr0, wp); > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pse); > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pae); > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, smep); > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, smap); > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pke); > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, la57); > +BUILD_MMU_ROLE_ACCESSOR(base, efer, nx); > + > struct kvm_mmu_role_regs vcpu_to_role_regs(struct kvm_vcpu *vcpu)
On Wed, Jun 23, 2021, Paolo Bonzini wrote: > On 22/06/21 19:57, Sean Christopherson wrote: > > +static inline bool is_##reg##_##name(struct kvm_mmu *mmu) \ > > What do you think about calling these is_mmu_##name? The point of having > these helpers is that the register doesn't count, and they return the > effective value (e.g. false in most EPT cases). I strongly prefer to keep <reg> in the name, both to match the mmu_role bits and to make it a bit more clear that it's reflective (modified) register state, as opposed to PTEs or even something else entirely. E.g. I always struggled to remember the purpose of mmu->nx flag. I wouldn't be opposed to is_mmu_##reg##_##name() though. I omitted the "mmu" part because it was loosely implied by the "struct kvm_mmu" param, and to keep line lengths short. But being explicit is usually a good thing, and looking at the code I don't see any lines that would wrap if "mmu" were added. > > +{ \ > > + return !!(mmu->mmu_role. base_or_ext . reg##_##name); \ > > +} > > +BUILD_MMU_ROLE_ACCESSOR(ext, cr0, pg); > > +BUILD_MMU_ROLE_ACCESSOR(base, cr0, wp); > > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pse); > > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pae); > > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, smep); > > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, smap); > > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pke); > > +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, la57); > > +BUILD_MMU_ROLE_ACCESSOR(base, efer, nx); > > + > > struct kvm_mmu_role_regs vcpu_to_role_regs(struct kvm_vcpu *vcpu) >
On 23/06/21 22:47, Sean Christopherson wrote: >> What do you think about calling these is_mmu_##name? The point of having >> these helpers is that the register doesn't count, and they return the >> effective value (e.g. false in most EPT cases). > > I strongly prefer to keep <reg> in the name, both to match the mmu_role bits and > to make it a bit more clear that it's reflective (modified) register state, as > opposed to PTEs or even something else entirely. E.g. I always struggled to > remember the purpose of mmu->nx flag. No problem. I do disagree that it's register state ("modified" seems to be more than a parenthetical remark), but not enough to argue about it and even less to do the work to rename the accessors. Paolo
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 7bc5b1a8fca5..be95595b30c7 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -206,6 +206,27 @@ BUILD_MMU_ROLE_REGS_ACCESSOR(cr4, la57, X86_CR4_LA57); BUILD_MMU_ROLE_REGS_ACCESSOR(efer, nx, EFER_NX); BUILD_MMU_ROLE_REGS_ACCESSOR(efer, lma, EFER_LMA); +/* + * The MMU itself (with a valid role) is the single source of truth for the + * MMU. Do not use the regs used to build the MMU/role, nor the vCPU. The + * regs don't account for dependencies, e.g. clearing CR4 bits if CR0.PG=1, + * and the vCPU may be incorrect/irrelevant. + */ +#define BUILD_MMU_ROLE_ACCESSOR(base_or_ext, reg, name) \ +static inline bool is_##reg##_##name(struct kvm_mmu *mmu) \ +{ \ + return !!(mmu->mmu_role. base_or_ext . reg##_##name); \ +} +BUILD_MMU_ROLE_ACCESSOR(ext, cr0, pg); +BUILD_MMU_ROLE_ACCESSOR(base, cr0, wp); +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pse); +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pae); +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, smep); +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, smap); +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pke); +BUILD_MMU_ROLE_ACCESSOR(ext, cr4, la57); +BUILD_MMU_ROLE_ACCESSOR(base, efer, nx); + struct kvm_mmu_role_regs vcpu_to_role_regs(struct kvm_vcpu *vcpu) { struct kvm_mmu_role_regs regs = { diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h index b632606a87d6..5cf36eb96ee2 100644 --- a/arch/x86/kvm/mmu/paging_tmpl.h +++ b/arch/x86/kvm/mmu/paging_tmpl.h @@ -471,7 +471,7 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker, error: errcode |= write_fault | user_fault; - if (fetch_fault && (mmu->nx || mmu->mmu_role.ext.cr4_smep)) + if (fetch_fault && (mmu->nx || is_cr4_smep(mmu))) errcode |= PFERR_FETCH_MASK; walker->fault.vector = PF_VECTOR;
Add helpers via a builder macro for all mmu_role bits that track a CR0, CR4, or EFER bit. Digging out the bits manually is not exactly the most readable code. Future commits will switch to using mmu_role instead of vCPU state to configure the MMU, i.e. there are about to be a large number of users. Signed-off-by: Sean Christopherson <seanjc@google.com> --- arch/x86/kvm/mmu/mmu.c | 21 +++++++++++++++++++++ arch/x86/kvm/mmu/paging_tmpl.h | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-)