From: Jan Beulich <jbeulich@suse.com>
To: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: "Roger Pau Monné" <roger.pau@citrix.com>,
Xen-devel <xen-devel@lists.xenproject.org>
Subject: Re: [PATCH 21/22] x86/traps: Introduce FRED entrypoints
Date: Mon, 18 Aug 2025 12:03:39 +0200 [thread overview]
Message-ID: <d1635022-c386-4665-be07-e66afc8f3330@suse.com> (raw)
In-Reply-To: <20250808202314.1045968-22-andrew.cooper3@citrix.com>
On 08.08.2025 22:23, Andrew Cooper wrote:
> Under FRED, there's one entrypoint from Ring 3, and one from Ring 0.
>
> FRED gives us a good stack (even for SYSCALL/SYSENTER), and a unified event
> frame on the stack, meaing that all software needs to do is spill the GPRs
> with a line of PUSHes. Introduce PUSH_AND_CLEAR_GPRS and POP_GPRS for this
> purpose.
>
> Introduce entry_FRED_R0() which to a first appoximation is complete for all
> event handling within Xen.
>
> entry_FRED_R0() needs deriving from entry_FRED_R3(), so introduce a basic
> handler. There is more work required to make the return-to-guest path work
> under FRED, so leave a BUG clearly in place.
>
> Also introduce entry_from_{xen,pv}() to be the C level handlers. By simply
> copying regs->fred_ss.vector into regs->entry_vector, we can reuse all the
> existing fault handlers.
>
> Extend fatal_trap() to render the event type, including by name, when FRED is
> active. This is slightly complicated, because X86_ET_OTHER must not use
> vector_name() or SYSCALL and SYSENTER get rendered as #BP and #DB. Also,
> {read,write}_gs_shadow() needs modifying to avoid the SWAPGS instruction,
> which is disallowed in FRED mode.
>
> This is sufficient to handle all interrupts and exceptions encountered during
> development, including plenty of Double Faults.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
>
> SIMICS hasn't been updated to the FRED v9, and still wants ENDBR instructions
> at the entrypoints.
> ---
> xen/arch/x86/include/asm/asm_defns.h | 65 ++++++++++++
> xen/arch/x86/include/asm/msr.h | 8 +-
> xen/arch/x86/traps.c | 153 ++++++++++++++++++++++++++-
> xen/arch/x86/x86_64/Makefile | 1 +
> xen/arch/x86/x86_64/entry-fred.S | 35 ++++++
> 5 files changed, 256 insertions(+), 6 deletions(-)
> create mode 100644 xen/arch/x86/x86_64/entry-fred.S
>
> diff --git a/xen/arch/x86/include/asm/asm_defns.h b/xen/arch/x86/include/asm/asm_defns.h
> index 72a0082d319d..a81a4043d0f1 100644
> --- a/xen/arch/x86/include/asm/asm_defns.h
> +++ b/xen/arch/x86/include/asm/asm_defns.h
> @@ -315,6 +315,71 @@ static always_inline void stac(void)
> subq $-(UREGS_error_code-UREGS_r15+\adj), %rsp
> .endm
>
> +/*
> + * Push and clear GPRs
> + */
> +.macro PUSH_AND_CLEAR_GPRS
> + push %rdi
> + xor %edi, %edi
> + push %rsi
> + xor %esi, %esi
> + push %rdx
> + xor %edx, %edx
> + push %rcx
> + xor %ecx, %ecx
> + push %rax
> + xor %eax, %eax
> + push %r8
> + xor %r8d, %r8d
> + push %r9
> + xor %r9d, %r9d
> + push %r10
> + xor %r10d, %r10d
> + push %r11
> + xor %r11d, %r11d
> + push %rbx
> + xor %ebx, %ebx
> + push %rbp
> +#ifdef CONFIG_FRAME_POINTER
> +/* Indicate special exception stack frame by inverting the frame pointer. */
> + mov %rsp, %rbp
> + notq %rbp
> +#else
> + xor %ebp, %ebp
> +#endif
> + push %r12
> + xor %r12d, %r12d
> + push %r13
> + xor %r13d, %r13d
> + push %r14
> + xor %r14d, %r14d
> + push %r15
> + xor %r15d, %r15d
> +.endm
> +
> +/*
> + * POP GPRs from a UREGS_* frame on the stack. Does not modify flags.
> + *
> + * @rax: Alternative destination for the %rax value on the stack.
> + */
> +.macro POP_GPRS rax=%rax
> + pop %r15
> + pop %r14
> + pop %r13
> + pop %r12
> + pop %rbp
> + pop %rbx
> + pop %r11
> + pop %r10
> + pop %r9
> + pop %r8
> + pop \rax
> + pop %rcx
> + pop %rdx
> + pop %rsi
> + pop %rdi
> +.endm
> +
> #ifdef CONFIG_PV32
> #define CR4_PV32_RESTORE \
> ALTERNATIVE_2 "", \
> diff --git a/xen/arch/x86/include/asm/msr.h b/xen/arch/x86/include/asm/msr.h
> index b6b85b04c3fd..01f510315ffe 100644
> --- a/xen/arch/x86/include/asm/msr.h
> +++ b/xen/arch/x86/include/asm/msr.h
> @@ -202,9 +202,9 @@ static inline unsigned long read_gs_base(void)
>
> static inline unsigned long read_gs_shadow(void)
> {
> - unsigned long base;
> + unsigned long base, cr4 = read_cr4();
>
> - if ( read_cr4() & X86_CR4_FSGSBASE )
> + if ( !(cr4 & X86_CR4_FRED) && (cr4 & X86_CR4_FSGSBASE) )
> {
> asm volatile ( "swapgs" );
> base = __rdgsbase();
> @@ -234,7 +234,9 @@ static inline void write_gs_base(unsigned long base)
>
> static inline void write_gs_shadow(unsigned long base)
> {
> - if ( read_cr4() & X86_CR4_FSGSBASE )
> + unsigned long cr4 = read_cr4();
> +
> + if ( !(cr4 & X86_CR4_FRED) && (cr4 & X86_CR4_FSGSBASE) )
> {
> asm volatile ( "swapgs\n\t"
> "wrgsbase %0\n\t"
> diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
> index 270b93ed623e..e67a428e4362 100644
> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -1013,6 +1013,32 @@ void show_execution_state_nmi(const cpumask_t *mask, bool show_all)
> printk("Non-responding CPUs: {%*pbl}\n", CPUMASK_PR(&show_state_mask));
> }
>
> +static const char *x86_et_name(unsigned int type)
> +{
> + static const char *const names[] = {
> + [X86_ET_EXT_INTR] = "EXT_INTR",
> + [X86_ET_NMI] = "NMI",
> + [X86_ET_HW_EXC] = "HW_EXC",
> + [X86_ET_SW_INT] = "SW_INT",
> + [X86_ET_PRIV_SW_EXC] = "PRIV_SW_EXEC",
> + [X86_ET_SW_EXC] = "SW_EXEC",
> + [X86_ET_OTHER] = "OTHER",
> + };
> +
> + return (type < ARRAY_SIZE(names) && names[type]) ? names[type] : "???";
> +}
> +
> +static const char *x86_et_other_name(unsigned int vec)
> +{
> + static const char *const names[] = {
> + [0] = "MTF",
> + [1] = "SYSCALL",
> + [2] = "SYSENTER",
> + };
> +
> + return (vec < ARRAY_SIZE(names) && names[vec][0]) ? names[vec] : "???";
> +}
> +
> const char *vector_name(unsigned int vec)
> {
> static const char names[][4] = {
> @@ -1091,9 +1117,42 @@ void fatal_trap(const struct cpu_user_regs *regs, bool show_remote)
> }
> }
>
> - panic("FATAL TRAP: vec %u, %s[%04x]%s\n",
> - trapnr, vector_name(trapnr), regs->error_code,
> - (regs->eflags & X86_EFLAGS_IF) ? "" : " IN INTERRUPT CONTEXT");
> + if ( read_cr4() & X86_CR4_FRED )
> + {
> + bool render_ec = false;
> + const char *vec_name = NULL;
> +
> + switch ( regs->fred_ss.type )
> + {
> + case X86_ET_HW_EXC:
> + case X86_ET_SW_INT:
> + case X86_ET_PRIV_SW_EXC:
> + case X86_ET_SW_EXC:
> + render_ec = true;
> + vec_name = vector_name(regs->fred_ss.vector);
> + break;
> +
> + case X86_ET_OTHER:
> + vec_name = x86_et_other_name(regs->fred_ss.vector);
> + break;
> + }
> +
> + if ( render_ec )
> + panic("Fatal TRAP: type %u, %s, vec %u, %s[%04x]%s\n",
> + regs->fred_ss.type, x86_et_name(regs->fred_ss.type),
> + regs->fred_ss.vector, vec_name ?: "",
> + regs->error_code,
> + (regs->eflags & X86_EFLAGS_IF) ? "" : " IN INTERRUPT CONTEXT");
> + else
> + panic("Fatal TRAP: type %u, %s, vec %u, %s%s\n",
> + regs->fred_ss.type, x86_et_name(regs->fred_ss.type),
> + regs->fred_ss.vector, vec_name ?: "",
> + (regs->eflags & X86_EFLAGS_IF) ? "" : " IN INTERRUPT CONTEXT");
> + }
> + else
> + panic("FATAL TRAP: vec %u, %s[%04x]%s\n",
> + trapnr, vector_name(trapnr), regs->error_code,
> + (regs->eflags & X86_EFLAGS_IF) ? "" : " IN INTERRUPT CONTEXT");
> }
>
> void asmlinkage noreturn do_unhandled_trap(struct cpu_user_regs *regs)
> @@ -2181,6 +2240,94 @@ void asmlinkage check_ist_exit(const struct cpu_user_regs *regs, bool ist_exit)
> }
> #endif
>
> +void asmlinkage entry_from_pv(struct cpu_user_regs *regs)
> +{
> + /* Copy fred_ss.vector into entry_vector as IDT delivery would have done. */
> + regs->entry_vector = regs->fred_ss.vector;
> +
> + switch ( regs->fred_ss.type )
> + {
> + case X86_ET_EXT_INTR:
> + do_IRQ(regs);
> + break;
> +
> + case X86_ET_NMI:
> + do_nmi(regs);
> + break;
> +
> + case X86_ET_HW_EXC:
> + case X86_ET_SW_INT:
> + case X86_ET_PRIV_SW_EXC:
> + case X86_ET_SW_EXC:
> + goto fatal;
> +
> + default:
> + goto fatal;
> + }
> +
> + return;
> +
> + fatal:
> + fatal_trap(regs, false);
> +}
Noticed only now: Shouldn't this be surrounded with #ifdef CONFIG_PV (with
knock-on effects elsewhere)?
Jan
next prev parent reply other threads:[~2025-08-18 10:03 UTC|newest]
Thread overview: 120+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-08 20:22 [PATCH 00/22] x86: FRED support, part 1 (stacks and exceptions) Andrew Cooper
2025-08-08 20:22 ` [PATCH 01/22] x86/msr: Rename MSR_INTERRUPT_SSP_TABLE to MSR_ISST Andrew Cooper
2025-08-12 8:06 ` Jan Beulich
2025-08-13 9:02 ` Andrew Cooper
2025-08-08 20:22 ` [PATCH 02/22] x86/msr: Rename wrmsr_ns() to wrmsrns(), and take 64bit value Andrew Cooper
2025-08-11 6:36 ` Andrew Cooper
2025-08-12 8:08 ` Jan Beulich
2025-08-08 20:22 ` [PATCH 03/22] x86/traps: Drop incorrect BUILD_BUG_ON() and comment in load_system_tables() Andrew Cooper
2025-08-12 8:11 ` Jan Beulich
2025-08-13 9:40 ` Andrew Cooper
2025-08-14 8:50 ` Jan Beulich
2025-08-08 20:22 ` [PATCH 04/22] x86/idt: Minor improvements to _update_gate_addr_lower() Andrew Cooper
2025-08-12 8:16 ` Jan Beulich
2025-08-13 9:48 ` Andrew Cooper
2025-08-08 20:22 ` [PATCH 05/22] x86/traps: Rename early_traps_init() to bsp_early_traps_init() Andrew Cooper
2025-08-12 8:17 ` Jan Beulich
2025-08-08 20:22 ` [PATCH 06/22] x86/traps: Introduce bsp_traps_reinit() Andrew Cooper
2025-08-12 8:19 ` Jan Beulich
2025-08-13 9:51 ` Andrew Cooper
2025-08-08 20:22 ` [PATCH 07/22] x86/spec-ctrl: Rework init_shadow_spec_ctrl_state() to take an info pointer Andrew Cooper
2025-08-12 8:27 ` Jan Beulich
2025-08-13 10:35 ` Andrew Cooper
2025-08-08 20:23 ` [PATCH 08/22] x86/traps: Introduce ap_early_traps_init() and set up exception handling earlier Andrew Cooper
2025-08-12 8:41 ` Jan Beulich
2025-08-13 11:13 ` Andrew Cooper
2025-08-14 8:53 ` Jan Beulich
2025-08-14 18:07 ` [PATCH v1.1 08/22] x86/traps: Introduce percpu_early_traps_init() " Andrew Cooper
2025-08-15 9:24 ` Jan Beulich
2025-08-08 20:23 ` [PATCH 09/22] x86/traps: Move load_system_tables() into traps-setup.c Andrew Cooper
2025-08-12 9:19 ` Jan Beulich
2025-08-13 11:25 ` Andrew Cooper
2025-08-14 8:55 ` Jan Beulich
2025-08-14 18:09 ` Andrew Cooper
2025-08-15 8:22 ` Jan Beulich
2025-08-15 8:28 ` Andrew Cooper
2025-08-15 8:32 ` Jan Beulich
2025-08-12 9:43 ` Nicola Vetrini
2025-08-13 11:36 ` Andrew Cooper
2025-08-14 7:26 ` Jan Beulich
2025-08-14 18:20 ` Andrew Cooper
2025-08-15 8:30 ` Jan Beulich
2025-08-15 8:40 ` Nicola Vetrini
2025-08-15 8:49 ` Jan Beulich
2025-08-08 20:23 ` [PATCH 10/22] x86/traps: Move subarch_percpu_traps_init() " Andrew Cooper
2025-08-11 8:17 ` Andrew Cooper
2025-08-12 9:52 ` Jan Beulich
2025-08-13 11:53 ` Andrew Cooper
2025-08-14 8:58 ` Jan Beulich
2025-08-14 10:17 ` Andrew Cooper
2025-08-14 10:52 ` Jan Beulich
2025-08-14 11:02 ` Andrew Cooper
2025-08-08 20:23 ` [PATCH 11/22] x86/traps: Fold x86_64/traps.c into traps.c Andrew Cooper
2025-08-12 9:53 ` Jan Beulich
2025-08-08 20:23 ` [PATCH 12/22] x86/traps: Unexport show_code() and show_stack_overflow() Andrew Cooper
2025-08-12 9:54 ` Jan Beulich
2025-08-08 20:23 ` [PATCH 13/22] x86: FRED enumerations Andrew Cooper
2025-08-13 12:28 ` Andrew Cooper
2025-08-14 7:30 ` Jan Beulich
2025-08-14 11:20 ` Jan Beulich
2025-08-14 11:42 ` Andrew Cooper
2025-08-14 11:44 ` Jan Beulich
2025-08-14 11:47 ` Andrew Cooper
2025-08-14 19:37 ` Nicola Vetrini
2025-08-14 19:44 ` Andrew Cooper
2025-08-14 21:27 ` Nicola Vetrini
2025-08-14 20:18 ` Nicola Vetrini
2025-08-14 13:19 ` Jan Beulich
2025-08-14 18:45 ` Andrew Cooper
2025-08-15 8:34 ` Jan Beulich
2025-08-21 21:23 ` Andrew Cooper
2025-08-18 9:02 ` Jan Beulich
2025-08-08 20:23 ` [PATCH 14/22] x86/traps: Extend struct cpu_user_regs/cpu_info with FRED fields Andrew Cooper
2025-08-14 13:12 ` Jan Beulich
2025-08-14 15:07 ` Andrew Cooper
2025-08-08 20:23 ` [PATCH 15/22] x86/traps: Introduce opt_fred Andrew Cooper
2025-08-14 13:30 ` Jan Beulich
2025-08-14 19:16 ` Andrew Cooper
2025-08-15 8:37 ` Jan Beulich
2025-08-21 21:52 ` Andrew Cooper
2025-08-25 9:08 ` Jan Beulich
2025-08-08 20:23 ` [PATCH 16/22] x86/boot: Adjust CR4 handling around ap_early_traps_init() Andrew Cooper
2025-08-14 14:47 ` Jan Beulich
2025-08-14 14:54 ` Andrew Cooper
2025-08-14 14:56 ` Jan Beulich
2025-08-14 19:22 ` Andrew Cooper
2025-08-08 20:23 ` [PATCH 17/22] x86/S3: Switch to using RSTORSSP to recover SSP on resume Andrew Cooper
2025-08-14 14:54 ` Jan Beulich
2025-08-08 20:23 ` [PATCH 18/22] x86/traps: Set MSR_PL0_SSP in load_system_tables() Andrew Cooper
2025-08-14 15:00 ` Jan Beulich
2025-08-14 19:37 ` Andrew Cooper
2025-08-15 8:52 ` Jan Beulich
2025-08-15 13:49 ` Andrew Cooper
2025-08-08 20:23 ` [PATCH 19/22] x86/boot: Use RSTORSSP to establish SSP Andrew Cooper
2025-08-14 15:11 ` Jan Beulich
2025-08-14 20:09 ` Andrew Cooper
2025-08-15 9:03 ` Jan Beulich
2025-08-21 22:09 ` Andrew Cooper
2025-08-25 9:12 ` Jan Beulich
2025-08-08 20:23 ` [PATCH 20/22] x86/traps: Alter switch_stack_and_jump() for FRED mode Andrew Cooper
2025-08-14 15:35 ` Jan Beulich
2025-08-14 20:55 ` Andrew Cooper
2025-08-15 9:10 ` Jan Beulich
2025-08-21 22:56 ` Andrew Cooper
2025-08-25 9:19 ` Jan Beulich
2025-08-08 20:23 ` [PATCH 21/22] x86/traps: Introduce FRED entrypoints Andrew Cooper
2025-08-11 11:38 ` Andrew Cooper
2025-08-14 15:57 ` Jan Beulich
2025-08-14 20:40 ` Andrew Cooper
2025-08-15 9:22 ` Jan Beulich
2025-08-18 8:59 ` Jan Beulich
2025-08-18 10:03 ` Jan Beulich [this message]
2025-08-18 10:09 ` Andrew Cooper
2025-08-08 20:23 ` [PATCH 22/22] x86/traps: Enable FRED when requested Andrew Cooper
2025-08-18 9:35 ` Jan Beulich
2025-08-18 9:47 ` Andrew Cooper
2025-08-18 9:53 ` Jan Beulich
2025-08-08 23:49 ` [PATCH 23/22] x86/vmx: Adjust NMI handling for FRED Andrew Cooper
2025-08-18 10:02 ` Jan Beulich
2025-08-18 17:18 ` Andrew Cooper
2025-08-19 6:31 ` Jan Beulich
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=d1635022-c386-4665-be07-e66afc8f3330@suse.com \
--to=jbeulich@suse.com \
--cc=andrew.cooper3@citrix.com \
--cc=roger.pau@citrix.com \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.