Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp1392313ybz; Thu, 16 Apr 2020 08:22:34 -0700 (PDT) X-Google-Smtp-Source: APiQypK60P0iAVsv6sEjhau6jP1OquubnBb/ysOBahFRvpEQzpwfTo9pv2rIu6XkOodnAzEcBlQR X-Received: by 2002:a17:906:2bd1:: with SMTP id n17mr10036280ejg.176.1587050553710; Thu, 16 Apr 2020 08:22:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1587050553; cv=none; d=google.com; s=arc-20160816; b=tpds21Zw2ZnCPSfAJ5IMsgf7/+y9MT9sd30mN1MAVpDrIwi2xeNyy0nSMGL9LQ7kBa 2l3VZa/uGQ0P+43052katNCcOUYbaK+Cbki7j0XRfiMjphlTiFea3u6fdYGRPRVYGdQX nuW1RIzIs3qPqwbXm57ac6R/cTm+T0ub6acLYbeOY6UTuiLB6CdFRq49dm8LwGFSrpR3 lStc50BrxfnMvetuMzAyYpwOQ0JVv9XqNputR6AsHbmN8ekxX5OK2iNMOH53aVkitrxp jVHOOeNv0ESHbuYRac0kOX3heN4fsu4asL4Wzlomz2XdpIVrpmryL36vh0p3obco9043 L5Lg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=G0V0Z0ZvgglCGlCS4wF/ZqrvTYQ6xNycfdrn5NlVePE=; b=aNc6Prs18Gz85EebCB/2fycHkwYH4uoHp7ZS74SAXRcszVY0vgU8S6ux4OOMSUIpQ5 fX/hyIKipzz3yeU61B50fQ1l307B2ohth8vnFaLHAirc23MTdhN336LvYjcT+u7gshKj EUh0LMgD+DrxYKSCYSPpOXLWex/sWp8xLF2A95+IUQPno+f0c20N2U24qQI51CDFf9HB XqLWR6t9TGqyJY1+reNk2yimaguQ0DGqGy1HfOKNd3Mb7wwo6OHU9uxHI/DJIfthLBfV SEE0ZKviXnNm/DR47oqxAew2UPDfj5K3r5OKwoOS4xZTR4jG2FDN0bfLW4MdykvAXb2c S/RQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=2af+8x1e; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id nh5si4676808ejb.352.2020.04.16.08.22.09; Thu, 16 Apr 2020 08:22:33 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=2af+8x1e; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731778AbgDPPUO (ORCPT + 99 others); Thu, 16 Apr 2020 11:20:14 -0400 Received: from mail.kernel.org ([198.145.29.99]:33516 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2898678AbgDPNra (ORCPT ); Thu, 16 Apr 2020 09:47:30 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 9188921744; Thu, 16 Apr 2020 13:47:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1587044848; bh=rAE7rB+Hi786MKpUO7dDoxTVBTSD19Rs3R/iOiuEn38=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=2af+8x1ei6/oKs+NsK8uRVXKPzPl02B5GeDy5OV3YvM+JtSCFOiUBtPWssx8V8n9w Tq1cZynGHYJ8BKSurIF+c51Et3zFAT7x8xhy2M4oKo9sWg4zlwR0Y1Av3S7Gm3/E55 lPUo32XS67Sit6R7J5uHPTFyTVjGmpZaGc1nBQPY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Liran Alon , Sean Christopherson , Paolo Bonzini Subject: [PATCH 5.4 125/232] KVM: nVMX: Properly handle userspace interrupt window request Date: Thu, 16 Apr 2020 15:23:39 +0200 Message-Id: <20200416131330.694867397@linuxfoundation.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200416131316.640996080@linuxfoundation.org> References: <20200416131316.640996080@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sean Christopherson commit a1c77abb8d93381e25a8d2df3a917388244ba776 upstream. Return true for vmx_interrupt_allowed() if the vCPU is in L2 and L1 has external interrupt exiting enabled. IRQs are never blocked in hardware if the CPU is in the guest (L2 from L1's perspective) when IRQs trigger VM-Exit. The new check percolates up to kvm_vcpu_ready_for_interrupt_injection() and thus vcpu_run(), and so KVM will exit to userspace if userspace has requested an interrupt window (to inject an IRQ into L1). Remove the @external_intr param from vmx_check_nested_events(), which is actually an indicator that userspace wants an interrupt window, e.g. it's named @req_int_win further up the stack. Injecting a VM-Exit into L1 to try and bounce out to L0 userspace is all kinds of broken and is no longer necessary. Remove the hack in nested_vmx_vmexit() that attempted to workaround the breakage in vmx_check_nested_events() by only filling interrupt info if there's an actual interrupt pending. The hack actually made things worse because it caused KVM to _never_ fill interrupt info when the LAPIC resides in userspace (kvm_cpu_has_interrupt() queries interrupt.injected, which is always cleared by prepare_vmcs12() before reaching the hack in nested_vmx_vmexit()). Fixes: 6550c4df7e50 ("KVM: nVMX: Fix interrupt window request with "Acknowledge interrupt on exit"") Cc: stable@vger.kernel.org Cc: Liran Alon Signed-off-by: Sean Christopherson Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/vmx/nested.c | 18 ++++-------------- arch/x86/kvm/vmx/vmx.c | 9 +++++++-- arch/x86/kvm/x86.c | 10 +++++----- 4 files changed, 17 insertions(+), 22 deletions(-) --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1130,7 +1130,7 @@ struct kvm_x86_ops { bool (*pt_supported)(void); bool (*pku_supported)(void); - int (*check_nested_events)(struct kvm_vcpu *vcpu, bool external_intr); + int (*check_nested_events)(struct kvm_vcpu *vcpu); void (*request_immediate_exit)(struct kvm_vcpu *vcpu); void (*sched_in)(struct kvm_vcpu *kvm, int cpu); --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -3460,7 +3460,7 @@ static void nested_vmx_inject_exception_ nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI, intr_info, exit_qual); } -static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr) +static int vmx_check_nested_events(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); unsigned long exit_qual; @@ -3507,8 +3507,7 @@ static int vmx_check_nested_events(struc return 0; } - if ((kvm_cpu_has_interrupt(vcpu) || external_intr) && - nested_exit_on_intr(vcpu)) { + if (kvm_cpu_has_interrupt(vcpu) && nested_exit_on_intr(vcpu)) { if (block_nested_events) return -EBUSY; nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, 0, 0); @@ -4158,17 +4157,8 @@ void nested_vmx_vmexit(struct kvm_vcpu * vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; if (likely(!vmx->fail)) { - /* - * TODO: SDM says that with acknowledge interrupt on - * exit, bit 31 of the VM-exit interrupt information - * (valid interrupt) is always set to 1 on - * EXIT_REASON_EXTERNAL_INTERRUPT, so we shouldn't - * need kvm_cpu_has_interrupt(). See the commit - * message for details. - */ - if (nested_exit_intr_ack_set(vcpu) && - exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT && - kvm_cpu_has_interrupt(vcpu)) { + if (exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT && + nested_exit_intr_ack_set(vcpu)) { int irq = kvm_cpu_get_interrupt(vcpu); WARN_ON(irq < 0); vmcs12->vm_exit_intr_info = irq | --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -4505,8 +4505,13 @@ static int vmx_nmi_allowed(struct kvm_vc static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu) { - return (!to_vmx(vcpu)->nested.nested_run_pending && - vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) && + if (to_vmx(vcpu)->nested.nested_run_pending) + return false; + + if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu)) + return true; + + return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) && !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS)); } --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -7555,7 +7555,7 @@ static void update_cr8_intercept(struct kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr); } -static int inject_pending_event(struct kvm_vcpu *vcpu, bool req_int_win) +static int inject_pending_event(struct kvm_vcpu *vcpu) { int r; @@ -7591,7 +7591,7 @@ static int inject_pending_event(struct k * from L2 to L1. */ if (is_guest_mode(vcpu) && kvm_x86_ops->check_nested_events) { - r = kvm_x86_ops->check_nested_events(vcpu, req_int_win); + r = kvm_x86_ops->check_nested_events(vcpu); if (r != 0) return r; } @@ -7653,7 +7653,7 @@ static int inject_pending_event(struct k * KVM_REQ_EVENT only on certain events and not unconditionally? */ if (is_guest_mode(vcpu) && kvm_x86_ops->check_nested_events) { - r = kvm_x86_ops->check_nested_events(vcpu, req_int_win); + r = kvm_x86_ops->check_nested_events(vcpu); if (r != 0) return r; } @@ -8130,7 +8130,7 @@ static int vcpu_enter_guest(struct kvm_v goto out; } - if (inject_pending_event(vcpu, req_int_win) != 0) + if (inject_pending_event(vcpu) != 0) req_immediate_exit = true; else { /* Enable SMI/NMI/IRQ window open exits if needed. @@ -8360,7 +8360,7 @@ static inline int vcpu_block(struct kvm static inline bool kvm_vcpu_running(struct kvm_vcpu *vcpu) { if (is_guest_mode(vcpu) && kvm_x86_ops->check_nested_events) - kvm_x86_ops->check_nested_events(vcpu, false); + kvm_x86_ops->check_nested_events(vcpu); return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE && !vcpu->arch.apf.halted);