x86/ptrace: Add FRED additional information to the pt_regs structure
authorXin Li <xin3.li@intel.com>
Tue, 5 Dec 2023 10:50:03 +0000 (02:50 -0800)
committerBorislav Petkov (AMD) <bp@alien8.de>
Wed, 31 Jan 2024 21:01:20 +0000 (22:01 +0100)
FRED defines additional information in the upper 48 bits of cs/ss
fields. Therefore add the information definitions into the pt_regs
structure.

Specifically introduce a new structure fred_ss to denote the FRED flags
above SS selector, which avoids FRED_SSX_ macros and makes the code
simpler and easier to read.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Originally-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Xin Li <xin3.li@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Tested-by: Shan Kang <shan.kang@intel.com>
Link: https://lore.kernel.org/r/20231205105030.8698-15-xin3.li@intel.com
arch/x86/include/asm/ptrace.h

index b268cd2a2d01c4dcd85253a7045cbbb7afd18ee1..5a83fbd9bc0b44f5bac9a4b3447e3b52fc5e1abc 100644 (file)
@@ -56,6 +56,50 @@ struct pt_regs {
 
 #else /* __i386__ */
 
+struct fred_cs {
+               /* CS selector */
+       u64     cs      : 16,
+               /* Stack level at event time */
+               sl      :  2,
+               /* IBT in WAIT_FOR_ENDBRANCH state */
+               wfe     :  1,
+                       : 45;
+};
+
+struct fred_ss {
+               /* SS selector */
+       u64     ss      : 16,
+               /* STI state */
+               sti     :  1,
+               /* Set if syscall, sysenter or INT n */
+               swevent :  1,
+               /* Event is NMI type */
+               nmi     :  1,
+                       : 13,
+               /* Event vector */
+               vector  :  8,
+                       :  8,
+               /* Event type */
+               type    :  4,
+                       :  4,
+               /* Event was incident to enclave execution */
+               enclave :  1,
+               /* CPU was in long mode */
+               lm      :  1,
+               /*
+                * Nested exception during FRED delivery, not set
+                * for #DF.
+                */
+               nested  :  1,
+                       :  1,
+               /*
+                * The length of the instruction causing the event.
+                * Only set for INTO, INT1, INT3, INT n, SYSCALL
+                * and SYSENTER.  0 otherwise.
+                */
+               insnlen :  4;
+};
+
 struct pt_regs {
        /*
         * C ABI says these regs are callee-preserved. They aren't saved on
@@ -85,6 +129,12 @@ struct pt_regs {
         * - the syscall number (syscall, sysenter, int80)
         * - error_code stored by the CPU on traps and exceptions
         * - the interrupt number for device interrupts
+        *
+        * A FRED stack frame starts here:
+        *   1) It _always_ includes an error code;
+        *
+        *   2) The return frame for ERET[US] starts here, but
+        *      the content of orig_ax is ignored.
         */
        unsigned long orig_ax;
 
@@ -92,24 +142,30 @@ struct pt_regs {
        unsigned long ip;
 
        union {
-               /* The full 64-bit data slot containing CS */
-               u64             csx;
                /* CS selector */
                u16             cs;
+               /* The extended 64-bit data slot containing CS */
+               u64             csx;
+               /* The FRED CS extension */
+               struct fred_cs  fred_cs;
        };
 
        unsigned long flags;
        unsigned long sp;
 
        union {
-               /* The full 64-bit data slot containing SS */
-               u64             ssx;
                /* SS selector */
                u16             ss;
+               /* The extended 64-bit data slot containing SS */
+               u64             ssx;
+               /* The FRED SS extension */
+               struct fred_ss  fred_ss;
        };
 
        /*
-        * Top of stack on IDT systems.
+        * Top of stack on IDT systems, while FRED systems have extra fields
+        * defined above for storing exception related information, e.g. CR2 or
+        * DR6.
         */
 };