lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <bb05156c-a143-4257-b5a3-4af05429e07f@linux.intel.com>
Date: Tue, 9 Apr 2024 16:52:56 +0800
From: Binbin Wu <binbin.wu@...ux.intel.com>
To: isaku.yamahata@...el.com
Cc: kvm@...r.kernel.org, linux-kernel@...r.kernel.org,
 isaku.yamahata@...il.com, Paolo Bonzini <pbonzini@...hat.com>,
 erdemaktas@...gle.com, Sean Christopherson <seanjc@...gle.com>,
 Sagi Shahar <sagis@...gle.com>, Kai Huang <kai.huang@...el.com>,
 chen.bo@...el.com, hang.yuan@...el.com, tina.zhang@...el.com,
 Sean Christopherson <sean.j.christopherson@...el.com>
Subject: Re: [PATCH v19 096/130] KVM: VMX: Move NMI/exception handler to
 common helper



On 2/26/2024 4:26 PM, isaku.yamahata@...el.com wrote:
> From: Sean Christopherson <sean.j.christopherson@...el.com>
>
> TDX mostly handles NMI/exception exit mostly the same to VMX case.  The
> difference is how to retrieve exit qualification.  To share the code with
> TDX, move NMI/exception to a common header, common.h.

Suggest to add "No functional change intended." in the changelog.

