Skip to content

Commit 7911f14

Browse files
aeglIngo Molnar
authored andcommitted
x86/mce: Implement recovery for errors in TDX/SEAM non-root mode
Machine check SMIs (MSMI) signaled during SEAM operation (typically inside TDX guests), on a system with Intel eMCA enabled, might eventually be reported to the kernel #MC handler with the saved RIP on the stack pointing to the instruction in kernel code after the SEAMCALL instruction that entered the SEAM operation. Linux currently says that is a fatal error and shuts down. There is a new bit in IA32_MCG_STATUS that, when set to 1, indicates that the machine check didn't originally occur at that saved RIP, but during SEAM non-root operation. Add new entries to the severity table to detect this for both data load and instruction fetch that set the severity to "AR" (action required). Increase the width of the mcgmask/mcgres fields in "struct severity" from unsigned char to unsigned short since the new bit is in position 12. Action required for these errors is just mark the page as poisoned and return from the machine check handler. HW ABI notes: ============= The SEAM_NR bit in IA32_MCG_STATUS hasn't yet made it into the Intel Software Developers' Manual. But it is described in section 16.5.2 of "Intel(R) Trust Domain Extensions (Intel(R) TDX) Module Base Architecture Specification" downloadable from: https://cdrdv2.intel.com/v1/dl/getContent/733575 Backport notes: =============== Little value in backporting this patch to stable or LTS kernels as this is only relevant with support for TDX, which I assume won't be backported. But for anyone taking this to v6.1 or older, you also need commit: a51cbd0 ("x86/mce: Use severity table to handle uncorrected errors in kernel") Signed-off-by: Tony Luck <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 0e6ebfd commit 7911f14

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

arch/x86/include/asm/mce.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define MCG_CTL_P BIT_ULL(8) /* MCG_CTL register available */
1414
#define MCG_EXT_P BIT_ULL(9) /* Extended registers available */
1515
#define MCG_CMCI_P BIT_ULL(10) /* CMCI supported */
16+
#define MCG_SEAM_NR BIT_ULL(12) /* MCG_STATUS_SEAM_NR supported */
1617
#define MCG_EXT_CNT_MASK 0xff0000 /* Number of Extended registers */
1718
#define MCG_EXT_CNT_SHIFT 16
1819
#define MCG_EXT_CNT(c) (((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT)
@@ -25,6 +26,7 @@
2526
#define MCG_STATUS_EIPV BIT_ULL(1) /* ip points to correct instruction */
2627
#define MCG_STATUS_MCIP BIT_ULL(2) /* machine check in progress */
2728
#define MCG_STATUS_LMCES BIT_ULL(3) /* LMCE signaled */
29+
#define MCG_STATUS_SEAM_NR BIT_ULL(12) /* Machine check inside SEAM non-root mode */
2830

2931
/* MCG_EXT_CTL register defines */
3032
#define MCG_EXT_CTL_LMCE_EN BIT_ULL(0) /* Enable LMCE */

arch/x86/kernel/cpu/mce/core.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,24 @@ noinstr void do_machine_check(struct pt_regs *regs)
15931593
else
15941594
queue_task_work(&m, msg, kill_me_maybe);
15951595

1596+
} else if (m.mcgstatus & MCG_STATUS_SEAM_NR) {
1597+
/*
1598+
* Saved RIP on stack makes it look like the machine check
1599+
* was taken in the kernel on the instruction following
1600+
* the entry to SEAM mode. But MCG_STATUS_SEAM_NR indicates
1601+
* that the machine check was taken inside SEAM non-root
1602+
* mode. CPU core has already marked that guest as dead.
1603+
* It is OK for the kernel to resume execution at the
1604+
* apparent point of the machine check as the fault did
1605+
* not occur there. Mark the page as poisoned so it won't
1606+
* be added to free list when the guest is terminated.
1607+
*/
1608+
if (mce_usable_address(&m)) {
1609+
struct page *p = pfn_to_online_page(m.addr >> PAGE_SHIFT);
1610+
1611+
if (p)
1612+
SetPageHWPoison(p);
1613+
}
15961614
} else {
15971615
/*
15981616
* Handle an MCE which has happened in kernel space but from

arch/x86/kernel/cpu/mce/severity.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ static struct severity {
3939
u64 mask;
4040
u64 result;
4141
unsigned char sev;
42-
unsigned char mcgmask;
43-
unsigned char mcgres;
42+
unsigned short mcgmask;
43+
unsigned short mcgres;
4444
unsigned char ser;
4545
unsigned char context;
4646
unsigned char excp;
@@ -173,6 +173,18 @@ static struct severity {
173173
SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_INSTR),
174174
USER
175175
),
176+
MCESEV(
177+
AR, "Data load error in SEAM non-root mode",
178+
SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA),
179+
MCGMASK(MCG_STATUS_SEAM_NR, MCG_STATUS_SEAM_NR),
180+
KERNEL
181+
),
182+
MCESEV(
183+
AR, "Instruction fetch error in SEAM non-root mode",
184+
SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_INSTR),
185+
MCGMASK(MCG_STATUS_SEAM_NR, MCG_STATUS_SEAM_NR),
186+
KERNEL
187+
),
176188
MCESEV(
177189
PANIC, "Data load in unrecoverable area of kernel",
178190
SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA),

0 commit comments

Comments
 (0)