diff mbox series

[v2,03/21] x86/virt/tdx: Implement the SEAMCALL base function

Message ID 269a053607357eedd9a1e8ddf0e7240ae0c3985c.1647167475.git.kai.huang@intel.com (mailing list archive)
State New, archived
Headers show
Series TDX host kernel support | expand

Commit Message

Huang, Kai March 13, 2022, 10:49 a.m. UTC
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 the 'TDX module') runs in SEAM
VMX root to manage the crypto protected VMs running in SEAM VMX non-root.
SEAM VMX root is also used to host another CPU-attested software module
(called the 'P-SEAMLDR') to load and update the TDX module.

Host kernel transits to either the P-SEAMLDR or the TDX module via the
new SEAMCALL instruction.  SEAMCALLs are host-side interface functions
defined by the P-SEAMLDR and the 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,
they share 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, and it can fail with VMfailInvalid, for instance, when the SEAM
software module 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 | 52 ++++++++++++++++++++++++++++++++++++
 arch/x86/virt/vmx/tdx.h      | 11 ++++++++
 3 files changed, 64 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/virt/vmx/seamcall.S
 create mode 100644 arch/x86/virt/vmx/tdx.h

Comments

Tian, Kevin March 23, 2022, 3:35 a.m. UTC | #1
> From: Kai Huang <kai.huang@intel.com>
> Sent: Sunday, March 13, 2022 6:50 PM
> 
> 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.

s/isolate/are isolated/

> 
> A CPU-attested software module (called the 'TDX module') runs in SEAM
> VMX root to manage the crypto protected VMs running in SEAM VMX non-
> root.
> SEAM VMX root is also used to host another CPU-attested software module
> (called the 'P-SEAMLDR') to load and update the TDX module.
> 
> Host kernel transits to either the P-SEAMLDR or the TDX module via the
> new SEAMCALL instruction.  SEAMCALLs are host-side interface functions
> defined by the P-SEAMLDR and the TDX module around the new SEAMCALL
> instruction.  They are similar to a hypercall, except they are made by

"SEAMCALLs are ... functions ... around the new SEAMCALL instruction"

This is confusing. Probably just:

"SEAMCALL functions are defined and handled by the P-SEAMLDR and
the TDX module"

> host kernel to the SEAM software.
> 
> SEAMCALLs use an ABI different from the x86-64 system-v ABI.  Instead,
> they share 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, and it can fail with VMfailInvalid, for instance, when the SEAM
> software module 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.

SEAMCALL is TDX specific, is it? If yes, there is no need to have both
TDX and SEAMCALL in one macro, i.e. above can be SEAMCALL_VMFAILINVALID.

Thanks
Kevin
Huang, Kai March 28, 2022, 1:41 a.m. UTC | #2
On Wed, 2022-03-23 at 16:35 +1300, Tian, Kevin wrote:
> > From: Kai Huang <kai.huang@intel.com>
> > Sent: Sunday, March 13, 2022 6:50 PM
> > 
> > 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.
> 
> s/isolate/are isolated/

OK thanks.

> 
> > 
> > A CPU-attested software module (called the 'TDX module') runs in SEAM
> > VMX root to manage the crypto protected VMs running in SEAM VMX non-
> > root.
> > SEAM VMX root is also used to host another CPU-attested software module
> > (called the 'P-SEAMLDR') to load and update the TDX module.
> > 
> > Host kernel transits to either the P-SEAMLDR or the TDX module via the
> > new SEAMCALL instruction.  SEAMCALLs are host-side interface functions
> > defined by the P-SEAMLDR and the TDX module around the new SEAMCALL
> > instruction.  They are similar to a hypercall, except they are made by
> 
> "SEAMCALLs are ... functions ... around the new SEAMCALL instruction"
> 
> This is confusing. Probably just:

May I ask why is it confusing?