>
> Signed-off-by: Sean Christopherson <sean.j.christopherson@...el.com>
> Signed-off-by: Isaku Yamahata <isaku.yamahata@...el.com>
> ---
>   arch/x86/kvm/vmx/common.h | 59 +++++++++++++++++++++++++++++++++
>   arch/x86/kvm/vmx/vmx.c    | 68 +++++----------------------------------
>   2 files changed, 67 insertions(+), 60 deletions(-)
>
> diff --git a/arch/x86/kvm/vmx/common.h b/arch/x86/kvm/vmx/common.h
> index 6f21d0d48809..632af7a76d0a 100644
> --- a/arch/x86/kvm/vmx/common.h
> +++ b/arch/x86/kvm/vmx/common.h
> @@ -4,8 +4,67 @@
>   
>   #include <linux/kvm_host.h>
>   
> +#include <asm/traps.h>
> +
>   #include "posted_intr.h"
>   #include "mmu.h"
> +#include "vmcs.h"
> +#include "x86.h"
> +
> +extern unsigned long vmx_host_idt_base;
> +void vmx_do_interrupt_irqoff(unsigned long entry);
> +void vmx_do_nmi_irqoff(void);
> +
> +static inline void vmx_handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)
> +{
> +	/*
> +	 * Save xfd_err to guest_fpu before interrupt is enabled, so the
> +	 * MSR value is not clobbered by the host activity before the guest
> +	 * has chance to consume it.
> +	 *
> +	 * Do not blindly read xfd_err here, since this exception might
> +	 * be caused by L1 interception on a platform which doesn't
> +	 * support xfd at all.
> +	 *
> +	 * Do it conditionally upon guest_fpu::xfd. xfd_err matters
> +	 * only when xfd contains a non-zero value.
> +	 *
> +	 * Queuing exception is done in vmx_handle_exit. See comment there.
> +	 */
> +	if (vcpu->arch.guest_fpu.fpstate->xfd)
> +		rdmsrl(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
> +}
> +
> +static inline void vmx_handle_exception_irqoff(struct kvm_vcpu *vcpu,
> +					       u32 intr_info)
> +{
> +	/* if exit due to PF check for async PF */
> +	if (is_page_fault(intr_info))
> +		vcpu->arch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();
> +	/* if exit due to NM, handle before interrupts are enabled */
> +	else if (is_nm_fault(intr_info))
> +		vmx_handle_nm_fault_irqoff(vcpu);
> +	/* Handle machine checks before interrupts are enabled */
> +	else if (is_machine_check(intr_info))
> +		kvm_machine_check();
> +}
> +
> +static inline void vmx_handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
> +							u32 intr_info)
> +{
> +	unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
> +	gate_desc *desc = (gate_desc *)vmx_host_idt_base + vector;
> +
> +	if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
> +	    "unexpected VM-Exit interrupt info: 0x%x", intr_info))
> +		return;
> +
> +	kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
> +	vmx_do_interrupt_irqoff(gate_offset(desc));
> +	kvm_after_interrupt(vcpu);
> +
> +	vcpu->arch.at_instruction_boundary = true;
> +}
>   
>   static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
>   					     unsigned long exit_qualification)
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 29d891e0795e..f8a00a766c40 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -518,7 +518,7 @@ static inline void vmx_segment_cache_clear(struct vcpu_vmx *vmx)
>   	vmx->segment_cache.bitmask = 0;
>   }
>   
> -static unsigned long host_idt_base;
> +unsigned long vmx_host_idt_base;
>   
>   #if IS_ENABLED(CONFIG_HYPERV)
>   static bool __read_mostly enlightened_vmcs = true;
> @@ -4273,7 +4273,7 @@ void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
>   	vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
>   	vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8);  /* 22.2.4 */
>   
> -	vmcs_writel(HOST_IDTR_BASE, host_idt_base);   /* 22.2.4 */
> +	vmcs_writel(HOST_IDTR_BASE, vmx_host_idt_base);   /* 22.2.4 */
>   
>   	vmcs_writel(HOST_RIP, (unsigned long)vmx_vmexit); /* 22.2.5 */
>   
> @@ -5166,7 +5166,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
>   	intr_info = vmx_get_intr_info(vcpu);
>   
>   	/*
> -	 * Machine checks are handled by handle_exception_irqoff(), or by
> +	 * Machine checks are handled by vmx_handle_exception_irqoff(), or by
>   	 * vmx_vcpu_run() if a #MC occurs on VM-Entry.  NMIs are handled by
>   	 * vmx_vcpu_enter_exit().
>   	 */
> @@ -5174,7 +5174,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
>   		return 1;
>   
>   	/*
> -	 * Queue the exception here instead of in handle_nm_fault_irqoff().
> +	 * Queue the exception here instead of in vmx_handle_nm_fault_irqoff().
>   	 * This ensures the nested_vmx check is not skipped so vmexit can
>   	 * be reflected to L1 (when it intercepts #NM) before reaching this
>   	 * point.
> @@ -6889,59 +6889,6 @@ void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
>   	vmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]);
>   }
>   
> -void vmx_do_interrupt_irqoff(unsigned long entry);
> -void vmx_do_nmi_irqoff(void);
> -
> -static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)
> -{
> -	/*
> -	 * Save xfd_err to guest_fpu before interrupt is enabled, so the
> -	 * MSR value is not clobbered by the host activity before the guest
> -	 * has chance to consume it.
> -	 *
> -	 * Do not blindly read xfd_err here, since this exception might
> -	 * be caused by L1 interception on a platform which doesn't
> -	 * support xfd at all.
> -	 *
> -	 * Do it conditionally upon guest_fpu::xfd. xfd_err matters
> -	 * only when xfd contains a non-zero value.
> -	 *
> -	 * Queuing exception is done in vmx_handle_exit. See comment there.
> -	 */
> -	if (vcpu->arch.guest_fpu.fpstate->xfd)
> -		rdmsrl(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
> -}
> -
> -static void handle_exception_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
> -{
> -	/* if exit due to PF check for async PF */
> -	if (is_page_fault(intr_info))
> -		vcpu->arch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();
> -	/* if exit due to NM, handle before interrupts are enabled */
> -	else if (is_nm_fault(intr_info))
> -		handle_nm_fault_irqoff(vcpu);
> -	/* Handle machine checks before interrupts are enabled */
> -	else if (is_machine_check(intr_info))
> -		kvm_machine_check();
> -}
> -
> -static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
> -					     u32 intr_info)
> -{
> -	unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
> -	gate_desc *desc = (gate_desc *)host_idt_base + vector;
> -
> -	if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
> -	    "unexpected VM-Exit interrupt info: 0x%x", intr_info))
> -		return;
> -
> -	kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
> -	vmx_do_interrupt_irqoff(gate_offset(desc));
> -	kvm_after_interrupt(vcpu);
> -
> -	vcpu->arch.at_instruction_boundary = true;
> -}
> -
>   void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
>   {
>   	struct vcpu_vmx *vmx = to_vmx(vcpu);
> @@ -6950,9 +6897,10 @@ void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
>   		return;
>   
>   	if (vmx->exit_reason.basic == EXIT_REASON_EXTERNAL_INTERRUPT)
> -		handle_external_interrupt_irqoff(vcpu, vmx_get_intr_info(vcpu));
> +		vmx_handle_external_interrupt_irqoff(vcpu,
> +						     vmx_get_intr_info(vcpu));
>   	else if (vmx->exit_reason.basic == EXIT_REASON_EXCEPTION_NMI)
> -		handle_exception_irqoff(vcpu, vmx_get_intr_info(vcpu));
> +		vmx_handle_exception_irqoff(vcpu, vmx_get_intr_info(vcpu));
>   }
>   
>   /*
> @@ -8284,7 +8232,7 @@ __init int vmx_hardware_setup(void)
>   	int r;
>   
>   	store_idt(&dt);
> -	host_idt_base = dt.address;
> +	vmx_host_idt_base = dt.address;
>   
>   	vmx_setup_user_return_msrs();
>   


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