diff mbox series

[RFC,14/32] x86/fred: header file with FRED definitions

Message ID 20221220063658.19271-15-xin3.li@intel.com (mailing list archive)
State New, archived
Headers show
Series x86: enable FRED for x86-64 | expand

Commit Message

Li, Xin3 Dec. 20, 2022, 6:36 a.m. UTC
From: "H. Peter Anvin (Intel)" <hpa@zytor.com>

Add a header file for FRED prototypes and definitions.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Xin Li <xin3.li@intel.com>
---
 arch/x86/include/asm/fred.h | 99 +++++++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)
 create mode 100644 arch/x86/include/asm/fred.h

Comments

Peter Zijlstra Dec. 20, 2022, 8:56 a.m. UTC | #1
> +/*
> + * FRED return instructions
> + *
> + * Replace with "ERETS"/"ERETU" once binutils support FRED return instructions.

binutils version that supports these instructions goes here...

> + */
> +#define ERETS			_ASM_BYTES(0xf2,0x0f,0x01,0xca)
> +#define ERETU			_ASM_BYTES(0xf3,0x0f,0x01,0xca)
> +
> +/*
> + * Event stack level macro for the FRED_STKLVLS MSR.
> + * Usage example: FRED_STKLVL(X86_TRAP_DF, 3)
> + * Multiple values can be ORd together.
> + */
> +#define FRED_STKLVL(v,l)	(_AT(unsigned long, l) << (2*(v)))
> +
> +/* FRED_CONFIG MSR */
> +#define FRED_CONFIG_CSL_MASK		0x3
> +#define FRED_CONFIG_SHADOW_STACK_SPACE	_BITUL(3)
> +#define FRED_CONFIG_REDZONE(b)		__ALIGN_KERNEL_MASK((b), _UL(0x3f))
> +#define FRED_CONFIG_INT_STKLVL(l)	(_AT(unsigned long, l) << 9)
> +#define FRED_CONFIG_ENTRYPOINT(p)	_AT(unsigned long, (p))
> +
> +/* FRED event type and vector bit width and counts */
> +#define FRED_EVENT_TYPE_BITS		3 /* only 3 bits used in FRED 3.0 */
> +#define FRED_EVENT_TYPE_COUNT		_BITUL(FRED_EVENT_TYPE_BITS)
> +#define FRED_EVENT_VECTOR_BITS		8
> +#define FRED_EVENT_VECTOR_COUNT		_BITUL(FRED_EVENT_VECTOR_BITS)
> +
> +/* FRED EVENT_TYPE_OTHER vector numbers */
> +#define FRED_SYSCALL			1
> +#define FRED_SYSENTER			2
> +
> +/* Flags above the CS selector (regs->csl) */
> +#define FRED_CSL_ENABLE_NMI		_BITUL(28)
> +#define FRED_CSL_ALLOW_SINGLE_STEP	_BITUL(25)
> +#define FRED_CSL_INTERRUPT_SHADOW	_BITUL(24)