> 
> "SEAMCALL functions are defined and handled by the P-SEAMLDR and
> the TDX module"
> 
> > host kernel to the SEAM software.
> > 
> > SEAMCALLs use an ABI different from the x86-64 system-v ABI.  Instead,
> > they share 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, and it can fail with VMfailInvalid, for instance, when the SEAM
> > software module 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.
> 
> SEAMCALL is TDX specific, is it? If yes, there is no need to have both
> TDX and SEAMCALL in one macro, i.e. above can be SEAMCALL_VMFAILINVALID.

This is defined in TDX guest series.  I just use it.

https://lore.kernel.org/lkml/20220324152415.grt6xvhblmd4uccu@black.fi.intel.com/T/#md0b1aa563bd003ab625de159612a0d07e3ded7cb
Tian, Kevin March 28, 2022, 8:16 a.m. UTC | #3
> From: Huang, Kai <kai.huang@intel.com>
> Sent: Monday, March 28, 2022 9:42 AM
> 
> 
> >
> > >
> > > A CPU-attested software module (called the 'TDX module') runs in SEAM
> > > VMX root to manage the crypto protected VMs running in SEAM VMX
> non-
> > > root.
> > > SEAM VMX root is also used to host another CPU-attested software
> module
> > > (called the 'P-SEAMLDR') to load and update the TDX module.
> > >
> > > Host kernel transits to either the P-SEAMLDR or the TDX module via the
> > > new SEAMCALL instruction.  SEAMCALLs are host-side interface functions
> > > defined by the P-SEAMLDR and the TDX module around the new
> SEAMCALL
> > > instruction.  They are similar to a hypercall, except they are made by
> >
> > "SEAMCALLs are ... functions ... around the new SEAMCALL instruction"
> >
> > This is confusing. Probably just:
> 
> May I ask why is it confusing?

SEAMCALL is an instruction. One of its arguments carries the function
number.
Huang, Kai March 28, 2022, 9:10 a.m. UTC | #4
On Mon, 2022-03-28 at 21:16 +1300, Tian, Kevin wrote:
> > From: Huang, Kai <kai.huang@intel.com>
> > Sent: Monday, March 28, 2022 9:42 AM
> > 
> > 
> > > 
> > > > 
> > > > A CPU-attested software module (called the 'TDX module') runs in SEAM
> > > > VMX root to manage the crypto protected VMs running in SEAM VMX
> > non-
> > > > root.
> > > > SEAM VMX root is also used to host another CPU-attested software
> > module
> > > > (called the 'P-SEAMLDR') to load and update the TDX module.
> > > > 
> > > > Host kernel transits to either the P-SEAMLDR or the TDX module via the
> > > > new SEAMCALL instruction.  SEAMCALLs are host-side interface functions
> > > > defined by the P-SEAMLDR and the TDX module around the new
> > SEAMCALL
> > > > instruction.  They are similar to a hypercall, except they are made by
> > > 
> > > "SEAMCALLs are ... functions ... around the new SEAMCALL instruction"
> > > 
> > > This is confusing. Probably just:
> > 
> > May I ask why is it confusing?
> 
> SEAMCALL is an instruction. One of its arguments carries the function
> number.
> 

To confirm, are you saying the word "SEAMCALLs" is confusing, and we should use
"SEAMCALL leaf functions" instead?
diff mbox series

Patch

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..f31a717c00e0
--- /dev/null
+++ b/arch/x86/virt/vmx/seamcall.S
@@ -0,0 +1,52 @@ 
+/* 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 module
+ *		   (the P-SEAMLDR or the TDX module)
+ *
+ * Transform function call register arguments into the SEAMCALL register
+ * ABI.  Return TDX_SEAMCALL_VMFAILINVALID, or the completion status of
+ * the SEAMCALL.  Additional output operands are saved in @out (if it is
+ * provided by caller).
+ *
+ *-------------------------------------------------------------------------
+ * 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
+ *                       used by the P-SEAMLDR or 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