lkml.org 
[lkml]   [2023]   [Jul]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v15 062/115] KVM: TDX: Add helper assembly function to TDX vcpu
    Date
    From: Isaku Yamahata <isaku.yamahata@intel.com>

    TDX defines an API to run TDX vcpu with its own ABI. Define an assembly
    helper function to run TDX vcpu to hide the special ABI so that C code can
    call it with function call ABI.

    Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
    ---
    v14 -> v15:
    - use symbolic local label(.Lxxx) instead of numeric local label
    - optimized

    Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
    ---
    arch/x86/include/asm/tdx.h | 3 +-
    arch/x86/kvm/vmx/vmenter.S | 164 +++++++++++++++++++++++++++++++++++++
    2 files changed, 166 insertions(+), 1 deletion(-)

    diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
    index 97b23325ba5e..75711766159b 100644
    --- a/arch/x86/include/asm/tdx.h
    +++ b/arch/x86/include/asm/tdx.h
    @@ -18,7 +18,8 @@
    * Bits 47:40 == 0xFF indicate Reserved status code class that never used by
    * TDX module.
    */
    -#define TDX_ERROR _BITUL(63)
    +#define TDX_ERROR_BIT 63
    +#define TDX_ERROR _BITUL(TDX_ERROR_BIT)
    #define TDX_SW_ERROR (TDX_ERROR | GENMASK_ULL(47, 40))
    #define TDX_SEAMCALL_VMFAILINVALID (TDX_SW_ERROR | _UL(0xFFFF0000))

    diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S
    index 07e927d4d099..b4f1f6117968 100644
    --- a/arch/x86/kvm/vmx/vmenter.S
    +++ b/arch/x86/kvm/vmx/vmenter.S
    @@ -6,6 +6,7 @@
    #include <asm/nospec-branch.h>
    #include <asm/percpu.h>
    #include <asm/segment.h>
    +#include <asm/tdx.h>
    #include "kvm-asm-offsets.h"
    #include "run_flags.h"

    @@ -31,6 +32,12 @@
    #define VCPU_R15 __VCPU_REGS_R15 * WORD_SIZE
    #endif

    +#ifdef CONFIG_INTEL_TDX_HOST
    +#define TDH_VP_ENTER 0
    +#define EXIT_REASON_TDCALL 77
    +#define seamcall .byte 0x66,0x0f,0x01,0xcf
    +#endif
    +
    .macro VMX_DO_EVENT_IRQOFF call_insn call_target
    /*
    * Unconditionally create a stack frame, getting the correct RSP on the
    @@ -360,3 +367,160 @@ SYM_FUNC_END(vmread_error_trampoline)
    SYM_FUNC_START(vmx_do_interrupt_irqoff)
    VMX_DO_EVENT_IRQOFF CALL_NOSPEC _ASM_ARG1
    SYM_FUNC_END(vmx_do_interrupt_irqoff)
    +
    +#ifdef CONFIG_INTEL_TDX_HOST
    +
    +.pushsection .noinstr.text, "ax"
    +
    +/**
    + * __tdx_vcpu_run - Call SEAMCALL(TDH_VP_ENTER) to run a TD vcpu
    + * @tdvpr: physical address of TDVPR
    + * @regs: void * (to registers of TDVCPU)
    + * @gpr_mask: non-zero if guest registers need to be loaded prior to TDH_VP_ENTER
    + *
    + * Returns:
    + * TD-Exit Reason
    + *
    + * Note: KVM doesn't support using XMM in its hypercalls, it's the HyperV
    + * code's responsibility to save/restore XMM registers on TDVMCALL.
    + */
    +SYM_FUNC_START(__tdx_vcpu_run)
    + push %rbp
    + mov %rsp, %rbp
    +
    + push %r15
    + push %r14
    + push %r13
    + push %r12
    + push %rbx
    +
    + /* Save @regs, which is needed after TDH_VP_ENTER to capture output. */
    + push %rsi
    +
    + /* Load @tdvpr to RCX */
    + mov %rdi, %rcx
    +
    + /* No need to load guest GPRs if the last exit wasn't a TDVMCALL. */
    + test %dx, %dx
    + je .Lskip_copy_inputs
    +
    + /* Load @regs to RAX, which will be clobbered with $TDH_VP_ENTER anyways. */
    + mov %rsi, %rax
    +
    + mov VCPU_RBX(%rax), %rbx
    + mov VCPU_RDX(%rax), %rdx
    + mov VCPU_RBP(%rax), %rbp
    + mov VCPU_RSI(%rax), %rsi
    + mov VCPU_RDI(%rax), %rdi
    +
    + mov VCPU_R8 (%rax), %r8
    + mov VCPU_R9 (%rax), %r9
    + mov VCPU_R10(%rax), %r10
    + mov VCPU_R11(%rax), %r11
    + mov VCPU_R12(%rax), %r12
    + mov VCPU_R13(%rax), %r13
    + mov VCPU_R14(%rax), %r14
    + mov VCPU_R15(%rax), %r15
    +
    + /* Load TDH_VP_ENTER to RAX. This kills the @regs pointer! */
    +.Lskip_copy_inputs:
    + mov $TDH_VP_ENTER, %rax
    +
    +.Lseamcall:
    + seamcall
    +
    + jc .Lvmfail_invalid
    +
    + /* xor-swap (%rsp) and %rax */
    + xor (%rsp), %rax
    + xor %rax, (%rsp)
    + xor (%rsp), %rax
    +
    + /* Skip to the exit path if TDH_VP_ENTER failed. */
    + btq $TDX_ERROR_BIT, (%rsp)
    + jc .Lout_rax
    +
    + /* check if TD-exit due to TDVMCALL */
    + cmpq $EXIT_REASON_TDCALL, (%rsp)
    +
    + /* Jump on non-TDVMCALL */
    + jne .Lout_non_tdvmcall
    +
    + /* Save all output from SEAMCALL(TDH_VP_ENTER) */
    + mov %rbx, VCPU_RBX(%rax)
    + mov %rbp, VCPU_RBP(%rax)
    + mov %rsi, VCPU_RSI(%rax)
    + mov %rdi, VCPU_RDI(%rax)
    + mov %r10, VCPU_R10(%rax)
    + mov %r11, VCPU_R11(%rax)
    + mov %r12, VCPU_R12(%rax)
    + mov %r13, VCPU_R13(%rax)
    + mov %r14, VCPU_R14(%rax)
    + mov %r15, VCPU_R15(%rax)
    +
    +.Lout_non_tdvmcall:
    + mov %rcx, VCPU_RCX(%rax)
    + mov %rdx, VCPU_RDX(%rax)
    + mov %r8, VCPU_R8 (%rax)
    + mov %r9, VCPU_R9 (%rax)
    +
    + /*
    + * Clear all general purpose registers except RSP and RAX to prevent
    + * speculative use of the guest's values.
    + */
    + xorl %ebx, %ebx
    + xorl %ecx, %ecx
    + xorl %edx, %edx
    + xorl %esi, %esi
    + xorl %edi, %edi
    + xorl %ebp, %ebp
    + xorl %r8d, %r8d
    + xorl %r9d, %r9d
    + xorl %r10d, %r10d
    + xorl %r11d, %r11d
    + xorl %r12d, %r12d
    + xorl %r13d, %r13d
    + xorl %r14d, %r14d
    + xorl %r15d, %r15d
    +
    + /* Restore the TD-Exit reason to RAX for return. */
    +.Lout_rax:
    + pop %rax
    +
    + /* "POP" @regs. */
    +.Lout_regs:
    + pop %rbx
    + pop %r12
    + pop %r13
    + pop %r14
    + pop %r15
    +
    + pop %rbp
    + RET
    +
    +.Lvmfail_invalid:
    + /*
    + * Use same return value convention to tdxcall.S.
    + * TDX_SEAMCALL_VMFAILINVALID doesn't conflict with any TDX status code.
    + */
    + mov $TDX_SEAMCALL_VMFAILINVALID, %rax
    + /* discard pushed %rsi: %rsi is caller-saved. */
    + add $8, %rsp
    + jmp .Lout_regs
    +
    +.Lseamcall_faulted:
    + cmpb $0, kvm_rebooting
    + je 1f
    + mov $TDX_SW_ERROR, %r12
    + orq %r12, %rax
    + add $8, %rsp
    + jmp .Lout_regs
    +1: ud2
    + /* Use FAULT version to know what fault happened. */
    + _ASM_EXTABLE_FAULT(.Lseamcall, .Lseamcall_faulted)
    +
    +SYM_FUNC_END(__tdx_vcpu_run)
    +
    +.popsection
    +
    +#endif
    --
    2.25.1
    \
     
     \ /
      Last update: 2023-07-26 00:21    [W:4.028 / U:0.336 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site