linux-hyperv.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Xin Li <xin3.li@intel.com>
To: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-edac@vger.kernel.org, linux-hyperv@vger.kernel.org,
	kvm@vger.kernel.org, xen-devel@lists.xenproject.org
Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
	dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com,
	luto@kernel.org, pbonzini@redhat.com, seanjc@google.com,
	peterz@infradead.org, jgross@suse.com, ravi.v.shankar@intel.com,
	mhiramat@kernel.org, andrew.cooper3@citrix.com,
	jiangshanlai@gmail.com
Subject: [PATCH v10 31/38] x86/fred: Fixup fault on ERETU by jumping to fred_entrypoint_user
Date: Wed, 13 Sep 2023 21:47:58 -0700	[thread overview]
Message-ID: <20230914044805.301390-32-xin3.li@intel.com> (raw)
In-Reply-To: <20230914044805.301390-1-xin3.li@intel.com>

If the stack frame contains an invalid user context (e.g. due to invalid SS,
a non-canonical RIP, etc.) the ERETU instruction will trap (#SS or #GP).

From a Linux point of view, this really should be considered a user space
failure, so use the standard fault fixup mechanism to intercept the fault,
fix up the exception frame, and redirect execution to fred_entrypoint_user.
The end result is that it appears just as if the hardware had taken the
exception immediately after completing the transition to user space.

Suggested-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Tested-by: Shan Kang <shan.kang@intel.com>
Signed-off-by: Xin Li <xin3.li@intel.com>
---

Changes since v8:
* Reflect the FRED spec 5.0 change that ERETS and ERETU add 8 to %rsp
  before popping the return context from the stack.

Changes since v6:
* Add a comment to explain why it is safe to write to the previous FRED stack
  frame. (Lai Jiangshan).

Changes since v5:
* Move the NMI bit from an invalid stack frame, which caused ERETU to fault,
  to the fault handler's stack frame, thus to unblock NMI ASAP if NMI is blocked
  (Lai Jiangshan).
---
 arch/x86/entry/entry_64_fred.S             |  5 +-
 arch/x86/include/asm/extable_fixup_types.h |  4 +-
 arch/x86/mm/extable.c                      | 79 ++++++++++++++++++++++
 3 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/arch/x86/entry/entry_64_fred.S b/arch/x86/entry/entry_64_fred.S
index 5781c3411b44..d1c2fc4af8ae 100644
--- a/arch/x86/entry/entry_64_fred.S
+++ b/arch/x86/entry/entry_64_fred.S
@@ -3,6 +3,7 @@
  * The actual FRED entry points.
  */
 
+#include <asm/asm.h>
 #include <asm/fred.h>
 
 #include "calling.h"
@@ -34,7 +35,9 @@ SYM_CODE_START_NOALIGN(asm_fred_entrypoint_user)
 	call	fred_entry_from_user
 SYM_INNER_LABEL(asm_fred_exit_user, SYM_L_GLOBAL)
 	FRED_EXIT
-	ERETU
+1:	ERETU
+
+	_ASM_EXTABLE_TYPE(1b, asm_fred_entrypoint_user, EX_TYPE_ERETU)
 SYM_CODE_END(asm_fred_entrypoint_user)
 
 .fill asm_fred_entrypoint_kernel - ., 1, 0xcc
diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h
index 991e31cfde94..1585c798a02f 100644
--- a/arch/x86/include/asm/extable_fixup_types.h
+++ b/arch/x86/include/asm/extable_fixup_types.h
@@ -64,6 +64,8 @@
 #define	EX_TYPE_UCOPY_LEN4		(EX_TYPE_UCOPY_LEN | EX_DATA_IMM(4))
 #define	EX_TYPE_UCOPY_LEN8		(EX_TYPE_UCOPY_LEN | EX_DATA_IMM(8))
 
-#define EX_TYPE_ZEROPAD			20 /* longword load with zeropad on fault */
+#define	EX_TYPE_ZEROPAD			20 /* longword load with zeropad on fault */
+
+#define	EX_TYPE_ERETU			21
 
 #endif
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 271dcb2deabc..bc7af7e8587b 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -6,6 +6,7 @@
 #include <xen/xen.h>
 
 #include <asm/fpu/api.h>
+#include <asm/fred.h>
 #include <asm/sev.h>
 #include <asm/traps.h>
 #include <asm/kdebug.h>
@@ -223,6 +224,80 @@ static bool ex_handler_ucopy_len(const struct exception_table_entry *fixup,
 	return ex_handler_uaccess(fixup, regs, trapnr, fault_address);
 }
 
+#ifdef CONFIG_X86_FRED
+static bool ex_handler_eretu(const struct exception_table_entry *fixup,
+			     struct pt_regs *regs, unsigned long error_code)
+{
+	struct pt_regs *uregs = (struct pt_regs *)
+		(regs->sp - offsetof(struct pt_regs, orig_ax));
+	unsigned short ss = uregs->ss;
+	unsigned short cs = uregs->cs;
+
+	/*
+	 * Move the NMI bit from the invalid stack frame, which caused ERETU
+	 * to fault, to the fault handler's stack frame, thus to unblock NMI
+	 * with the fault handler's ERETS instruction ASAP if NMI is blocked.
+	 */
+	regs->fred_ss.nmi = uregs->fred_ss.nmi;
+
+	/*
+	 * Sync event information to uregs, i.e., the ERETU return frame, but
+	 * is it safe to write to the ERETU return frame which is just above
+	 * current event stack frame?
+	 *
+	 * The RSP used by FRED to push a stack frame is not the value in %rsp,
+	 * it is calculated from %rsp with the following 2 steps:
+	 * 1) RSP = %rsp - (IA32_FRED_CONFIG & 0x1c0)	// Reserve N*64 bytes
+	 * 2) RSP = RSP & ~0x3f		// Align to a 64-byte cache line
+	 * when an event delivery doesn't trigger a stack level change.
+	 *
+	 * Here is an example with N*64 (N=1) bytes reserved:
+	 *
+	 *  64-byte cache line ==>  ______________
+	 *                         |___Reserved___|
+	 *                         |__Event_data__|
+	 *                         |_____SS_______|
+	 *                         |_____RSP______|
+	 *                         |_____FLAGS____|
+	 *                         |_____CS_______|
+	 *                         |_____IP_______|
+	 *  64-byte cache line ==> |__Error_code__| <== ERETU return frame
+	 *                         |______________|
+	 *                         |______________|
+	 *                         |______________|
+	 *                         |______________|
+	 *                         |______________|
+	 *                         |______________|
+	 *                         |______________|
+	 *  64-byte cache line ==> |______________| <== RSP after step 1) and 2)
+	 *                         |___Reserved___|
+	 *                         |__Event_data__|
+	 *                         |_____SS_______|
+	 *                         |_____RSP______|
+	 *                         |_____FLAGS____|
+	 *                         |_____CS_______|
+	 *                         |_____IP_______|
+	 *  64-byte cache line ==> |__Error_code__| <== ERETS return frame
+	 *
+	 * Thus a new FRED stack frame will always be pushed below a previous
+	 * FRED stack frame ((N*64) bytes may be reserved between), and it is
+	 * safe to write to a previous FRED stack frame as they never overlap.
+	 */
+	fred_info(uregs)->edata = fred_event_data(regs);
+	uregs->ssx = regs->ssx;
+	uregs->fred_ss.ss = ss;
+	/* The NMI bit was moved away above */
+	uregs->fred_ss.nmi = 0;
+	uregs->csx = regs->csx;
+	uregs->sl = 0;
+	uregs->wfe = 0;
+	uregs->cs = cs;
+	uregs->orig_ax = error_code;
+
+	return ex_handler_default(fixup, regs);
+}
+#endif
+
 int ex_get_fixup_type(unsigned long ip)
 {
 	const struct exception_table_entry *e = search_exception_tables(ip);
@@ -300,6 +375,10 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
 		return ex_handler_ucopy_len(e, regs, trapnr, fault_addr, reg, imm);
 	case EX_TYPE_ZEROPAD:
 		return ex_handler_zeropad(e, regs, fault_addr);
+#ifdef CONFIG_X86_FRED
+	case EX_TYPE_ERETU:
+		return ex_handler_eretu(e, regs, error_code);
+#endif
 	}
 	BUG();
 }
