diff options
author | Kai Huang <kai.huang@intel.com> | 2023-08-15 14:02:01 +0300 |
---|---|---|
committer | Dave Hansen <dave.hansen@linux.intel.com> | 2023-09-13 02:28:13 +0300 |
commit | c641cfb5c157b6c3062a824fd8ba190bf06fb952 (patch) | |
tree | a4730f5b5910366cfb34846045c97d7f242e9e2d /arch/x86/include/asm/shared | |
parent | 12f34ed8622aafd3bbd9d8aa4550dcb7016ea1e6 (diff) | |
download | linux-c641cfb5c157b6c3062a824fd8ba190bf06fb952.tar.xz |
x86/tdx: Make TDX_HYPERCALL asm similar to TDX_MODULE_CALL
Now the 'struct tdx_hypercall_args' and 'struct tdx_module_args' are
almost the same, and the TDX_HYPERCALL and TDX_MODULE_CALL asm macro
share similar code pattern too. The __tdx_hypercall() and __tdcall()
should be unified to use the same assembly code.
As a preparation to unify them, simplify the TDX_HYPERCALL to make it
more like the TDX_MODULE_CALL.
The TDX_HYPERCALL takes the pointer of 'struct tdx_hypercall_args' as
function call argument, and does below extra things comparing to the
TDX_MODULE_CALL:
1) It sets RAX to 0 (TDG.VP.VMCALL leaf) internally;
2) It sets RCX to the (fixed) bitmap of shared registers internally;
3) It calls __tdx_hypercall_failed() internally (and panics) when the
TDCALL instruction itself fails;
4) After TDCALL, it moves R10 to RAX to return the return code of the
VMCALL leaf, regardless the '\ret' asm macro argument;
Firstly, change the TDX_HYPERCALL to take the same function call
arguments as the TDX_MODULE_CALL does: TDCALL leaf ID, and the pointer
to 'struct tdx_module_args'. Then 1) and 2) can be moved to the
caller:
- TDG.VP.VMCALL leaf ID can be passed via the function call argument;
- 'struct tdx_module_args' is 'struct tdx_hypercall_args' + RCX, thus
the bitmap of shared registers can be passed via RCX in the
structure.
Secondly, to move 3) and 4) out of assembly, make the TDX_HYPERCALL
always save output registers to the structure. The caller then can:
- Call __tdx_hypercall_failed() when TDX_HYPERCALL returns error;
- Return R10 in the structure as the return code of the VMCALL leaf;
With above changes, change the asm function from __tdx_hypercall() to
__tdcall_hypercall(), and reimplement __tdx_hypercall() as the C wrapper
of it. This avoids having to add another wrapper of __tdx_hypercall()
(_tdx_hypercall() is already taken).
The __tdcall_hypercall() will be replaced with a __tdcall() variant
using TDX_MODULE_CALL in a later commit as the final goal is to have one
assembly to handle both TDCALL and TDVMCALL.
Currently, the __tdx_hypercall() asm is in '.noinstr.text'. To keep
this unchanged, annotate __tdx_hypercall(), which is a C function now,
as 'noinstr'.
Remove the __tdx_hypercall_ret() as __tdx_hypercall() already does so.
Implement __tdx_hypercall() in tdx-shared.c so it can be shared with the
compressed code.
Opportunistically fix a checkpatch error complaining using space around
parenthesis '(' and ')' while moving the bitmap of shared registers to
<asm/shared/tdx.h>.
[ dhansen: quash new calls of __tdx_hypercall_ret() that showed up ]
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/0cbf25e7aee3256288045023a31f65f0cef90af4.1692096753.git.kai.huang%40intel.com
Diffstat (limited to 'arch/x86/include/asm/shared')
-rw-r--r-- | arch/x86/include/asm/shared/tdx.h | 86 |
1 files changed, 57 insertions, 29 deletions
diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h index 669749a22d8c..85493c4813cf 100644 --- a/arch/x86/include/asm/shared/tdx.h +++ b/arch/x86/include/asm/shared/tdx.h @@ -11,6 +11,7 @@ #define TDX_IDENT "IntelTDX " /* TDX module Call Leaf IDs */ +#define TDG_VP_VMCALL 0 #define TDG_VP_INFO 1 #define TDG_VP_VEINFO_GET 3 #define TDG_MR_REPORT 4 @@ -26,9 +27,64 @@ #define TDVMCALL_STATUS_RETRY 1 +/* + * Bitmasks of exposed registers (with VMM). + */ +#define TDX_RDX BIT(2) +#define TDX_RBX BIT(3) +#define TDX_RSI BIT(6) +#define TDX_RDI BIT(7) +#define TDX_R8 BIT(8) +#define TDX_R9 BIT(9) +#define TDX_R10 BIT(10) +#define TDX_R11 BIT(11) +#define TDX_R12 BIT(12) +#define TDX_R13 BIT(13) +#define TDX_R14 BIT(14) +#define TDX_R15 BIT(15) + +/* + * These registers are clobbered to hold arguments for each + * TDVMCALL. They are safe to expose to the VMM. + * Each bit in this mask represents a register ID. Bit field + * details can be found in TDX GHCI specification, section + * titled "TDCALL [TDG.VP.VMCALL] leaf". + */ +#define TDVMCALL_EXPOSE_REGS_MASK \ + (TDX_RDX | TDX_RBX | TDX_RSI | TDX_RDI | TDX_R8 | TDX_R9 | \ + TDX_R10 | TDX_R11 | TDX_R12 | TDX_R13 | TDX_R14 | TDX_R15) + #ifndef __ASSEMBLY__ /* + * Used in __tdcall*() to gather the input/output registers' values of the + * TDCALL instruction when requesting services from the TDX module. This is a + * software only structure and not part of the TDX module/VMM ABI + */ +struct tdx_module_args { + /* callee-clobbered */ + u64 rcx; + u64 rdx; + u64 r8; + u64 r9; + /* extra callee-clobbered */ + u64 r10; + u64 r11; + /* callee-saved + rdi/rsi */ + u64 r12; + u64 r13; + u64 r14; + u64 r15; + u64 rbx; + u64 rdi; + u64 rsi; +}; + +/* Used to communicate with the TDX module */ +u64 __tdcall(u64 fn, struct tdx_module_args *args); +u64 __tdcall_ret(u64 fn, struct tdx_module_args *args); + +/* * Used in __tdx_hypercall() to pass down and get back registers' values of * the TDCALL instruction when requesting services from the VMM. * @@ -50,8 +106,8 @@ struct tdx_hypercall_args { }; /* Used to request services from the VMM */ +u64 __tdcall_hypercall(u64 fn, struct tdx_module_args *args); u64 __tdx_hypercall(struct tdx_hypercall_args *args); -u64 __tdx_hypercall_ret(struct tdx_hypercall_args *args); /* * Wrapper for standard use of __tdx_hypercall with no output aside from @@ -75,34 +131,6 @@ static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15) /* Called from __tdx_hypercall() for unrecoverable failure */ void __tdx_hypercall_failed(void); -/* - * Used in __tdcall*() to gather the input/output registers' values of the - * TDCALL instruction when requesting services from the TDX module. This is a - * software only structure and not part of the TDX module/VMM ABI - */ -struct tdx_module_args { - /* callee-clobbered */ - u64 rcx; - u64 rdx; - u64 r8; - u64 r9; - /* extra callee-clobbered */ - u64 r10; - u64 r11; - /* callee-saved + rdi/rsi */ - u64 r12; - u64 r13; - u64 r14; - u64 r15; - u64 rbx; - u64 rdi; - u64 rsi; -}; - -/* Used to communicate with the TDX module */ -u64 __tdcall(u64 fn, struct tdx_module_args *args); -u64 __tdcall_ret(u64 fn, struct tdx_module_args *args); - bool tdx_accept_memory(phys_addr_t start, phys_addr_t end); /* |