Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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()

+132 -27
+60 -25
arch/x86/coco/tdx/tdcall.S
··· 13 13 /* 14 14 * Bitmasks of exposed registers (with VMM). 15 15 */ 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) 16 22 #define TDX_R10 BIT(10) 17 23 #define TDX_R11 BIT(11) 18 24 #define TDX_R12 BIT(12) ··· 33 27 * details can be found in TDX GHCI specification, section 34 28 * titled "TDCALL [TDG.VP.VMCALL] leaf". 35 29 */ 36 - #define TDVMCALL_EXPOSE_REGS_MASK ( TDX_R10 | TDX_R11 | \ 37 - TDX_R12 | TDX_R13 | \ 38 - TDX_R14 | TDX_R15 ) 30 + #define TDVMCALL_EXPOSE_REGS_MASK \ 31 + ( TDX_RDX | TDX_RBX | TDX_RSI | TDX_RDI | TDX_R8 | TDX_R9 | \ 32 + TDX_R10 | TDX_R11 | TDX_R12 | TDX_R13 | TDX_R14 | TDX_R15 ) 39 33 40 34 .section .noinstr.text, "ax" 41 35 ··· 132 126 push %r14 133 127 push %r13 134 128 push %r12 129 + push %rbx 130 + 131 + /* Free RDI and RSI to be used as TDVMCALL arguments */ 132 + movq %rdi, %rax 133 + push %rsi 134 + 135 + /* Copy hypercall registers from arg struct: */ 136 + movq TDX_HYPERCALL_r8(%rax), %r8 137 + movq TDX_HYPERCALL_r9(%rax), %r9 138 + movq TDX_HYPERCALL_r10(%rax), %r10 139 + movq TDX_HYPERCALL_r11(%rax), %r11 140 + movq TDX_HYPERCALL_r12(%rax), %r12 141 + movq TDX_HYPERCALL_r13(%rax), %r13 142 + movq TDX_HYPERCALL_r14(%rax), %r14 143 + movq TDX_HYPERCALL_r15(%rax), %r15 144 + movq TDX_HYPERCALL_rdi(%rax), %rdi 145 + movq TDX_HYPERCALL_rsi(%rax), %rsi 146 + movq TDX_HYPERCALL_rbx(%rax), %rbx 147 + movq TDX_HYPERCALL_rdx(%rax), %rdx 148 + 149 + push %rax 135 150 136 151 /* Mangle function call ABI into TDCALL ABI: */ 137 152 /* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */ 138 153 xor %eax, %eax 139 - 140 - /* Copy hypercall registers from arg struct: */ 141 - movq TDX_HYPERCALL_r10(%rdi), %r10 142 - movq TDX_HYPERCALL_r11(%rdi), %r11 143 - movq TDX_HYPERCALL_r12(%rdi), %r12 144 - movq TDX_HYPERCALL_r13(%rdi), %r13 145 - movq TDX_HYPERCALL_r14(%rdi), %r14 146 - movq TDX_HYPERCALL_r15(%rdi), %r15 147 154 148 155 movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx 149 156 150 157 tdcall 151 158 152 159 /* 153 - * RAX==0 indicates a failure of the TDVMCALL mechanism itself and that 160 + * RAX!=0 indicates a failure of the TDVMCALL mechanism itself and that 154 161 * something has gone horribly wrong with the TDX module. 155 162 * 156 163 * The return status of the hypercall operation is in a separate ··· 173 154 testq %rax, %rax 174 155 jne .Lpanic 175 156 157 + pop %rax 158 + 159 + /* Copy hypercall result registers to arg struct if needed */ 160 + testq $TDX_HCALL_HAS_OUTPUT, (%rsp) 161 + jz .Lout 162 + 163 + movq %r8, TDX_HYPERCALL_r8(%rax) 164 + movq %r9, TDX_HYPERCALL_r9(%rax) 165 + movq %r10, TDX_HYPERCALL_r10(%rax) 166 + movq %r11, TDX_HYPERCALL_r11(%rax) 167 + movq %r12, TDX_HYPERCALL_r12(%rax) 168 + movq %r13, TDX_HYPERCALL_r13(%rax) 169 + movq %r14, TDX_HYPERCALL_r14(%rax) 170 + movq %r15, TDX_HYPERCALL_r15(%rax) 171 + movq %rdi, TDX_HYPERCALL_rdi(%rax) 172 + movq %rsi, TDX_HYPERCALL_rsi(%rax) 173 + movq %rbx, TDX_HYPERCALL_rbx(%rax) 174 + movq %rdx, TDX_HYPERCALL_rdx(%rax) 175 + .Lout: 176 176 /* TDVMCALL leaf return code is in R10 */ 177 177 movq %r10, %rax 178 178 179 - /* Copy hypercall result registers to arg struct if needed */ 180 - testq $TDX_HCALL_HAS_OUTPUT, %rsi 181 - jz .Lout 182 - 183 - movq %r10, TDX_HYPERCALL_r10(%rdi) 184 - movq %r11, TDX_HYPERCALL_r11(%rdi) 185 - movq %r12, TDX_HYPERCALL_r12(%rdi) 186 - movq %r13, TDX_HYPERCALL_r13(%rdi) 187 - movq %r14, TDX_HYPERCALL_r14(%rdi) 188 - movq %r15, TDX_HYPERCALL_r15(%rdi) 189 - .Lout: 190 179 /* 191 180 * Zero out registers exposed to the VMM to avoid speculative execution 192 181 * with VMM-controlled values. This needs to include all registers 193 - * present in TDVMCALL_EXPOSE_REGS_MASK (except R12-R15). R12-R15 194 - * context will be restored. 182 + * present in TDVMCALL_EXPOSE_REGS_MASK, except RBX, and R12-R15 which 183 + * will be restored. 195 184 */ 185 + xor %r8d, %r8d 186 + xor %r9d, %r9d 196 187 xor %r10d, %r10d 197 188 xor %r11d, %r11d 189 + xor %rdi, %rdi 190 + xor %rdx, %rdx 191 + 192 + /* Remove TDX_HCALL_* flags from the stack */ 193 + pop %rsi 198 194 199 195 /* Restore callee-saved GPRs as mandated by the x86_64 ABI */ 196 + pop %rbx 200 197 pop %r12 201 198 pop %r13 202 199 pop %r14
+60 -2
arch/x86/coco/tdx/tdx.c
··· 19 19 #define TDX_GET_VEINFO 3 20 20 #define TDX_GET_REPORT 4 21 21 #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 22 26 23 27 /* TDX hypercall Leaf IDs */ 24 28 #define TDVMCALL_MAP_GPA 0x10001 29 + #define TDVMCALL_REPORT_FATAL_ERROR 0x10003 25 30 26 31 /* MMIO direction */ 27 32 #define EPT_READ 0 ··· 42 37 #define VE_GET_PORT_NUM(e) ((e) >> 16) 43 38 #define VE_IS_IO_STRING(e) ((e) & BIT(4)) 44 39 40 + #define ATTR_DEBUG BIT(0) 45 41 #define ATTR_SEPT_VE_DISABLE BIT(28) 46 42 47 43 /* TDX Module call error codes */ ··· 147 141 } 148 142 EXPORT_SYMBOL_GPL(tdx_mcall_get_report0); 149 143 144 + static void __noreturn tdx_panic(const char *msg) 145 + { 146 + struct tdx_hypercall_args args = { 147 + .r10 = TDX_HYPERCALL_STANDARD, 148 + .r11 = TDVMCALL_REPORT_FATAL_ERROR, 149 + .r12 = 0, /* Error code: 0 is Panic */ 150 + }; 151 + union { 152 + /* Define register order according to the GHCI */ 153 + struct { u64 r14, r15, rbx, rdi, rsi, r8, r9, rdx; }; 154 + 155 + char str[64]; 156 + } message; 157 + 158 + /* VMM assumes '\0' in byte 65, if the message took all 64 bytes */ 159 + strncpy(message.str, msg, 64); 160 + 161 + args.r8 = message.r8; 162 + args.r9 = message.r9; 163 + args.r14 = message.r14; 164 + args.r15 = message.r15; 165 + args.rdi = message.rdi; 166 + args.rsi = message.rsi; 167 + args.rbx = message.rbx; 168 + args.rdx = message.rdx; 169 + 170 + /* 171 + * This hypercall should never return and it is not safe 172 + * to keep the guest running. Call it forever if it 173 + * happens to return. 174 + */ 175 + while (1) 176 + __tdx_hypercall(&args, 0); 177 + } 178 + 150 179 static void tdx_parse_tdinfo(u64 *cc_mask) 151 180 { 152 181 struct tdx_module_output out; ··· 213 172 * TD-private memory. Only VMM-shared memory (MMIO) will #VE. 214 173 */ 215 174 td_attr = out.rdx; 216 - if (!(td_attr & ATTR_SEPT_VE_DISABLE)) 217 - panic("TD misconfiguration: SEPT_VE_DISABLE attibute must be set.\n"); 175 + if (!(td_attr & ATTR_SEPT_VE_DISABLE)) { 176 + const char *msg = "TD misconfiguration: SEPT_VE_DISABLE attribute must be set."; 177 + 178 + /* Relax SEPT_VE_DISABLE check for debug TD. */ 179 + if (td_attr & ATTR_DEBUG) 180 + pr_warn("%s\n", msg); 181 + else 182 + tdx_panic(msg); 183 + } 218 184 } 219 185 220 186 /* ··· 665 617 } 666 618 } 667 619 620 + static inline bool is_private_gpa(u64 gpa) 621 + { 622 + return gpa == cc_mkenc(gpa); 623 + } 624 + 668 625 /* 669 626 * Handle the kernel #VE. 670 627 * ··· 688 635 case EXIT_REASON_CPUID: 689 636 return handle_cpuid(regs, ve); 690 637 case EXIT_REASON_EPT_VIOLATION: 638 + if (is_private_gpa(ve->gpa)) 639 + panic("Unexpected EPT-violation on private memory."); 691 640 return handle_mmio(regs, ve); 692 641 case EXIT_REASON_IO_INSTRUCTION: 693 642 return handle_io(regs, ve); ··· 855 800 cc_set_vendor(CC_VENDOR_INTEL); 856 801 tdx_parse_tdinfo(&cc_mask); 857 802 cc_set_mask(cc_mask); 803 + 804 + /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */ 805 + tdx_module_call(TDX_WR, 0, TDCS_NOTIFY_ENABLES, 0, -1ULL, NULL); 858 806 859 807 /* 860 808 * All bits above GPA width are reserved and kernel treats shared bit
+6
arch/x86/include/asm/shared/tdx.h
··· 21 21 * This is a software only structure and not part of the TDX module/VMM ABI. 22 22 */ 23 23 struct tdx_hypercall_args { 24 + u64 r8; 25 + u64 r9; 24 26 u64 r10; 25 27 u64 r11; 26 28 u64 r12; 27 29 u64 r13; 28 30 u64 r14; 29 31 u64 r15; 32 + u64 rdi; 33 + u64 rsi; 34 + u64 rbx; 35 + u64 rdx; 30 36 }; 31 37 32 38 /* Used to request services from the VMM */
+6
arch/x86/kernel/asm-offsets.c
··· 76 76 OFFSET(TDX_MODULE_r11, tdx_module_output, r11); 77 77 78 78 BLANK(); 79 + OFFSET(TDX_HYPERCALL_r8, tdx_hypercall_args, r8); 80 + OFFSET(TDX_HYPERCALL_r9, tdx_hypercall_args, r9); 79 81 OFFSET(TDX_HYPERCALL_r10, tdx_hypercall_args, r10); 80 82 OFFSET(TDX_HYPERCALL_r11, tdx_hypercall_args, r11); 81 83 OFFSET(TDX_HYPERCALL_r12, tdx_hypercall_args, r12); 82 84 OFFSET(TDX_HYPERCALL_r13, tdx_hypercall_args, r13); 83 85 OFFSET(TDX_HYPERCALL_r14, tdx_hypercall_args, r14); 84 86 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); 85 91 86 92 BLANK(); 87 93 OFFSET(BP_scratch, boot_params, scratch);