lkml.org 
[lkml]   [2022]   [Feb]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC PATCH 03/21] x86/virt/tdx: Implement the SEAMCALL base function
Date
Secure Arbitration Mode (SEAM) is an extension of VMX architecture.  It
defines a new VMX root operation (SEAM VMX root) and a new VMX non-root
operation (SEAM VMX non-root) which isolate from legacy VMX root and VMX
non-root mode.

A CPU-attested software module (called 'TDX module') runs in SEAM VMX
root to manage the protected VMs running in SEAM VMX non-root. SEAM VMX
root is also used to host another CPU-attested software module (called
'P-SEAMLDR') to load and update the TDX module.

Host kernel transits to either P-SEAMLDR or TDX module via the new
SEAMCALL instruction. SEAMCALLs are host-side interface functions
defined by P-SEAMLDR and TDX module around the new SEAMCALL instruction.
They are similar to a hypercall, except they are made by host kernel to
the SEAM software.

SEAMCALLs use an ABI different from the x86-64 system-v ABI. Instead,
it shares the same ABI with the TDCALL. %rax is used to carry both the
SEAMCALL leaf function number (input) and the completion status code
(output). Additional GPRs (%rcx, %rdx, %r8->%r11) may be further used
as both input and output operands in individual leaf SEAMCALLs.

Implement a C function __seamcall() to do SEAMCALL using the assembly
macro used by __tdx_module_call() (the implementation of TDCALL). The
only exception not covered here is TDENTER leaf function which takes
all GPRs and XMM0-XMM15 as both input and output. The caller of TDENTER
should implement its own logic to call TDENTER directly instead of using
this function.

SEAMCALL instruction is essentially a VMExit from VMX root to SEAM VMX
root. It fails with VMfailInvalid when the SEAM software is not loaded.
The C function __seamcall() returns TDX_SEAMCALL_VMFAILINVALID, which
doesn't conflict with any actual error code of SEAMCALLs, to uniquely
represent this case.

Signed-off-by: Kai Huang <kai.huang@intel.com>
---
arch/x86/virt/vmx/Makefile | 2 +-
arch/x86/virt/vmx/seamcall.S | 53 ++++++++++++++++++++++++++++++++++++
arch/x86/virt/vmx/tdx.h | 11 ++++++++
3 files changed, 65 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/virt/vmx/seamcall.S
create mode 100644 arch/x86/virt/vmx/tdx.h

diff --git a/arch/x86/virt/vmx/Makefile b/arch/x86/virt/vmx/Makefile
index 1bd688684716..fd577619620e 100644
--- a/arch/x86/virt/vmx/Makefile
+++ b/arch/x86/virt/vmx/Makefile
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_INTEL_TDX_HOST) += tdx.o
+obj-$(CONFIG_INTEL_TDX_HOST) += tdx.o seamcall.o
diff --git a/arch/x86/virt/vmx/seamcall.S b/arch/x86/virt/vmx/seamcall.S
new file mode 100644
index 000000000000..65edec23b5f4
--- /dev/null
+++ b/arch/x86/virt/vmx/seamcall.S
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/linkage.h>
+#include <asm/frame.h>
+
+#include "../tdxcall.S"
+
+/*
+ * __seamcall() - Host-side interface functions to SEAM software
+ * (P-SEAMLDR or TDX module)
+ *
+ * Transform function call register arguments into the SEAMCALL register
+ * ABI. Return TDX_SEAMCALL_VMFAILINVALID (when SEAM software is not
+ * loaded or SEAMCALLs are made into P-SEAMLDR concurrently), or the
+ * completion status of the SEAMCALL. Additional output operands are
+ * saved in @out (if it is provided by the user).
+ *
+ *-------------------------------------------------------------------------
+ * SEAMCALL ABI:
+ *-------------------------------------------------------------------------
+ * Input Registers:
+ *
+ * RAX - SEAMCALL Leaf number.
+ * RCX,RDX,R8-R9 - SEAMCALL Leaf specific input registers.
+ *
+ * Output Registers:
+ *
+ * RAX - SEAMCALL completion status code.
+ * RCX,RDX,R8-R11 - SEAMCALL Leaf specific output registers.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * __seamcall() function ABI:
+ *
+ * @fn (RDI) - SEAMCALL Leaf number, moved to RAX
+ * @rcx (RSI) - Input parameter 1, moved to RCX
+ * @rdx (RDX) - Input parameter 2, moved to RDX
+ * @r8 (RCX) - Input parameter 3, moved to R8
+ * @r9 (R8) - Input parameter 4, moved to R9
+ *
+ * @out (R9) - struct tdx_module_output pointer
+ * stored temporarily in R12 (not
+ * shared with the TDX module). It
+ * can be NULL.
+ *
+ * Return (via RAX) the completion status of the SEAMCALL, or
+ * TDX_SEAMCALL_VMFAILINVALID.
+ */
+SYM_FUNC_START(__seamcall)
+ FRAME_BEGIN
+ TDX_MODULE_CALL host=1
+ FRAME_END
+ ret
+SYM_FUNC_END(__seamcall)
diff --git a/arch/x86/virt/vmx/tdx.h b/arch/x86/virt/vmx/tdx.h
new file mode 100644
index 000000000000..9d5b6f554c20
--- /dev/null
+++ b/arch/x86/virt/vmx/tdx.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _X86_VIRT_TDX_H
+#define _X86_VIRT_TDX_H
+
+#include <linux/types.h>
+
+struct tdx_module_output;
+u64 __seamcall(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
+ struct tdx_module_output *out);
+
+#endif
--
2.33.1
\
 
 \ /
  Last update: 2022-02-28 03:14    [W:0.129 / U:0.064 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site