-- 
2.34.1


  parent reply	other threads:[~2023-09-14  5:19 UTC|newest]

Thread overview: 88+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-14  4:47 [PATCH v10 00/38] x86: enable FRED for x86-64 Xin Li
2023-09-14  4:47 ` [PATCH v10 01/38] x86/cpufeatures: Add the cpu feature bit for WRMSRNS Xin Li
2023-09-14  4:47 ` [PATCH v10 02/38] x86/opcode: Add the WRMSRNS instruction to the x86 opcode map Xin Li
2023-09-15  5:47   ` Masami Hiramatsu
2023-09-14  4:47 ` [PATCH v10 03/38] x86/msr: Add the WRMSRNS instruction support Xin Li
2023-09-14  6:02   ` Juergen Gross
2023-09-14 13:01     ` andrew.cooper3
2023-09-14 14:05   ` andrew.cooper3
2023-09-14 23:00     ` Thomas Gleixner
2023-09-14 23:34       ` H. Peter Anvin
2023-09-14 23:46       ` andrew.cooper3
2023-09-15  0:12         ` Thomas Gleixner
2023-09-15  0:33           ` andrew.cooper3
2023-09-15  0:38             ` H. Peter Anvin
2023-09-15  1:46               ` andrew.cooper3
2023-09-15  2:06                 ` H. Peter Anvin
2023-09-15  0:42         ` Thomas Gleixner
2023-09-15  1:01         ` H. Peter Anvin
2023-09-15  1:16           ` andrew.cooper3
2023-09-15  5:32             ` Juergen Gross
2023-09-20 15:00             ` Peter Zijlstra
2023-09-20 15:04               ` Juergen Gross
2023-09-20  7:58   ` Nikolay Borisov
2023-09-20  8:18     ` Li, Xin3
2023-09-22  8:16       ` Li, Xin3
2023-09-22 15:00         ` Thomas Gleixner
2023-09-22 23:21           ` Li, Xin3
2023-09-14  4:47 ` [PATCH v10 04/38] x86/entry: Remove idtentry_sysvec from entry_{32,64}.S Xin Li
2023-09-14  4:47 ` [PATCH v10 05/38] x86/trapnr: Add event type macros to <asm/trapnr.h> Xin Li
2023-09-14 14:22   ` andrew.cooper3
2023-09-14  4:47 ` [PATCH v10 06/38] Documentation/x86/64: Add a documentation for FRED Xin Li
2023-09-20  9:44   ` Nikolay Borisov
2023-09-14  4:47 ` [PATCH v10 07/38] x86/fred: Add Kconfig option for FRED (CONFIG_X86_FRED) Xin Li
2023-09-14  4:47 ` [PATCH v10 08/38] x86/cpufeatures: Add the cpu feature bit for FRED Xin Li
2023-09-14  6:03   ` Juergen Gross
2023-09-14  6:09     ` Jan Beulich
2023-09-14 13:15       ` andrew.cooper3
2023-09-15  1:07         ` Thomas Gleixner
2023-09-15  5:27           ` Juergen Gross
2023-09-14  4:47 ` [PATCH v10 09/38] x86/fred: Disable FRED support if CONFIG_X86_FRED is disabled Xin Li
2023-09-20 10:19   ` Nikolay Borisov
2023-09-14  4:47 ` [PATCH v10 10/38] x86/fred: Disable FRED by default in its early stage Xin Li
2023-09-14  4:47 ` [PATCH v10 11/38] x86/opcode: Add ERET[US] instructions to the x86 opcode map Xin Li
2023-09-14  4:47 ` [PATCH v10 12/38] x86/objtool: Teach objtool about ERET[US] Xin Li
2023-09-14  4:47 ` [PATCH v10 13/38] x86/cpu: Add X86_CR4_FRED macro Xin Li
2023-09-20 10:50   ` Nikolay Borisov
2023-09-20 17:25     ` Li, Xin3
2023-09-14  4:47 ` [PATCH v10 14/38] x86/cpu: Add MSR numbers for FRED configuration Xin Li
2023-09-14  4:47 ` [PATCH v10 15/38] x86/ptrace: Cleanup the definition of the pt_regs structure Xin Li
2023-09-14  4:47 ` [PATCH v10 16/38] x86/ptrace: Add FRED additional information to " Xin Li
2023-09-20 12:57   ` Nikolay Borisov
2023-09-20 17:23     ` Li, Xin3
2023-09-21  6:07       ` Nikolay Borisov
2023-09-21  6:24         ` Li, Xin3
2023-09-14  4:47 ` [PATCH v10 17/38] x86/fred: Add a new header file for FRED definitions Xin Li
2023-09-14  4:47 ` [PATCH v10 18/38] x86/fred: Reserve space for the FRED stack frame Xin Li
2023-09-14  4:47 ` [PATCH v10 19/38] x86/fred: Update MSR_IA32_FRED_RSP0 during task switch Xin Li
2023-09-14  4:47 ` [PATCH v10 20/38] x86/fred: Disallow the swapgs instruction when FRED is enabled Xin Li
2023-09-14  4:47 ` [PATCH v10 21/38] x86/fred: No ESPFIX needed " Xin Li
2023-09-14  4:47 ` [PATCH v10 22/38] x86/fred: Allow single-step trap and NMI when starting a new task Xin Li
2023-09-14  4:47 ` [PATCH v10 23/38] x86/fred: Make exc_page_fault() work for FRED Xin Li
2023-09-14  4:47 ` [PATCH v10 24/38] x86/idtentry: Incorporate definitions/declarations of the FRED entries Xin Li
2023-09-14  4:47 ` [PATCH v10 25/38] x86/fred: Add a debug fault entry stub for FRED Xin Li
2023-09-14  4:47 ` [PATCH v10 26/38] x86/fred: Add a NMI " Xin Li
2023-09-14  4:47 ` [PATCH v10 27/38] x86/fred: Add a machine check " Xin Li
2023-09-14  4:47 ` [PATCH v10 28/38] x86/fred: FRED entry/exit and dispatch code Xin Li
2023-09-21  9:48   ` Nikolay Borisov
2023-09-21 10:08     ` Thomas Gleixner
2023-09-21 17:54       ` Li, Xin3
2023-09-14  4:47 ` [PATCH v10 29/38] x86/traps: Add sysvec_install() to install a system interrupt handler Xin Li
2023-09-14  4:47 ` [PATCH v10 30/38] x86/fred: Let ret_from_fork_asm() jmp to asm_fred_exit_user when FRED is enabled Xin Li
2023-09-14  4:47 ` Xin Li [this message]
2023-09-14  4:47 ` [PATCH v10 32/38] x86/entry/calling: Allow PUSH_AND_CLEAR_REGS being used beyond actual entry code Xin Li
2023-09-14  4:48 ` [PATCH v10 33/38] x86/entry: Add fred_entry_from_kvm() for VMX to handle IRQ/NMI Xin Li
2023-09-20 17:54   ` Paolo Bonzini
2023-09-20 23:10     ` Li, Xin3
2023-09-21 12:11   ` Nikolay Borisov
2023-09-21 12:38     ` Paolo Bonzini
2023-09-14  4:48 ` [PATCH v10 34/38] KVM: VMX: Call fred_entry_from_kvm() for IRQ/NMI handling Xin Li
2023-09-20 17:54   ` Paolo Bonzini
2023-09-14  4:48 ` [PATCH v10 35/38] x86/syscall: Split IDT syscall setup code into idt_syscall_init() Xin Li
2023-09-14  4:48 ` [PATCH v10 36/38] x86/fred: Add fred_syscall_init() Xin Li
2023-09-19  8:28   ` Thomas Gleixner
2023-09-20  4:33     ` Li, Xin3
2023-09-20  8:18       ` Thomas Gleixner
2023-09-21  2:24         ` H. Peter Anvin
2023-09-14  4:48 ` [PATCH v10 37/38] x86/fred: Add FRED initialization functions Xin Li
2023-09-14  4:48 ` [PATCH v10 38/38] x86/fred: Invoke FRED initialization code to enable FRED Xin Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230914044805.301390-32-xin3.li@intel.com \
    --to=xin3.li@intel.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=jgross@suse.com \
    --cc=jiangshanlai@gmail.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-edac@vger.kernel.org \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=ravi.v.shankar@intel.com \
    --cc=seanjc@google.com \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).