[RFC,14/32] x86/fred: header file with FRED definitions
Commit Message
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
> +/*
> + * 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 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 :)
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.
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.
new file mode 100644
@@ -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 */