On Mon, Sep 14, 2020 at 9:56 PM Sean Christopherson <sean.j.christopherson@xxxxxxxxx> wrote: > > Move the asm blob that invokes the appropriate IRQ handler after VM-Exit > into a proper subroutine. Slightly rework the blob so that it plays > nice with objtool without any additional hints (existing hints aren't > able to handle returning with a seemingly modified stack size). > > Suggested-by: Josh Poimboeuf <jpoimboe@xxxxxxxxxx> > Cc: Uros Bizjak <ubizjak@xxxxxxxxx> > Signed-off-by: Sean Christopherson <sean.j.christopherson@xxxxxxxxx> > --- > arch/x86/kvm/vmx/vmenter.S | 28 ++++++++++++++++++++++++++++ > arch/x86/kvm/vmx/vmx.c | 33 +++------------------------------ > 2 files changed, 31 insertions(+), 30 deletions(-) > > diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S > index 799db084a336..baec1e0fefc5 100644 > --- a/arch/x86/kvm/vmx/vmenter.S > +++ b/arch/x86/kvm/vmx/vmenter.S > @@ -4,6 +4,7 @@ > #include <asm/bitsperlong.h> > #include <asm/kvm_vcpu_regs.h> > #include <asm/nospec-branch.h> > +#include <asm/segment.h> > > #define WORD_SIZE (BITS_PER_LONG / 8) > > @@ -294,3 +295,30 @@ SYM_FUNC_START(vmread_error_trampoline) > > ret > SYM_FUNC_END(vmread_error_trampoline) > + > +SYM_FUNC_START(vmx_do_interrupt_nmi_irqoff) > + /* > + * Unconditionally create a stack frame. RSP needs to be aligned for > + * x86-64, getting the correct RSP on the stack (for x86-64) would take > + * two instructions anyways, and it helps make objtool happy (see below). > + */ > + push %_ASM_BP > + mov %rsp, %_ASM_BP _ASM_SP instead of %rsp to avoid assembly failure for 32bit targets. > + > +#ifdef CONFIG_X86_64 > + push $__KERNEL_DS > + push %_ASM_BP > +#endif > + pushf > + push $__KERNEL_CS > + CALL_NOSPEC _ASM_ARG1 > + > + /* > + * "Restore" RSP from RBP, even though IRET has already unwound RSP to > + * the correct value. objtool doesn't know the target will IRET and so > + * thinks the stack is getting walloped (without the explicit restore). > + */ > + mov %_ASM_BP, %rsp > + pop %_ASM_BP > + ret > +SYM_FUNC_END(vmx_do_interrupt_nmi_irqoff) > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index 46ba2e03a892..391f079d9136 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -6409,6 +6409,8 @@ static void vmx_apicv_post_state_restore(struct kvm_vcpu *vcpu) > memset(vmx->pi_desc.pir, 0, sizeof(vmx->pi_desc.pir)); > } > > +void vmx_do_interrupt_nmi_irqoff(unsigned long entry); > + > static void handle_exception_nmi_irqoff(struct vcpu_vmx *vmx) > { > u32 intr_info = vmx_get_intr_info(&vmx->vcpu); > @@ -6430,10 +6432,6 @@ static void handle_exception_nmi_irqoff(struct vcpu_vmx *vmx) > static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu) > { > unsigned int vector; > - unsigned long entry; > -#ifdef CONFIG_X86_64 > - unsigned long tmp; > -#endif > gate_desc *desc; > u32 intr_info = vmx_get_intr_info(vcpu); > > @@ -6443,36 +6441,11 @@ static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu) > > vector = intr_info & INTR_INFO_VECTOR_MASK; > desc = (gate_desc *)host_idt_base + vector; > - entry = gate_offset(desc); I'd leave the above line... > > kvm_before_interrupt(vcpu); > - > - asm volatile( > -#ifdef CONFIG_X86_64 > - "mov %%rsp, %[sp]\n\t" > - "and $-16, %%rsp\n\t" > - "push %[ss]\n\t" > - "push %[sp]\n\t" > -#endif > - "pushf\n\t" > - "push %[cs]\n\t" > - CALL_NOSPEC > - : > -#ifdef CONFIG_X86_64 > - [sp]"=&r"(tmp), > -#endif > - ASM_CALL_CONSTRAINT > - : > - [thunk_target]"r"(entry), > -#ifdef CONFIG_X86_64 > - [ss]"i"(__KERNEL_DS), > -#endif > - [cs]"i"(__KERNEL_CS) > - ); > - > + vmx_do_interrupt_nmi_irqoff(gate_offset(desc)); ... to make the above line read as: vmx_do_interrupt_nmi_irqoff(entry); This way, it looks more descriptive to me. Uros. > kvm_after_interrupt(vcpu); > } > -STACK_FRAME_NON_STANDARD(handle_external_interrupt_irqoff); > > static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu) > { > -- > 2.28.0 >