• Kai Huang's avatar
    x86/tdx: Make TDX_HYPERCALL asm similar to TDX_MODULE_CALL · c641cfb5
    Kai Huang authored
    Now the 'struct tdx_hypercall_args' and 'struct tdx_module_args' are
    almost the same, and the TDX_HYPERCALL and TDX_MODULE_CALL asm macro
    share similar code pattern too.  The __tdx_hypercall() and __tdcall()
    should be unified to use the same assembly code.
    
    As a preparation to unify them, simplify the TDX_HYPERCALL to make it
    more like the TDX_MODULE_CALL.
    
    The TDX_HYPERCALL takes the pointer of 'struct tdx_hypercall_args' as
    function call argument, and does below extra things comparing to the
    TDX_MODULE_CALL:
    
    1) It sets RAX to 0 (TDG.VP.VMCALL leaf) internally;
    2) It sets RCX to the (fixed) bitmap of shared registers internally;
    3) It calls __tdx_hypercall_failed() internally (and panics) when the
       TDCALL instruction itself fails;
    4) After TDCALL, it moves R10 to RAX to return the return code of the
       VMCALL leaf, regardless the '\ret' asm macro argument;
    
    Firstly, change the TDX_HYPERCALL to take the same function call
    arguments as the TDX_MODULE_CALL does: TDCALL leaf ID, and the pointer
    to 'struct tdx_module_args'.  Then 1) and 2) can be moved to the
    caller:
    
     - TDG.VP.VMCALL leaf ID can be passed via the function call argument;
     - 'struct tdx_module_args' is 'struct tdx_hypercall_args' + RCX, thus
       the bitmap of shared registers can be passed via RCX in the
       structure.
    
    Secondly, to move 3) and 4) out of assembly, make the TDX_HYPERCALL
    always save output registers to the structure.  The caller then can:
    
     - Call __tdx_hypercall_failed() when TDX_HYPERCALL returns error;
     - Return R10 in the structure as the return code of the VMCALL leaf;
    
    With above changes, change the asm function from __tdx_hypercall() to
    __tdcall_hypercall(), and reimplement __tdx_hypercall() as the C wrapper
    of it.  This avoids having to add another wrapper of __tdx_hypercall()
    (_tdx_hypercall() is already taken).
    
    The __tdcall_hypercall() will be replaced with a __tdcall() variant
    using TDX_MODULE_CALL in a later commit as the final goal is to have one
    assembly to handle both TDCALL and TDVMCALL.
    
    Currently, the __tdx_hypercall() asm is in '.noinstr.text'.  To keep
    this unchanged, annotate __tdx_hypercall(), which is a C function now,
    as 'noinstr'.
    
    Remove the __tdx_hypercall_ret() as __tdx_hypercall() already does so.
    
    Implement __tdx_hypercall() in tdx-shared.c so it can be shared with the
    compressed code.
    
    Opportunistically fix a checkpatch error complaining using space around
    parenthesis '(' and ')' while moving the bitmap of shared registers to
    <asm/shared/tdx.h>.
    
    [ dhansen: quash new calls of __tdx_hypercall_ret() that showed up ]
    Suggested-by: default avatarPeter Zijlstra <peterz@infradead.org>
    Signed-off-by: default avatarKai Huang <kai.huang@intel.com>
    Signed-off-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
    Reviewed-by: default avatarKirill A. Shutemov <kirill.shutemov@linux.intel.com>
    Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Link: https://lore.kernel.org/all/0cbf25e7aee3256288045023a31f65f0cef90af4.1692096753.git.kai.huang%40intel.com
    c641cfb5
asm-offsets.c 3.84 KB