What's the state of IBT WAIT-FOR-ENDBR vs this? That really should also
get a high CS bit.
Li, Xin3 Dec. 21, 2022, 2:58 a.m. UTC | #2
> > +/*
> > + * FRED return instructions
> > + *
> > + * Replace with "ERETS"/"ERETU" once binutils support FRED return
> instructions.
> 
> binutils version that supports these instructions goes here...
> 
> > + */
> > +#define ERETS			_ASM_BYTES(0xf2,0x0f,0x01,0xca)
> > +#define ERETU			_ASM_BYTES(0xf3,0x0f,0x01,0xca)
> > +
> > +/*
> > + * Event stack level macro for the FRED_STKLVLS MSR.
> > + * Usage example: FRED_STKLVL(X86_TRAP_DF, 3)
> > + * Multiple values can be ORd together.
> > + */
> > +#define FRED_STKLVL(v,l)	(_AT(unsigned long, l) << (2*(v)))
> > +
> > +/* FRED_CONFIG MSR */
> > +#define FRED_CONFIG_CSL_MASK		0x3
> > +#define FRED_CONFIG_SHADOW_STACK_SPACE	_BITUL(3)
> > +#define FRED_CONFIG_REDZONE(b)		__ALIGN_KERNEL_MASK((b),
> _UL(0x3f))
> > +#define FRED_CONFIG_INT_STKLVL(l)	(_AT(unsigned long, l) << 9)
> > +#define FRED_CONFIG_ENTRYPOINT(p)	_AT(unsigned long, (p))
> > +
> > +/* FRED event type and vector bit width and counts */
> > +#define FRED_EVENT_TYPE_BITS		3 /* only 3 bits used in FRED 3.0
> */
> > +#define FRED_EVENT_TYPE_COUNT		_BITUL(FRED_EVENT_TYPE_BITS)
> > +#define FRED_EVENT_VECTOR_BITS		8
> > +#define FRED_EVENT_VECTOR_COUNT
> 	_BITUL(FRED_EVENT_VECTOR_BITS)
> > +
> > +/* FRED EVENT_TYPE_OTHER vector numbers */
> > +#define FRED_SYSCALL			1
> > +#define FRED_SYSENTER			2
> > +
> > +/* Flags above the CS selector (regs->csl) */
> > +#define FRED_CSL_ENABLE_NMI		_BITUL(28)
> > +#define FRED_CSL_ALLOW_SINGLE_STEP	_BITUL(25)
> > +#define FRED_CSL_INTERRUPT_SHADOW	_BITUL(24)
> 
> What's the state of IBT WAIT-FOR-ENDBR vs this? That really should also get a
> high CS bit.

FRED does provide more possibilities :)
Peter Zijlstra Dec. 22, 2022, 1:03 p.m. UTC | #3
On Wed, Dec 21, 2022 at 02:58:06AM +0000, Li, Xin3 wrote:

> > > +/* Flags above the CS selector (regs->csl) */
> > > +#define FRED_CSL_ENABLE_NMI		_BITUL(28)
> > > +#define FRED_CSL_ALLOW_SINGLE_STEP	_BITUL(25)
> > > +#define FRED_CSL_INTERRUPT_SHADOW	_BITUL(24)
> > 
> > What's the state of IBT WAIT-FOR-ENDBR vs this? That really should also get a
> > high CS bit.
> 
> FRED does provide more possibilities :)

That's not an answer. IBT has a clear defect and FRED *should* fix it.
H. Peter Anvin Dec. 23, 2022, 7:34 p.m. UTC | #4
On December 22, 2022 5:03:57 AM PST, Peter Zijlstra <peterz@infradead.org> wrote:
>On Wed, Dec 21, 2022 at 02:58:06AM +0000, Li, Xin3 wrote:
>
>> > > +/* Flags above the CS selector (regs->csl) */
>> > > +#define FRED_CSL_ENABLE_NMI		_BITUL(28)
>> > > +#define FRED_CSL_ALLOW_SINGLE_STEP	_BITUL(25)
>> > > +#define FRED_CSL_INTERRUPT_SHADOW	_BITUL(24)
>> > 
>> > What's the state of IBT WAIT-FOR-ENDBR vs this? That really should also get a
>> > high CS bit.
>> 
>> FRED does provide more possibilities :)
>
>That's not an answer. IBT has a clear defect and FRED *should* fix it.

You are not wrong, of course. That being said, we have not wanted to hitch too many things to the FRED baseline, lest it ends up delayed for implementation/validation reasons. The important thing is that FRED *does* provide the mechanism for addressing that even if it does not make the first implementation.
diff mbox series

Patch

