Skip to content

Commit 373e715

Browse files
kirylhansendc
authored andcommitted
x86/tdx: Panic on bad configs that #VE on "private" memory access
All normal kernel memory is "TDX private memory". This includes everything from kernel stacks to kernel text. Handling exceptions on arbitrary accesses to kernel memory is essentially impossible because they can happen in horribly nasty places like kernel entry/exit. But, TDX hardware can theoretically _deliver_ a virtualization exception (#VE) on any access to private memory. But, it's not as bad as it sounds. TDX can be configured to never deliver these exceptions on private memory with a "TD attribute" called ATTR_SEPT_VE_DISABLE. The guest has no way to *set* this attribute, but it can check it. Ensure ATTR_SEPT_VE_DISABLE is set in early boot. panic() if it is unset. There is no sane way for Linux to run with this attribute clear so a panic() is appropriate. There's small window during boot before the check where kernel has an early #VE handler. But the handler is only for port I/O and will also panic() as soon as it sees any other #VE, such as a one generated by a private memory access. [ dhansen: Rewrite changelog and rebase on new tdx_parse_tdinfo(). Add Kirill's tested-by because I made changes since he wrote this. ] Fixes: 9a22bf6 ("x86/traps: Add #VE support for TDX guest") Reported-by: [email protected] Signed-off-by: Kirill A. Shutemov <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Tested-by: Kirill A. Shutemov <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/all/20221028141220.29217-3-kirill.shutemov%40linux.intel.com
1 parent a6dd6f3 commit 373e715

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

arch/x86/coco/tdx/tdx.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#define VE_GET_PORT_NUM(e) ((e) >> 16)
3535
#define VE_IS_IO_STRING(e) ((e) & BIT(4))
3636

37+
#define ATTR_SEPT_VE_DISABLE BIT(28)
38+
3739
/*
3840
* Wrapper for standard use of __tdx_hypercall with no output aside from
3941
* return code.
@@ -102,26 +104,35 @@ static void tdx_parse_tdinfo(u64 *cc_mask)
102104
{
103105
struct tdx_module_output out;
104106
unsigned int gpa_width;
107+
u64 td_attr;
105108

106109
/*
107110
* TDINFO TDX module call is used to get the TD execution environment
108111
* information like GPA width, number of available vcpus, debug mode
109112
* information, etc. More details about the ABI can be found in TDX
110113
* Guest-Host-Communication Interface (GHCI), section 2.4.2 TDCALL
111114
* [TDG.VP.INFO].
112-
*
113-
* The GPA width that comes out of this call is critical. TDX guests
114-
* can not meaningfully run without it.
115115
*/
116116
tdx_module_call(TDX_GET_INFO, 0, 0, 0, 0, &out);
117117

118-
gpa_width = out.rcx & GENMASK(5, 0);
119-
120118
/*
121119
* The highest bit of a guest physical address is the "sharing" bit.
122120
* Set it for shared pages and clear it for private pages.
121+
*
122+
* The GPA width that comes out of this call is critical. TDX guests
123+
* can not meaningfully run without it.
123124
*/
125+
gpa_width = out.rcx & GENMASK(5, 0);
124126
*cc_mask = BIT_ULL(gpa_width - 1);
127+
128+
/*
129+
* The kernel can not handle #VE's when accessing normal kernel
130+
* memory. Ensure that no #VE will be delivered for accesses to
131+
* TD-private memory. Only VMM-shared memory (MMIO) will #VE.
132+
*/
133+
td_attr = out.rdx;
134+
if (!(td_attr & ATTR_SEPT_VE_DISABLE))
135+
panic("TD misconfiguration: SEPT_VE_DISABLE attibute must be set.\n");
125136
}
126137

127138
/*

0 commit comments

Comments
 (0)