lkml.org 
[lkml]   [2022]   [Apr]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 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 are isolated 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. SEAMCALL leaf functions 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.

    SEAMCALL leaf functions use an ABI different from the x86-64 system-v
    ABI. Instead, they share the same ABI with the TDCALL leaf functions.
    %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 functions.

    Implement a C function __seamcall() to do SEAMCALL leaf functions using
    the assembly macro used by __tdx_module_call() (the implementation of
    TDCALL leaf functions). 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/tdx/Makefile | 2 +-
    arch/x86/virt/vmx/tdx/seamcall.S | 52 ++++++++++++++++++++++++++++++++
    arch/x86/virt/vmx/tdx/tdx.h | 11 +++++++
    3 files changed, 64 insertions(+), 1 deletion(-)
    create mode 100644 arch/x86/virt/vmx/tdx/seamcall.S
    create mode 100644 arch/x86/virt/vmx/tdx/tdx.h

    diff --git a/arch/x86/virt/vmx/tdx/Makefile b/arch/x86/virt/vmx/tdx/Makefile
    index 1bd688684716..fd577619620e 100644
    --- a/arch/x86/virt/vmx/tdx/Makefile
    +++ b/arch/x86/virt/vmx/tdx/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/tdx/seamcall.S b/arch/x86/virt/vmx/tdx/seamcall.S
    new file mode 100644
    index 000000000000..327961b2dd5a
    --- /dev/null
    +++ b/arch/x86/virt/vmx/tdx/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/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
    new file mode 100644
    index 000000000000..9d5b6f554c20
    --- /dev/null
    +++ b/arch/x86/virt/vmx/tdx/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.35.1
    \
     
     \ /
      Last update: 2022-04-06 18:09    [W:8.216 / U:0.952 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site