On Thu, Dec 29, 2022 at 05:14:03PM +0100, Borislav Petkov wrote: > On Wed, Dec 14, 2022 at 01:39:56PM -0600, Michael Roth wrote: > > This callback is used by the KVM MMU to check whether a #NPF was > > or a private GPA or not. > > s/or // > > > > > Signed-off-by: Michael Roth <michael.roth@xxxxxxx> > > --- > > arch/x86/include/asm/kvm-x86-ops.h | 1 + > > arch/x86/include/asm/kvm_host.h | 1 + > > arch/x86/kvm/mmu/mmu.c | 3 +-- > > arch/x86/kvm/mmu/mmu_internal.h | 40 +++++++++++++++++++++++++++--- > > 4 files changed, 39 insertions(+), 6 deletions(-) > > > > diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h > > index f530a550c092..efae987cdce0 100644 > > --- a/arch/x86/include/asm/kvm-x86-ops.h > > +++ b/arch/x86/include/asm/kvm-x86-ops.h > > @@ -132,6 +132,7 @@ KVM_X86_OP(complete_emulated_msr) > > KVM_X86_OP(vcpu_deliver_sipi_vector) > > KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons); > > KVM_X86_OP_OPTIONAL_RET0(private_mem_enabled); > > +KVM_X86_OP_OPTIONAL_RET0(fault_is_private); > > > > #undef KVM_X86_OP > > #undef KVM_X86_OP_OPTIONAL > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > > index 9317abffbf68..92539708f062 100644 > > --- a/arch/x86/include/asm/kvm_host.h > > +++ b/arch/x86/include/asm/kvm_host.h > > @@ -1636,6 +1636,7 @@ struct kvm_x86_ops { > > void (*load_mmu_pgd)(struct kvm_vcpu *vcpu, hpa_t root_hpa, > > int root_level); > > int (*private_mem_enabled)(struct kvm *kvm); > > + int (*fault_is_private)(struct kvm *kvm, gpa_t gpa, u64 error_code, bool *private_fault); > > bool > > and then you don't need the silly "== 1" at the call site. Obviously I need to add some proper documentation for this, but a 1 return basically means 'private_fault' pass-by-ref arg has been set with the appropriate value, whereas 0 means "there's no platform-specific handling for this, so if you have some generic way to determine this then use that instead". This is mainly to handle CONFIG_HAVE_KVM_PRIVATE_MEM_TESTING, which just parrots whatever kvm_mem_is_private() returns to support running KVM selftests without needed hardware/platform support. If we don't take care to skip this check where the above fault_is_private() hook returns 1, then it ends up breaking SNP in cases where the kernel has been compiled with CONFIG_HAVE_KVM_PRIVATE_MEM_TESTING, since SNP relies on the page fault flags to make this determination, not kvm_mem_is_private(), which normally only tracks the memory attributes set by userspace via KVM_SET_MEMORY_ATTRIBUTES ioctl. > > > > > bool (*has_wbinvd_exit)(void); > > ... > > > @@ -261,13 +293,13 @@ enum { > > }; > > > > static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, > > - u32 err, bool prefetch) > > + u64 err, bool prefetch) > > The u32 -> u64 change of err could use a sentence or two of > clarification in the commit message... Will do. -Mike > > > { > > bool is_tdp = likely(vcpu->arch.mmu->page_fault == kvm_tdp_page_fault); > > > > struct kvm_page_fault fault = { > > .addr = cr2_or_gpa, > > - .error_code = err, > > + .error_code = lower_32_bits(err), > > .exec = err & PFERR_FETCH_MASK, > > .write = err & PFERR_WRITE_MASK, > > .present = err & PFERR_PRESENT_MASK, > > @@ -281,8 +313,8 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, > > .max_level = KVM_MAX_HUGEPAGE_LEVEL, > > .req_level = PG_LEVEL_4K, > > .goal_level = PG_LEVEL_4K, > > - .is_private = IS_ENABLED(CONFIG_HAVE_KVM_PRIVATE_MEM_TESTING) && is_tdp && > > - kvm_mem_is_private(vcpu->kvm, cr2_or_gpa >> PAGE_SHIFT), > > + .is_private = is_tdp && kvm_mmu_fault_is_private(vcpu->kvm, > > + cr2_or_gpa, err), > > }; > > int r; > > > > -- > > 2.25.1 > > > > -- > Regards/Gruss, > Boris. > > https://people.kernel.org/tglx/notes-about-netiquette