Skip to content

Commit 7b80413

Browse files
kaihuanghansendc
authored andcommitted
x86/virt/tdx: Make TDX_MODULE_CALL handle SEAMCALL #UD and #GP
SEAMCALL instruction causes #UD if the CPU isn't in VMX operation. Currently the TDX_MODULE_CALL assembly doesn't handle #UD, thus making SEAMCALL when VMX is disabled would cause Oops. Unfortunately, there are legal cases that SEAMCALL can be made when VMX is disabled. For instance, VMX can be disabled due to emergency reboot while there are still TDX guests running. Extend the TDX_MODULE_CALL assembly to return an error code for #UD to handle this case gracefully, e.g., KVM can then quietly eat all SEAMCALL errors caused by emergency reboot. SEAMCALL instruction also causes #GP when TDX isn't enabled by the BIOS. Use _ASM_EXTABLE_FAULT() to catch both exceptions with the trap number recorded, and define two new error codes by XORing the trap number to the TDX_SW_ERROR. This opportunistically handles #GP too while using the same simple assembly code. A bonus is when kernel mistakenly calls SEAMCALL when CPU isn't in VMX operation, or when TDX isn't enabled by the BIOS, or when the BIOS is buggy, the kernel can get a nicer error code rather than a less understandable Oops. This is basically based on Peter's code. Suggested-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Kai Huang <kai.huang@intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/all/de975832a367f476aab2d0eb0d9de66019a16b54.1692096753.git.kai.huang%40intel.com
1 parent c33621b commit 7b80413

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

arch/x86/include/asm/tdx.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <asm/errno.h>
1010
#include <asm/ptrace.h>
11+
#include <asm/trapnr.h>
1112
#include <asm/shared/tdx.h>
1213

1314
/*
@@ -20,6 +21,9 @@
2021
#define TDX_SW_ERROR (TDX_ERROR | GENMASK_ULL(47, 40))
2122
#define TDX_SEAMCALL_VMFAILINVALID (TDX_SW_ERROR | _UL(0xFFFF0000))
2223

24+
#define TDX_SEAMCALL_GP (TDX_SW_ERROR | X86_TRAP_GP)
25+
#define TDX_SEAMCALL_UD (TDX_SW_ERROR | X86_TRAP_UD)
26+
2327
#ifndef __ASSEMBLY__
2428

2529
/*

arch/x86/virt/vmx/tdx/tdxcall.S

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
22
#include <asm/asm-offsets.h>
33
#include <asm/frame.h>
4+
#include <asm/asm.h>
45
#include <asm/tdx.h>
56

67
/*
@@ -85,6 +86,7 @@
8586
.endif /* \saved */
8687

8788
.if \host
89+
.Lseamcall\@:
8890
seamcall
8991
/*
9092
* SEAMCALL instruction is essentially a VMExit from VMX root
@@ -191,11 +193,28 @@
191193
.if \host
192194
.Lseamcall_vmfailinvalid\@:
193195
mov $TDX_SEAMCALL_VMFAILINVALID, %rax
196+
jmp .Lseamcall_fail\@
197+
198+
.Lseamcall_trap\@:
199+
/*
200+
* SEAMCALL caused #GP or #UD. By reaching here RAX contains
201+
* the trap number. Convert the trap number to the TDX error
202+
* code by setting TDX_SW_ERROR to the high 32-bits of RAX.
203+
*
204+
* Note cannot OR TDX_SW_ERROR directly to RAX as OR instruction
205+
* only accepts 32-bit immediate at most.
206+
*/
207+
movq $TDX_SW_ERROR, %rdi
208+
orq %rdi, %rax
209+
210+
.Lseamcall_fail\@:
194211
.if \ret && \saved
195212
/* pop the unused structure pointer back to RSI */
196213
popq %rsi
197214
.endif
198215
jmp .Lout\@
216+
217+
_ASM_EXTABLE_FAULT(.Lseamcall\@, .Lseamcall_trap\@)
199218
.endif /* \host */
200219

201220
.endm

0 commit comments

Comments
 (0)