2022-04-06 02:29:21 +03:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
#ifndef _ASM_X86_SHARED_TDX_H
|
|
|
|
#define _ASM_X86_SHARED_TDX_H
|
|
|
|
|
2022-04-06 02:29:25 +03:00
|
|
|
#include <linux/bits.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
|
|
#define TDX_HYPERCALL_STANDARD 0
|
|
|
|
|
2022-04-06 02:29:21 +03:00
|
|
|
#define TDX_CPUID_LEAF_ID 0x21
|
|
|
|
#define TDX_IDENT "IntelTDX "
|
|
|
|
|
2023-06-06 17:26:35 +03:00
|
|
|
/* TDX module Call Leaf IDs */
|
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
2023-08-15 23:02:01 +12:00
|
|
|
#define TDG_VP_VMCALL 0
|
2023-08-15 23:01:57 +12:00
|
|
|
#define TDG_VP_INFO 1
|
2025-05-06 17:57:09 -05:00
|
|
|
#define TDG_MR_RTMR_EXTEND 2
|
2023-08-15 23:01:57 +12:00
|
|
|
#define TDG_VP_VEINFO_GET 3
|
|
|
|
#define TDG_MR_REPORT 4
|
|
|
|
#define TDG_MEM_PAGE_ACCEPT 6
|
2024-11-04 12:38:00 +02:00
|
|
|
#define TDG_VM_RD 7
|
2023-08-15 23:01:57 +12:00
|
|
|
#define TDG_VM_WR 8
|
2023-06-06 17:26:35 +03:00
|
|
|
|
2024-12-02 09:24:58 +02:00
|
|
|
/* TDX attributes */
|
|
|
|
#define TDX_ATTR_DEBUG_BIT 0
|
|
|
|
#define TDX_ATTR_DEBUG BIT_ULL(TDX_ATTR_DEBUG_BIT)
|
|
|
|
#define TDX_ATTR_HGS_PLUS_PROF_BIT 4
|
|
|
|
#define TDX_ATTR_HGS_PLUS_PROF BIT_ULL(TDX_ATTR_HGS_PLUS_PROF_BIT)
|
|
|
|
#define TDX_ATTR_PERF_PROF_BIT 5
|
|
|
|
#define TDX_ATTR_PERF_PROF BIT_ULL(TDX_ATTR_PERF_PROF_BIT)
|
|
|
|
#define TDX_ATTR_PMT_PROF_BIT 6
|
|
|
|
#define TDX_ATTR_PMT_PROF BIT_ULL(TDX_ATTR_PMT_PROF_BIT)
|
|
|
|
#define TDX_ATTR_ICSSD_BIT 16
|
|
|
|
#define TDX_ATTR_ICSSD BIT_ULL(TDX_ATTR_ICSSD_BIT)
|
|
|
|
#define TDX_ATTR_LASS_BIT 27
|
|
|
|
#define TDX_ATTR_LASS BIT_ULL(TDX_ATTR_LASS_BIT)
|
|
|
|
#define TDX_ATTR_SEPT_VE_DISABLE_BIT 28
|
|
|
|
#define TDX_ATTR_SEPT_VE_DISABLE BIT_ULL(TDX_ATTR_SEPT_VE_DISABLE_BIT)
|
|
|
|
#define TDX_ATTR_MIGRTABLE_BIT 29
|
|
|
|
#define TDX_ATTR_MIGRTABLE BIT_ULL(TDX_ATTR_MIGRTABLE_BIT)
|
|
|
|
#define TDX_ATTR_PKS_BIT 30
|
|
|
|
#define TDX_ATTR_PKS BIT_ULL(TDX_ATTR_PKS_BIT)
|
|
|
|
#define TDX_ATTR_KL_BIT 31
|
|
|
|
#define TDX_ATTR_KL BIT_ULL(TDX_ATTR_KL_BIT)
|
|
|
|
#define TDX_ATTR_TPA_BIT 62
|
|
|
|
#define TDX_ATTR_TPA BIT_ULL(TDX_ATTR_TPA_BIT)
|
|
|
|
#define TDX_ATTR_PERFMON_BIT 63
|
|
|
|
#define TDX_ATTR_PERFMON BIT_ULL(TDX_ATTR_PERFMON_BIT)
|
|
|
|
|
2024-11-04 12:38:02 +02:00
|
|
|
/* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */
|
|
|
|
#define TDCS_CONFIG_FLAGS 0x1110000300000016
|
|
|
|
#define TDCS_TD_CTLS 0x1110000300000017
|
2023-06-06 17:26:35 +03:00
|
|
|
#define TDCS_NOTIFY_ENABLES 0x9100000000000010
|
2024-11-04 12:38:03 +02:00
|
|
|
#define TDCS_TOPOLOGY_ENUM_CONFIGURED 0x9100000000000019
|
2023-06-06 17:26:35 +03:00
|
|
|
|
2024-11-04 12:38:02 +02:00
|
|
|
/* TDCS_CONFIG_FLAGS bits */
|
|
|
|
#define TDCS_CONFIG_FLEXIBLE_PENDING_VE BIT_ULL(1)
|
|
|
|
|
|
|
|
/* TDCS_TD_CTLS bits */
|
2024-12-02 09:24:58 +02:00
|
|
|
#define TD_CTLS_PENDING_VE_DISABLE_BIT 0
|
|
|
|
#define TD_CTLS_PENDING_VE_DISABLE BIT_ULL(TD_CTLS_PENDING_VE_DISABLE_BIT)
|
|
|
|
#define TD_CTLS_ENUM_TOPOLOGY_BIT 1
|
|
|
|
#define TD_CTLS_ENUM_TOPOLOGY BIT_ULL(TD_CTLS_ENUM_TOPOLOGY_BIT)
|
|
|
|
#define TD_CTLS_VIRT_CPUID2_BIT 2
|
|
|
|
#define TD_CTLS_VIRT_CPUID2 BIT_ULL(TD_CTLS_VIRT_CPUID2_BIT)
|
|
|
|
#define TD_CTLS_REDUCE_VE_BIT 3
|
|
|
|
#define TD_CTLS_REDUCE_VE BIT_ULL(TD_CTLS_REDUCE_VE_BIT)
|
|
|
|
#define TD_CTLS_LOCK_BIT 63
|
|
|
|
#define TD_CTLS_LOCK BIT_ULL(TD_CTLS_LOCK_BIT)
|
2024-11-04 12:38:02 +02:00
|
|
|
|
2023-06-06 17:26:35 +03:00
|
|
|
/* TDX hypercall Leaf IDs */
|
2025-02-27 09:20:12 +08:00
|
|
|
#define TDVMCALL_GET_TD_VM_CALL_INFO 0x10000
|
2023-06-06 17:26:35 +03:00
|
|
|
#define TDVMCALL_MAP_GPA 0x10001
|
virt: tdx-guest: Add Quote generation support using TSM_REPORTS
In TDX guest, the attestation process is used to verify the TDX guest
trustworthiness to other entities before provisioning secrets to the
guest. The first step in the attestation process is TDREPORT
generation, which involves getting the guest measurement data in the
format of TDREPORT, which is further used to validate the authenticity
of the TDX guest. TDREPORT by design is integrity-protected and can
only be verified on the local machine.
To support remote verification of the TDREPORT in a SGX-based
attestation, the TDREPORT needs to be sent to the SGX Quoting Enclave
(QE) to convert it to a remotely verifiable Quote. SGX QE by design can
only run outside of the TDX guest (i.e. in a host process or in a
normal VM) and guest can use communication channels like vsock or
TCP/IP to send the TDREPORT to the QE. But for security concerns, the
TDX guest may not support these communication channels. To handle such
cases, TDX defines a GetQuote hypercall which can be used by the guest
to request the host VMM to communicate with the SGX QE. More details
about GetQuote hypercall can be found in TDX Guest-Host Communication
Interface (GHCI) for Intel TDX 1.0, section titled
"TDG.VP.VMCALL<GetQuote>".
Trusted Security Module (TSM) [1] exposes a common ABI for Confidential
Computing Guest platforms to get the measurement data via ConfigFS.
Extend the TSM framework and add support to allow an attestation agent
to get the TDX Quote data (included usage example below).
report=/sys/kernel/config/tsm/report/report0
mkdir $report
dd if=/dev/urandom bs=64 count=1 > $report/inblob
hexdump -C $report/outblob
rmdir $report
GetQuote TDVMCALL requires TD guest pass a 4K aligned shared buffer
with TDREPORT data as input, which is further used by the VMM to copy
the TD Quote result after successful Quote generation. To create the
shared buffer, allocate a large enough memory and mark it shared using
set_memory_decrypted() in tdx_guest_init(). This buffer will be re-used
for GetQuote requests in the TDX TSM handler.
Although this method reserves a fixed chunk of memory for GetQuote
requests, such one time allocation can help avoid memory fragmentation
related allocation failures later in the uptime of the guest.
Since the Quote generation process is not time-critical or frequently
used, the current version uses a polling model for Quote requests and
it also does not support parallel GetQuote requests.
Link: https://lore.kernel.org/lkml/169342399185.3934343.3035845348326944519.stgit@dwillia2-xfh.jf.intel.com/ [1]
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Reviewed-by: Erdem Aktas <erdemaktas@google.com>
Tested-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Tested-by: Peter Gonda <pgonda@google.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
2023-09-25 20:10:10 -07:00
|
|
|
#define TDVMCALL_GET_QUOTE 0x10002
|
2023-06-06 17:26:35 +03:00
|
|
|
#define TDVMCALL_REPORT_FATAL_ERROR 0x10003
|
2025-06-20 13:28:08 -04:00
|
|
|
#define TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT 0x10004ULL
|
2023-06-06 17:26:35 +03:00
|
|
|
|
2024-10-30 12:00:26 -07:00
|
|
|
/*
|
|
|
|
* TDG.VP.VMCALL Status Codes (returned in R10)
|
|
|
|
*/
|
|
|
|
#define TDVMCALL_STATUS_SUCCESS 0x0000000000000000ULL
|
|
|
|
#define TDVMCALL_STATUS_RETRY 0x0000000000000001ULL
|
|
|
|
#define TDVMCALL_STATUS_INVALID_OPERAND 0x8000000000000000ULL
|
2025-02-22 09:42:22 +08:00
|
|
|
#define TDVMCALL_STATUS_ALIGN_ERROR 0x8000000000000002ULL
|
2025-06-10 10:14:19 +08:00
|
|
|
#define TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED 0x8000000000000003ULL
|
2023-08-10 19:12:45 -07:00
|
|
|
|
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
2023-08-15 23:02:01 +12:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
|
2023-12-08 09:07:22 -08:00
|
|
|
/* TDX supported page sizes from the TDX module ABI. */
|
|
|
|
#define TDX_PS_4K 0
|
|
|
|
#define TDX_PS_2M 1
|
|
|
|
#define TDX_PS_1G 2
|
2023-12-08 09:07:28 -08:00
|
|
|
#define TDX_PS_NR (TDX_PS_1G + 1)
|
2023-12-08 09:07:22 -08:00
|
|
|
|
2025-03-19 11:30:57 +01:00
|
|
|
#ifndef __ASSEMBLER__
|
2022-04-06 02:29:25 +03:00
|
|
|
|
2023-09-18 16:18:58 +12:00
|
|
|
#include <linux/compiler_attributes.h>
|
|
|
|
|
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
2023-08-15 23:02:01 +12:00
|
|
|
/*
|
|
|
|
* 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);
|
2023-08-15 23:02:02 +12:00
|
|
|
u64 __tdcall_saved_ret(u64 fn, struct tdx_module_args *args);
|
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
2023-08-15 23:02:01 +12:00
|
|
|
|
2022-04-06 02:29:25 +03:00
|
|
|
/* Used to request services from the VMM */
|
2023-08-15 23:02:03 +12:00
|
|
|
u64 __tdx_hypercall(struct tdx_module_args *args);
|
2022-04-06 02:29:25 +03:00
|
|
|
|
2023-06-06 17:26:35 +03:00
|
|
|
/*
|
|
|
|
* Wrapper for standard use of __tdx_hypercall with no output aside from
|
|
|
|
* return code.
|
|
|
|
*/
|
|
|
|
static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15)
|
|
|
|
{
|
2023-08-15 23:02:03 +12:00
|
|
|
struct tdx_module_args args = {
|
2023-06-06 17:26:35 +03:00
|
|
|
.r10 = TDX_HYPERCALL_STANDARD,
|
|
|
|
.r11 = fn,
|
|
|
|
.r12 = r12,
|
|
|
|
.r13 = r13,
|
|
|
|
.r14 = r14,
|
|
|
|
.r15 = r15,
|
|
|
|
};
|
|
|
|
|
|
|
|
return __tdx_hypercall(&args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-04-06 02:29:25 +03:00
|
|
|
/* Called from __tdx_hypercall() for unrecoverable failure */
|
2023-09-18 16:18:58 +12:00
|
|
|
void __noreturn __tdx_hypercall_failed(void);
|
2022-04-06 02:29:25 +03:00
|
|
|
|
2023-06-06 17:26:37 +03:00
|
|
|
bool tdx_accept_memory(phys_addr_t start, phys_addr_t end);
|
|
|
|
|
2023-05-05 15:03:32 +03:00
|
|
|
/*
|
|
|
|
* The TDG.VP.VMCALL-Instruction-execution sub-functions are defined
|
|
|
|
* independently from but are currently matched 1:1 with VMX EXIT_REASONs.
|
|
|
|
* Reusing the KVM EXIT_REASON macros makes it easier to connect the host and
|
|
|
|
* guest sides of these calls.
|
|
|
|
*/
|
|
|
|
static __always_inline u64 hcall_func(u64 exit_reason)
|
|
|
|
{
|
|
|
|
return exit_reason;
|
|
|
|
}
|
|
|
|
|
2025-03-19 11:30:57 +01:00
|
|
|
#endif /* !__ASSEMBLER__ */
|
2022-04-06 02:29:21 +03:00
|
|
|
#endif /* _ASM_X86_SHARED_TDX_H */
|