[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v10 33/38] x86/entry: Add fred_entry_from_kvm() for VMX to handle IRQ/NMI
- To: Xin Li <xin3.li@xxxxxxxxx>, linux-doc@xxxxxxxxxxxxxxx, linux-kernel@xxxxxxxxxxxxxxx, linux-edac@xxxxxxxxxxxxxxx, linux-hyperv@xxxxxxxxxxxxxxx, kvm@xxxxxxxxxxxxxxx, xen-devel@xxxxxxxxxxxxxxxxxxxx
- From: Nikolay Borisov <nik.borisov@xxxxxxxx>
- Date: Thu, 21 Sep 2023 15:11:23 +0300
- Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=suse.com; dmarc=pass action=none header.from=suse.com; dkim=pass header.d=suse.com; arc=none
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=H9IV9WD6UoE+UWKkaa5daXyJPGea+Ww6mWdg7JHay50=; b=TC3cHOpUMcLosovSArjiG7N3ZsXlxfA8Wmcr4wKtRYSKa4Ewnh55D6J33Qn9UYGfsLXRIbXr6v0IcY3+m6ptuURJjB4fjLXyzFIi9QurVI0giXEfpSZLBhjRSiXj32uw7wRu3kn6T25WbYhaGokIT6M2pEwooIwlmslMUPpEIv9wTZwwIY6VP202VHVddxWQXPZ31CFkHMZUjiI2wTMNVlcvA7iL2LDOCLZot+EcXqzD4m8ah9V8rt3f1yMrcdNS8Mbqh8dAhsdapV/z1kC2gRvtJ/LfYq5K/vK8s+i9Bi3eqYP2Va/rbeAPPsVRjl3CaJdAwTyIqY5qusadgRl4PA==
- Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=LO42/PrvKoII8kw5Wxe6N/3e196hE2RagyBqIp7qvhVW57fvxr44E8jQzBG21RaIaHhkU6fEoItJ8svX3eBjKhhmHk24ClMR6dsluaIZ1LE0bZWAd7q2RAz68HZkhz5hFaWwD2/ABa1Tzm+D/b1IdIXi7S1WJyZsAURkjFsqxScMaR5rAUtGSvVDnN4n2vH8NweeRuzV1bShU1Kirstix1QAJyBqiv+OwoWvYG6KOrIgH9ZEjTVVvtFEssT28d+BcK11l7zXh0CMkKx69ryjazEoZhwhzGNJmERTIBWM1+/tH6w2gfMzFeJptytKh6MI1Ipw23n+SgUuzy41QNqeDg==
- Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=suse.com;
- Cc: tglx@xxxxxxxxxxxxx, mingo@xxxxxxxxxx, bp@xxxxxxxxx, dave.hansen@xxxxxxxxxxxxxxx, x86@xxxxxxxxxx, hpa@xxxxxxxxx, luto@xxxxxxxxxx, pbonzini@xxxxxxxxxx, seanjc@xxxxxxxxxx, peterz@xxxxxxxxxxxxx, jgross@xxxxxxxx, ravi.v.shankar@xxxxxxxxx, mhiramat@xxxxxxxxxx, andrew.cooper3@xxxxxxxxxx, jiangshanlai@xxxxxxxxx
- Delivery-date: Thu, 21 Sep 2023 12:11:49 +0000
- List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
On 14.09.23 г. 7:48 ч., Xin Li wrote:
In IRQ/NMI induced VM exits, KVM VMX needs to execute the respective
handlers, which requires the software to create a FRED stack frame,
and use it to invoke the handlers. Add fred_irq_entry_from_kvm() for
this job.
Export fred_entry_from_kvm() because VMX can be compiled as a module.
Suggested-by: Sean Christopherson <seanjc@xxxxxxxxxx>
Tested-by: Shan Kang <shan.kang@xxxxxxxxx>
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Signed-off-by: Xin Li <xin3.li@xxxxxxxxx>
---
Changes since v9:
* Shove the whole thing into arch/x86/entry/entry_64_fred.S for invoking
external_interrupt() and fred_exc_nmi() (Sean Christopherson).
* Correct and improve a few comments (Sean Christopherson).
* Merge the two IRQ/NMI asm entries into one as it's fine to invoke
noinstr code from regular code (Thomas Gleixner).
* Setup the long mode and NMI flags in the augmented SS field of FRED
stack frame in C instead of asm (Thomas Gleixner).
* Add UNWIND_HINT_{SAVE,RESTORE} to get rid of the warning: "objtool:
asm_fred_entry_from_kvm+0x0: unreachable instruction" (Peter Zijlstra).
Changes since v8:
* Add a new macro VMX_DO_FRED_EVENT_IRQOFF for FRED instead of
refactoring VMX_DO_EVENT_IRQOFF (Sean Christopherson).
* Do NOT use a trampoline, just LEA+PUSH the return RIP, PUSH the error
code, and jump to the FRED kernel entry point for NMI or call
external_interrupt() for IRQs (Sean Christopherson).
* Call external_interrupt() only when FRED is enabled, and convert the
non-FRED handling to external_interrupt() after FRED lands (Sean
Christopherson).
---
arch/x86/entry/entry_64_fred.S | 73 ++++++++++++++++++++++++++++++++++
arch/x86/entry/entry_fred.c | 14 +++++++
arch/x86/include/asm/fred.h | 18 +++++++++
3 files changed, 105 insertions(+)
diff --git a/arch/x86/entry/entry_64_fred.S b/arch/x86/entry/entry_64_fred.S
index d1c2fc4af8ae..f1088d6f2054 100644
--- a/arch/x86/entry/entry_64_fred.S
+++ b/arch/x86/entry/entry_64_fred.S
@@ -4,7 +4,9 @@
*/
#include <asm/asm.h>
+#include <asm/export.h>
#include <asm/fred.h>
+#include <asm/segment.h>
#include "calling.h"
@@ -54,3 +56,74 @@ SYM_CODE_START_NOALIGN(asm_fred_entrypoint_kernel)
FRED_EXIT
ERETS
SYM_CODE_END(asm_fred_entrypoint_kernel)
+
+#if IS_ENABLED(CONFIG_KVM_INTEL)
+SYM_FUNC_START(asm_fred_entry_from_kvm)
+ push %rbp
+ mov %rsp, %rbp
use FRAME_BEGIN/FRAME_END macros to ommit this code if
CONFIG_FRAME_POINTER is disabled.
+
+ UNWIND_HINT_SAVE
+
+ /*
+ * Don't check the FRED stack level, the call stack leading to this
+ * helper is effectively constant and shallow (relatively speaking).
+ *
+ * Emulate the FRED-defined redzone and stack alignment.
+ */
+ sub $(FRED_CONFIG_REDZONE_AMOUNT << 6), %rsp
+ and $FRED_STACK_FRAME_RSP_MASK, %rsp
+
+ /*
+ * Start to push a FRED stack frame, which is always 64 bytes:
+ *
+ * +--------+-----------------+
+ * | Bytes | Usage |
+ * +--------+-----------------+
+ * | 63:56 | Reserved |
+ * | 55:48 | Event Data |
+ * | 47:40 | SS + Event Info |
+ * | 39:32 | RSP |
+ * | 31:24 | RFLAGS |
+ * | 23:16 | CS + Aux Info |
+ * | 15:8 | RIP |
+ * | 7:0 | Error Code |
+ * +--------+-----------------+
+ */
+ push $0 /* Reserved, must be 0 */
+ push $0 /* Event data, 0 for IRQ/NMI */
+ push %rdi /* fred_ss handed in by the caller */
+ push %rbp
+ pushf
+ mov $__KERNEL_CS, %rax
+ push %rax
+
+ /*
+ * Unlike the IDT event delivery, FRED _always_ pushes an error code
+ * after pushing the return RIP, thus the CALL instruction CANNOT be
+ * used here to push the return RIP, otherwise there is no chance to
+ * push an error code before invoking the IRQ/NMI handler.
+ *
+ * Use LEA to get the return RIP and push it, then push an error code.
+ */
+ lea 1f(%rip), %rax
+ push %rax /* Return RIP */
+ push $0 /* Error code, 0 for IRQ/NMI */
+
+ PUSH_AND_CLEAR_REGS clear_bp=0 unwind_hint=0
+ movq %rsp, %rdi /* %rdi -> pt_regs */
+ call __fred_entry_from_kvm /* Call the C entry point */
+ POP_REGS
+ ERETS
+1:
+ /*
+ * Objtool doesn't understand what ERETS does, this hint tells it that
+ * yes, we'll reach here and with what stack state. A save/restore pair
+ * isn't strictly needed, but it's the simplest form.
+ */
+ UNWIND_HINT_RESTORE
+ pop %rbp
FRAME_END
+ RET
+
+SYM_FUNC_END(asm_fred_entry_from_kvm)
+EXPORT_SYMBOL_GPL(asm_fred_entry_from_kvm);
+#endif
<snip>
|