lkml.org 
[lkml]   [2022]   [Jun]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v7 063/102] 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>
    ---
    arch/x86/kvm/vmx/vmenter.S | 146 +++++++++++++++++++++++++++++++++++++
    1 file changed, 146 insertions(+)

    diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S
    index 435c187927c4..f58ea3c97ccf 100644
    --- a/arch/x86/kvm/vmx/vmenter.S
    +++ b/arch/x86/kvm/vmx/vmenter.S
    @@ -2,6 +2,7 @@
    #include <linux/linkage.h>
    #include <asm/asm.h>
    #include <asm/bitsperlong.h>
    +#include <asm/errno.h>
    #include <asm/kvm_vcpu_regs.h>
    #include <asm/nospec-branch.h>
    #include <asm/segment.h>
    @@ -28,6 +29,13 @@
    #define VCPU_R15 __VCPU_REGS_R15 * WORD_SIZE
    #endif

    +#ifdef CONFIG_INTEL_TDX_HOST
    +#define TDENTER 0
    +#define EXIT_REASON_TDCALL 77
    +#define TDENTER_ERROR_BIT 63
    +#define seamcall .byte 0x66,0x0f,0x01,0xcf
    +#endif
    +
    .section .noinstr.text, "ax"

    /**
    @@ -328,3 +336,141 @@ SYM_FUNC_START(vmx_do_interrupt_nmi_irqoff)
    pop %_ASM_BP
    RET
    SYM_FUNC_END(vmx_do_interrupt_nmi_irqoff)
    +
    +#ifdef CONFIG_INTEL_TDX_HOST
    +
    +.pushsection .noinstr.text, "ax"
    +
    +/**
    + * __tdx_vcpu_run - Call SEAMCALL(TDENTER) 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 TDENTER
    + *
    + * 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 TDENTER 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 1f
    +
    + /* Load @regs to RAX, which will be clobbered with $TDENTER 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 TDENTER to RAX. This kills the @regs pointer! */
    +1: mov $TDENTER, %rax
    +
    +2: seamcall
    +
    + /* Skip to the exit path if TDENTER failed. */
    + bt $TDENTER_ERROR_BIT, %rax
    + jc 4f
    +
    + /* Temporarily save the TD-Exit reason. */
    + push %rax
    +
    + /* check if TD-exit due to TDVMCALL */
    + cmp $EXIT_REASON_TDCALL, %ax
    +
    + /* Reload @regs to RAX. */
    + mov 8(%rsp), %rax
    +
    + /* Jump on non-TDVMCALL */
    + jne 3f
    +
    + /* Save all output from SEAMCALL(TDENTER) */
    + 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)
    +
    +3: 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.
    + */
    + xor %rbx, %rbx
    + xor %rcx, %rcx
    + xor %rdx, %rdx
    + xor %rsi, %rsi
    + xor %rdi, %rdi
    + xor %rbp, %rbp
    + xor %r8, %r8
    + xor %r9, %r9
    + xor %r10, %r10
    + xor %r11, %r11
    + xor %r12, %r12
    + xor %r13, %r13
    + xor %r14, %r14
    + xor %r15, %r15
    +
    + /* Restore the TD-Exit reason to RAX for return. */
    + pop %rax
    +
    + /* "POP" @regs. */
    +4: add $8, %rsp
    + pop %rbx
    + pop %r12
    + pop %r13
    + pop %r14
    + pop %r15
    +
    + pop %rbp
    + RET
    +
    +5: cmpb $0, kvm_rebooting
    + je 6f
    + mov $-EFAULT, %rax
    + jmp 4b
    +6: ud2
    + _ASM_EXTABLE(2b, 5b)
    +
    +SYM_FUNC_END(__tdx_vcpu_run)
    +
    +.popsection
    +
    +#endif
    --
    2.25.1
    \
     
     \ /
      Last update: 2022-06-28 00:00    [W:4.096 / U:0.408 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site