Skip to content

Commit d8e4731

Browse files
committed
Merge tag 'x86_tdx_for_6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull Intel Trust Domain Extensions (TDX) updates from Dave Hansen: "Other than a minor fixup, the content here is to ensure that TDX guests never see virtualization exceptions (#VE's) that might be induced by the untrusted VMM. This is a highly desirable property. Without it, #VE exception handling would fall somewhere between NMIs, machine checks and total insanity. With it, #VE handling remains pretty mundane. Summary: - Fixup comment typo - Prevent unexpected #VE's from: - Hosts removing perfectly good guest mappings (SEPT_VE_DISABLE) - Excessive #VE notifications (NOTIFY_ENABLES) which are delivered via a #VE" * tag 'x86_tdx_for_6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/tdx: Do not corrupt frame-pointer in __tdx_hypercall() x86/tdx: Disable NOTIFY_ENABLES x86/tdx: Relax SEPT_VE_DISABLE check for debug TD x86/tdx: Use ReportFatalError to report missing SEPT_VE_DISABLE x86/tdx: Expand __tdx_hypercall() to handle more arguments x86/tdx: Refactor __tdx_hypercall() to allow pass down more arguments x86/tdx: Add more registers to struct tdx_hypercall_args x86/tdx: Fix typo in comment in __tdx_hypercall()
2 parents 489fa31 + 1e70c68 commit d8e4731

File tree

4 files changed

+130
-25
lines changed

4 files changed

+130
-25
lines changed

arch/x86/coco/tdx/tdcall.S

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
/*
1414
* Bitmasks of exposed registers (with VMM).
1515
*/
16+
#define TDX_RDX BIT(2)
17+
#define TDX_RBX BIT(3)
18+
#define TDX_RSI BIT(6)
19+
#define TDX_RDI BIT(7)
20+
#define TDX_R8 BIT(8)
21+
#define TDX_R9 BIT(9)
1622
#define TDX_R10 BIT(10)
1723
#define TDX_R11 BIT(11)
1824
#define TDX_R12 BIT(12)
@@ -27,9 +33,9 @@
2733
* details can be found in TDX GHCI specification, section
2834
* titled "TDCALL [TDG.VP.VMCALL] leaf".
2935
*/
30-
#define TDVMCALL_EXPOSE_REGS_MASK ( TDX_R10 | TDX_R11 | \
31-
TDX_R12 | TDX_R13 | \
32-
TDX_R14 | TDX_R15 )
36+
#define TDVMCALL_EXPOSE_REGS_MASK \
37+
( TDX_RDX | TDX_RBX | TDX_RSI | TDX_RDI | TDX_R8 | TDX_R9 | \
38+
TDX_R10 | TDX_R11 | TDX_R12 | TDX_R13 | TDX_R14 | TDX_R15 )
3339

3440
.section .noinstr.text, "ax"
3541

@@ -126,25 +132,38 @@ SYM_FUNC_START(__tdx_hypercall)
126132
push %r14
127133
push %r13
128134
push %r12
135+
push %rbx
136+
137+
/* Free RDI and RSI to be used as TDVMCALL arguments */
138+
movq %rdi, %rax
139+
push %rsi
140+
141+
/* Copy hypercall registers from arg struct: */
142+
movq TDX_HYPERCALL_r8(%rax), %r8
143+
movq TDX_HYPERCALL_r9(%rax), %r9
144+
movq TDX_HYPERCALL_r10(%rax), %r10
145+
movq TDX_HYPERCALL_r11(%rax), %r11
146+
movq TDX_HYPERCALL_r12(%rax), %r12
147+
movq TDX_HYPERCALL_r13(%rax), %r13
148+
movq TDX_HYPERCALL_r14(%rax), %r14
149+
movq TDX_HYPERCALL_r15(%rax), %r15
150+
movq TDX_HYPERCALL_rdi(%rax), %rdi
151+
movq TDX_HYPERCALL_rsi(%rax), %rsi
152+
movq TDX_HYPERCALL_rbx(%rax), %rbx
153+
movq TDX_HYPERCALL_rdx(%rax), %rdx
154+
155+
push %rax
129156

130157
/* Mangle function call ABI into TDCALL ABI: */
131158
/* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */
132159
xor %eax, %eax
133160

134-
/* Copy hypercall registers from arg struct: */
135-
movq TDX_HYPERCALL_r10(%rdi), %r10
136-
movq TDX_HYPERCALL_r11(%rdi), %r11
137-
movq TDX_HYPERCALL_r12(%rdi), %r12
138-
movq TDX_HYPERCALL_r13(%rdi), %r13
139-
movq TDX_HYPERCALL_r14(%rdi), %r14
140-
movq TDX_HYPERCALL_r15(%rdi), %r15
141-
142161
movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx
143162

144163
tdcall
145164