diff --git a/arch/x86/include/asm/fred.h b/arch/x86/include/asm/fred.h
new file mode 100644
index 000000000000..6292b28d461d
--- /dev/null
+++ b/arch/x86/include/asm/fred.h
@@ -0,0 +1,99 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * arch/x86/include/asm/fred.h
+ *
+ * Macros for Flexible Return and Event Delivery (FRED)
+ */
+
+#ifndef ASM_X86_FRED_H
+#define ASM_X86_FRED_H
+
+#ifdef CONFIG_X86_FRED
+
+#include <linux/const.h>
+#include <asm/asm.h>
+
+/*
+ * FRED return instructions
+ *
+ * Replace with "ERETS"/"ERETU" once binutils support FRED return instructions.
+ */
+#define ERETS			_ASM_BYTES(0xf2,0x0f,0x01,0xca)
+#define ERETU			_ASM_BYTES(0xf3,0x0f,0x01,0xca)
+
+/*
+ * Event stack level macro for the FRED_STKLVLS MSR.
+ * Usage example: FRED_STKLVL(X86_TRAP_DF, 3)
+ * Multiple values can be ORd together.
+ */
+#define FRED_STKLVL(v,l)	(_AT(unsigned long, l) << (2*(v)))
+
+/* FRED_CONFIG MSR */
+#define FRED_CONFIG_CSL_MASK		0x3
+#define FRED_CONFIG_SHADOW_STACK_SPACE	_BITUL(3)
+#define FRED_CONFIG_REDZONE(b)		__ALIGN_KERNEL_MASK((b), _UL(0x3f))
+#define FRED_CONFIG_INT_STKLVL(l)	(_AT(unsigned long, l) << 9)
+#define FRED_CONFIG_ENTRYPOINT(p)	_AT(unsigned long, (p))
+
+/* FRED event type and vector bit width and counts */
+#define FRED_EVENT_TYPE_BITS		3 /* only 3 bits used in FRED 3.0 */
+#define FRED_EVENT_TYPE_COUNT		_BITUL(FRED_EVENT_TYPE_BITS)
+#define FRED_EVENT_VECTOR_BITS		8
+#define FRED_EVENT_VECTOR_COUNT		_BITUL(FRED_EVENT_VECTOR_BITS)
+
+/* FRED EVENT_TYPE_OTHER vector numbers */
+#define FRED_SYSCALL			1
+#define FRED_SYSENTER			2
+
+/* Flags above the CS selector (regs->csl) */
+#define FRED_CSL_ENABLE_NMI		_BITUL(28)
+#define FRED_CSL_ALLOW_SINGLE_STEP	_BITUL(25)
+#define FRED_CSL_INTERRUPT_SHADOW	_BITUL(24)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/kernel.h>
+#include <asm/ptrace.h>
+
+/* FRED stack frame information */
+struct fred_info {
+	unsigned long edata;	/* Event data: CR2, DR6, ... */
+	unsigned long resv;
+};
+
+/* Full format of the FRED stack frame */
+struct fred_frame {
+	struct pt_regs   regs;
+	struct fred_info info;
+};
+
+/* Getting the FRED frame information from a pt_regs pointer */
+static __always_inline struct fred_info *fred_info(struct pt_regs *regs)
+{
+	return &container_of(regs, struct fred_frame, regs)->info;
+}
+
+static __always_inline unsigned long fred_event_data(struct pt_regs *regs)
+{
+	return fred_info(regs)->edata;
+}
+
+/*
+ * How FRED event handlers are called.
+ *
+ * FRED event delivery establishes the full supervisor context
+ * by pushing everything related to the event being delivered
+ * to the FRED stack frame, e.g., the faulting linear address
+ * of a #PF is pushed as event data of the FRED #PF stack frame.
+ * Thus a struct pt_regs has everything needed and it's the only
+ * input parameter required for a FRED event handler.
+ */
+#define DECLARE_FRED_HANDLER(f) void f (struct pt_regs *regs)
+#define DEFINE_FRED_HANDLER(f) noinstr DECLARE_FRED_HANDLER(f)
+typedef DECLARE_FRED_HANDLER((*fred_handler));
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_X86_FRED */
+
+#endif /* ASM_X86_FRED_H */