Message ID | 4aa3aaa6d12640ee9948308116c6f57ad3a0c1ba.1705965635.git.isaku.yamahata@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM TDX basic feature support | expand |
On 1/23/2024 7:53 AM, isaku.yamahata@intel.com wrote: > From: Sean Christopherson <sean.j.christopherson@intel.com> > > The difference of TDX EPT violation is how to retrieve information, GPA, > and exit qualification. To share the code to handle EPT violation, split > out the guts of EPT violation handler so that VMX/TDX exit handler can call > it after retrieving GPA and exit qualification. Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com> > > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> > Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com> > Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> > Reviewed-by: Kai Huang <kai.huang@intel.com> > --- > arch/x86/kvm/vmx/common.h | 33 +++++++++++++++++++++++++++++++++ > arch/x86/kvm/vmx/vmx.c | 25 +++---------------------- > 2 files changed, 36 insertions(+), 22 deletions(-) > create mode 100644 arch/x86/kvm/vmx/common.h > > diff --git a/arch/x86/kvm/vmx/common.h b/arch/x86/kvm/vmx/common.h > new file mode 100644 > index 000000000000..235908f3e044 > --- /dev/null > +++ b/arch/x86/kvm/vmx/common.h > @@ -0,0 +1,33 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +#ifndef __KVM_X86_VMX_COMMON_H > +#define __KVM_X86_VMX_COMMON_H > + > +#include <linux/kvm_host.h> > + > +#include "mmu.h" > + > +static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa, > + unsigned long exit_qualification) > +{ > + u64 error_code; > + > + /* Is it a read fault? */ > + error_code = (exit_qualification & EPT_VIOLATION_ACC_READ) > + ? PFERR_USER_MASK : 0; > + /* Is it a write fault? */ > + error_code |= (exit_qualification & EPT_VIOLATION_ACC_WRITE) > + ? PFERR_WRITE_MASK : 0; > + /* Is it a fetch fault? */ > + error_code |= (exit_qualification & EPT_VIOLATION_ACC_INSTR) > + ? PFERR_FETCH_MASK : 0; > + /* ept page table entry is present? */ > + error_code |= (exit_qualification & EPT_VIOLATION_RWX_MASK) > + ? PFERR_PRESENT_MASK : 0; > + > + error_code |= (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) != 0 ? > + PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK; > + > + return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0); > +} > + > +#endif /* __KVM_X86_VMX_COMMON_H */ > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index 89f31263fe9c..185e22a2e101 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -50,6 +50,7 @@ > #include <asm/vmx.h> > > #include "capabilities.h" > +#include "common.h" > #include "cpuid.h" > #include "hyperv.h" > #include "kvm_onhyperv.h" > @@ -5779,11 +5780,8 @@ static int handle_task_switch(struct kvm_vcpu *vcpu) > > static int handle_ept_violation(struct kvm_vcpu *vcpu) > { > - unsigned long exit_qualification; > + unsigned long exit_qualification = vmx_get_exit_qual(vcpu); > gpa_t gpa; > - u64 error_code; > - > - exit_qualification = vmx_get_exit_qual(vcpu); > > /* > * EPT violation happened while executing iret from NMI, > @@ -5798,23 +5796,6 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) > > gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS); > trace_kvm_page_fault(vcpu, gpa, exit_qualification); > - > - /* Is it a read fault? */ > - error_code = (exit_qualification & EPT_VIOLATION_ACC_READ) > - ? PFERR_USER_MASK : 0; > - /* Is it a write fault? */ > - error_code |= (exit_qualification & EPT_VIOLATION_ACC_WRITE) > - ? PFERR_WRITE_MASK : 0; > - /* Is it a fetch fault? */ > - error_code |= (exit_qualification & EPT_VIOLATION_ACC_INSTR) > - ? PFERR_FETCH_MASK : 0; > - /* ept page table entry is present? */ > - error_code |= (exit_qualification & EPT_VIOLATION_RWX_MASK) > - ? PFERR_PRESENT_MASK : 0; > - > - error_code |= (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) != 0 ? > - PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK; > - > vcpu->arch.exit_qualification = exit_qualification; > > /* > @@ -5828,7 +5809,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) > if (unlikely(allow_smaller_maxphyaddr && !kvm_vcpu_is_legal_gpa(vcpu, gpa))) > return kvm_emulate_instruction(vcpu, 0); > > - return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0); > + return __vmx_handle_ept_violation(vcpu, gpa, exit_qualification); > } > > static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/vmx/common.h b/arch/x86/kvm/vmx/common.h new file mode 100644 index 000000000000..235908f3e044 --- /dev/null +++ b/arch/x86/kvm/vmx/common.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __KVM_X86_VMX_COMMON_H +#define __KVM_X86_VMX_COMMON_H + +#include <linux/kvm_host.h> + +#include "mmu.h" + +static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa, + unsigned long exit_qualification) +{ + u64 error_code; + + /* Is it a read fault? */ + error_code = (exit_qualification & EPT_VIOLATION_ACC_READ) + ? PFERR_USER_MASK : 0; + /* Is it a write fault? */ + error_code |= (exit_qualification & EPT_VIOLATION_ACC_WRITE) + ? PFERR_WRITE_MASK : 0; + /* Is it a fetch fault? */ + error_code |= (exit_qualification & EPT_VIOLATION_ACC_INSTR) + ? PFERR_FETCH_MASK : 0; + /* ept page table entry is present? */ + error_code |= (exit_qualification & EPT_VIOLATION_RWX_MASK) + ? PFERR_PRESENT_MASK : 0; + + error_code |= (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) != 0 ? + PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK; + + return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0); +} + +#endif /* __KVM_X86_VMX_COMMON_H */ diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 89f31263fe9c..185e22a2e101 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -50,6 +50,7 @@ #include <asm/vmx.h> #include "capabilities.h" +#include "common.h" #include "cpuid.h" #include "hyperv.h" #include "kvm_onhyperv.h" @@ -5779,11 +5780,8 @@ static int handle_task_switch(struct kvm_vcpu *vcpu) static int handle_ept_violation(struct kvm_vcpu *vcpu) { - unsigned long exit_qualification; + unsigned long exit_qualification = vmx_get_exit_qual(vcpu); gpa_t gpa; - u64 error_code; - - exit_qualification = vmx_get_exit_qual(vcpu); /* * EPT violation happened while executing iret from NMI, @@ -5798,23 +5796,6 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS); trace_kvm_page_fault(vcpu, gpa, exit_qualification); - - /* Is it a read fault? */ - error_code = (exit_qualification & EPT_VIOLATION_ACC_READ) - ? PFERR_USER_MASK : 0; - /* Is it a write fault? */ - error_code |= (exit_qualification & EPT_VIOLATION_ACC_WRITE) - ? PFERR_WRITE_MASK : 0; - /* Is it a fetch fault? */ - error_code |= (exit_qualification & EPT_VIOLATION_ACC_INSTR) - ? PFERR_FETCH_MASK : 0; - /* ept page table entry is present? */ - error_code |= (exit_qualification & EPT_VIOLATION_RWX_MASK) - ? PFERR_PRESENT_MASK : 0; - - error_code |= (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) != 0 ? - PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK; - vcpu->arch.exit_qualification = exit_qualification; /* @@ -5828,7 +5809,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) if (unlikely(allow_smaller_maxphyaddr && !kvm_vcpu_is_legal_gpa(vcpu, gpa))) return kvm_emulate_instruction(vcpu, 0); - return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0); + return __vmx_handle_ept_violation(vcpu, gpa, exit_qualification); } static int handle_ept_misconfig(struct kvm_vcpu *vcpu)