146165
/*
147-
* RAX==0 indicates a failure of the TDVMCALL mechanism itself and that
166+
* RAX!=0 indicates a failure of the TDVMCALL mechanism itself and that
148167
* something has gone horribly wrong with the TDX module.
149168
*
150169
* The return status of the hypercall operation is in a separate
@@ -154,30 +173,46 @@ SYM_FUNC_START(__tdx_hypercall)
154173
testq %rax, %rax
155174
jne .Lpanic
156175

157-
/* TDVMCALL leaf return code is in R10 */
158-
movq %r10, %rax
176+
pop %rax
159177

160178
/* Copy hypercall result registers to arg struct if needed */
161-
testq $TDX_HCALL_HAS_OUTPUT, %rsi
179+
testq $TDX_HCALL_HAS_OUTPUT, (%rsp)
162180
jz .Lout
163181

164-
movq %r10, TDX_HYPERCALL_r10(%rdi)
165-
movq %r11, TDX_HYPERCALL_r11(%rdi)
166-
movq %r12, TDX_HYPERCALL_r12(%rdi)
167-
movq %r13, TDX_HYPERCALL_r13(%rdi)
168-
movq %r14, TDX_HYPERCALL_r14(%rdi)
169-
movq %r15, TDX_HYPERCALL_r15(%rdi)
182+
movq %r8, TDX_HYPERCALL_r8(%rax)
183+
movq %r9, TDX_HYPERCALL_r9(%rax)
184+
movq %r10, TDX_HYPERCALL_r10(%rax)
185+
movq %r11, TDX_HYPERCALL_r11(%rax)
186+
movq %r12, TDX_HYPERCALL_r12(%rax)
187+
movq %r13, TDX_HYPERCALL_r13(%rax)
188+
movq %r14, TDX_HYPERCALL_r14(%rax)
189+
movq %r15, TDX_HYPERCALL_r15(%rax)
190+
movq %rdi, TDX_HYPERCALL_rdi(%rax)
191+
movq %rsi, TDX_HYPERCALL_rsi(%rax)
192+
movq %rbx, TDX_HYPERCALL_rbx(%rax)
193+
movq %rdx, TDX_HYPERCALL_rdx(%rax)
170194
.Lout:
195+
/* TDVMCALL leaf return code is in R10 */
196+
movq %r10, %rax
197+
171198
/*
172199
* Zero out registers exposed to the VMM to avoid speculative execution
173200
* with VMM-controlled values. This needs to include all registers
174-
* present in TDVMCALL_EXPOSE_REGS_MASK (except R12-R15). R12-R15
175-
* context will be restored.
201+
* present in TDVMCALL_EXPOSE_REGS_MASK, except RBX, and R12-R15 which
202+
* will be restored.
176203
*/
204+
xor %r8d, %r8d
205+
xor %r9d, %r9d
177206
xor %r10d, %r10d
178207
xor %r11d, %r11d
208+
xor %rdi, %rdi
209+
xor %rdx, %rdx
210+
211+
/* Remove TDX_HCALL_* flags from the stack */
212+
pop %rsi
179213

180214
/* Restore callee-saved GPRs as mandated by the x86_64 ABI */
215+
pop %rbx
181216
pop %r12
182217
pop %r13
183218
pop %r14

arch/x86/coco/tdx/tdx.c

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,14 @@
1919
#define TDX_GET_VEINFO 3
2020
#define TDX_GET_REPORT 4
2121
#define TDX_ACCEPT_PAGE 6
22+
#define TDX_WR 8
23+
24+
/* TDCS fields. To be used by TDG.VM.WR and TDG.VM.RD module calls */
25+
#define TDCS_NOTIFY_ENABLES 0x9100000000000010
2226

2327
/* TDX hypercall Leaf IDs */
2428
#define TDVMCALL_MAP_GPA 0x10001
29+
#define TDVMCALL_REPORT_FATAL_ERROR 0x10003
2530

2631
/* MMIO direction */
2732
#define EPT_READ 0
@@ -37,6 +42,7 @@
3742
#define VE_GET_PORT_NUM(e) ((e) >> 16)
3843
#define VE_IS_IO_STRING(e) ((e) & BIT(4))
3944

45+
#define ATTR_DEBUG BIT(0)
4046
#define ATTR_SEPT_VE_DISABLE BIT(28)
4147

4248
/* TDX Module call error codes */
@@ -141,6 +147,41 @@ int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport)
141147
}
142148
EXPORT_SYMBOL_GPL(tdx_mcall_get_report0);
143149

