lkml.org 
[lkml]   [2022]   [Mar]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    SubjectRe: [RFC PATCH v5 014/104] KVM: TDX: Add a function for KVM to invoke SEAMCALL
    From
    On 3/4/22 20:48, isaku.yamahata@intel.com wrote:
    > From: Isaku Yamahata <isaku.yamahata@intel.com>
    >
    > Add an assembly function for KVM to call the TDX module because __seamcall
    > defined in arch/x86/virt/vmx/seamcall.S doesn't fit for the KVM use case.
    >
    > TDX module API returns extended error information in registers, rcx, rdx,
    > r8, r9, r10, and r11 in addition to success case. KVM uses those extended
    > error information in addition to the status code returned in RAX. Update
    > the assembly code to optionally return those outputs even in the error case
    > and define the specific version for KVM to call the TDX module.
    >
    > SEAMCALL to the SEAM module (P-SEAMLDR or TDX module) can result in the
    > error of VmFailInvalid indicated by CF=1 when VMX isn't enabled by VMXON
    > instruction. Because KVM guarantees that VMX is enabled, VmFailInvalid
    > error won't happen. Don't check the error for KVM.
    >
    > Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
    > ---
    > arch/x86/kvm/Makefile | 2 +-
    > arch/x86/kvm/vmx/seamcall.S | 55 +++++++++++++++++++++++++++++++++++++
    > arch/x86/virt/tdxcall.S | 8 ++++--
    > 3 files changed, 62 insertions(+), 3 deletions(-)
    > create mode 100644 arch/x86/kvm/vmx/seamcall.S
    >
    > diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
    > index e2c05195cb95..e8f83a7d0dc3 100644
    > --- a/arch/x86/kvm/Makefile
    > +++ b/arch/x86/kvm/Makefile
    > @@ -24,7 +24,7 @@ kvm-$(CONFIG_KVM_XEN) += xen.o
    > kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \
    > vmx/evmcs.o vmx/nested.o vmx/posted_intr.o vmx/main.o
    > kvm-intel-$(CONFIG_X86_SGX_KVM) += vmx/sgx.o
    > -kvm-intel-$(CONFIG_INTEL_TDX_HOST) += vmx/tdx.o
    > +kvm-intel-$(CONFIG_INTEL_TDX_HOST) += vmx/tdx.o vmx/seamcall.o
    >
    > kvm-amd-y += svm/svm.o svm/vmenter.o svm/pmu.o svm/nested.o svm/avic.o svm/sev.o
    >
    > diff --git a/arch/x86/kvm/vmx/seamcall.S b/arch/x86/kvm/vmx/seamcall.S
    > new file mode 100644
    > index 000000000000..4a15017fc7dd
    > --- /dev/null
    > +++ b/arch/x86/kvm/vmx/seamcall.S
    > @@ -0,0 +1,55 @@
    > +/* SPDX-License-Identifier: GPL-2.0 */
    > +#include <linux/linkage.h>
    > +#include <asm/export.h>
    > +#include <asm/frame.h>
    > +
    > +#include "../../virt/tdxcall.S"
    > +
    > +/*
    > + * kvm_seamcall() - Host-side interface functions to SEAM software (TDX module)
    > + *
    > + * Transform function call register arguments into the SEAMCALL register
    > + * ABI. Return the completion status of the SEAMCALL. Additional output
    > + * operands are saved in @out (if it is provided by the user).
    > + * It doesn't check TDX_SEAMCALL_VMFAILINVALID unlike __semcall() because KVM
    > + * guarantees that VMX is enabled so that TDX_SEAMCALL_VMFAILINVALID doesn't
    > + * happen. In the case of error completion status code, extended error code may
    > + * be stored in leaf specific output registers.
    > + *
    > + *-------------------------------------------------------------------------
    > + * 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.
    > + *
    > + *-------------------------------------------------------------------------
    > + *
    > + * kvm_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
    > + */
    > +SYM_FUNC_START(kvm_seamcall)
    > + FRAME_BEGIN
    > + TDX_MODULE_CALL host=1 error_check=0
    > + FRAME_END
    > + ret
    > +SYM_FUNC_END(kvm_seamcall)
    > +EXPORT_SYMBOL_GPL(kvm_seamcall)
    > diff --git a/arch/x86/virt/tdxcall.S b/arch/x86/virt/tdxcall.S
    > index 90569faedacc..2e614b6b5f1e 100644
    > --- a/arch/x86/virt/tdxcall.S
    > +++ b/arch/x86/virt/tdxcall.S
    > @@ -13,7 +13,7 @@
    > #define tdcall .byte 0x66,0x0f,0x01,0xcc
    > #define seamcall .byte 0x66,0x0f,0x01,0xcf
    >
    > -.macro TDX_MODULE_CALL host:req
    > +.macro TDX_MODULE_CALL host:req error_check=1

    Perhaps name this argument ext_error_out and reverse it (that is, 0 is
    the current behavior while 1 is what KVM needs).

    Paolo

    > /*
    > * R12 will be used as temporary storage for struct tdx_module_output
    > * pointer. Since R12-R15 registers are not used by TDCALL/SEAMCALL
    > @@ -51,9 +51,11 @@
    > *
    > * Set %rax to TDX_SEAMCALL_VMFAILINVALID for VMfailInvalid.
    > * This value will never be used as actual SEAMCALL error code.
    > - */
    > + */
    > + .if \error_check
    > jnc .Lno_vmfailinvalid
    > mov $TDX_SEAMCALL_VMFAILINVALID, %rax
    > + .endif
    > .Lno_vmfailinvalid:
    > .else
    > tdcall
    > @@ -66,8 +68,10 @@
    > pop %r12
    >
    > /* Check for success: 0 - Successful, otherwise failed */
    > + .if \error_check
    > test %rax, %rax
    > jnz .Lno_output_struct
    > + .endif
    >
    > /*
    > * Since this function can be initiated without an output pointer,

    \
     
     \ /
      Last update: 2022-03-13 15:11    [W:4.046 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site