150+
static void __noreturn tdx_panic(const char *msg)
151+
{
152+
struct tdx_hypercall_args args = {
153+
.r10 = TDX_HYPERCALL_STANDARD,
154+
.r11 = TDVMCALL_REPORT_FATAL_ERROR,
155+
.r12 = 0, /* Error code: 0 is Panic */
156+
};
157+
union {
158+
/* Define register order according to the GHCI */
159+
struct { u64 r14, r15, rbx, rdi, rsi, r8, r9, rdx; };
160+
161+
char str[64];
162+
} message;
163+
164+
/* VMM assumes '\0' in byte 65, if the message took all 64 bytes */
165+
strncpy(message.str, msg, 64);
166+
167+
args.r8 = message.r8;
168+
args.r9 = message.r9;
169+
args.r14 = message.r14;
170+
args.r15 = message.r15;
171+
args.rdi = message.rdi;
172+
args.rsi = message.rsi;
173+
args.rbx = message.rbx;
174+
args.rdx = message.rdx;
175+
176+
/*
177+
* This hypercall should never return and it is not safe
178+
* to keep the guest running. Call it forever if it
179+
* happens to return.
180+
*/
181+
while (1)
182+
__tdx_hypercall(&args, 0);
183+
}
184+
144185
static void tdx_parse_tdinfo(u64 *cc_mask)
145186
{
146187
struct tdx_module_output out;
@@ -172,8 +213,15 @@ static void tdx_parse_tdinfo(u64 *cc_mask)
172213
* TD-private memory. Only VMM-shared memory (MMIO) will #VE.
173214
*/
174215
td_attr = out.rdx;
175-
if (!(td_attr & ATTR_SEPT_VE_DISABLE))
176-
panic("TD misconfiguration: SEPT_VE_DISABLE attibute must be set.\n");
216+
if (!(td_attr & ATTR_SEPT_VE_DISABLE)) {
217+
const char *msg = "TD misconfiguration: SEPT_VE_DISABLE attribute must be set.";
218+
219+
/* Relax SEPT_VE_DISABLE check for debug TD. */
220+
if (td_attr & ATTR_DEBUG)
221+
pr_warn("%s\n", msg);
222+
else
223+
tdx_panic(msg);
224+
}
177225
}
178226

179227
/*
@@ -617,6 +665,11 @@ static int virt_exception_user(struct pt_regs *regs, struct ve_info *ve)
617665
}
618666
}
619667

668+
static inline bool is_private_gpa(u64 gpa)
669+
{
670+
return gpa == cc_mkenc(gpa);
671+
}
672+
620673
/*
621674
* Handle the kernel #VE.
622675
*
@@ -635,6 +688,8 @@ static int virt_exception_kernel(struct pt_regs *regs, struct ve_info *ve)
635688
case EXIT_REASON_CPUID:
636689
return handle_cpuid(regs, ve);
637690
case EXIT_REASON_EPT_VIOLATION:
691+
if (is_private_gpa(ve->gpa))
692+
panic("Unexpected EPT-violation on private memory.");
638693
return handle_mmio(regs, ve);
639694
case EXIT_REASON_IO_INSTRUCTION:
640695
return handle_io(regs, ve);
@@ -801,6 +856,9 @@ void __init tdx_early_init(void)
801856
tdx_parse_tdinfo(&cc_mask);
802857
cc_set_mask(cc_mask);
803858

859+
/* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */
860+
tdx_module_call(TDX_WR, 0, TDCS_NOTIFY_ENABLES, 0, -1ULL, NULL);
861+
804862
/*
805863
* All bits above GPA width are reserved and kernel treats shared bit
806864
* as flag, not as part of physical address.

arch/x86/include/asm/shared/tdx.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,18 @@
2121
* This is a software only structure and not part of the TDX module/VMM ABI.
2222
*/
2323
struct tdx_hypercall_args {
24+
u64 r8;
25+
u64 r9;
2426
u64 r10;
2527
u64 r11;
2628
u64 r12;
2729
u64 r13;
2830
u64 r14;
2931
u64 r15;
32+
u64 rdi;
33+
u64 rsi;
34+
u64 rbx;
35+
u64 rdx;
3036
};
3137

3238
/* Used to request services from the VMM */

arch/x86/kernel/asm-offsets.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,18 @@ static void __used common(void)
7676
OFFSET(TDX_MODULE_r11, tdx_module_output, r11);
7777

7878
BLANK();
79+
OFFSET(TDX_HYPERCALL_r8, tdx_hypercall_args, r8);
80+
OFFSET(TDX_HYPERCALL_r9, tdx_hypercall_args, r9);
7981
OFFSET(TDX_HYPERCALL_r10, tdx_hypercall_args, r10);
8082
OFFSET(TDX_HYPERCALL_r11, tdx_hypercall_args, r11);
8183
OFFSET(TDX_HYPERCALL_r12, tdx_hypercall_args, r12);
8284
OFFSET(TDX_HYPERCALL_r13, tdx_hypercall_args, r13);
8385
OFFSET(TDX_HYPERCALL_r14, tdx_hypercall_args, r14);
8486
OFFSET(TDX_HYPERCALL_r15, tdx_hypercall_args, r15);
87+
OFFSET(TDX_HYPERCALL_rdi, tdx_hypercall_args, rdi);
88+
OFFSET(TDX_HYPERCALL_rsi, tdx_hypercall_args, rsi);
89+
OFFSET(TDX_HYPERCALL_rbx, tdx_hypercall_args, rbx);
90+
OFFSET(TDX_HYPERCALL_rdx, tdx_hypercall_args, rdx);
8591

8692
BLANK();
8793
OFFSET(BP_scratch, boot_params, scratch);

0 commit comments

Comments
 (0)