lkml.org 
[lkml]   [2022]   [Mar]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCHv5 09/30] x86/tdx: Add MSR support for TDX guests
    Date
    Use hypercall to emulate MSR read/write for the TDX platform.

    There are two viable approaches for doing MSRs in a TD guest:

    1. Execute the RDMSR/WRMSR instructions like most VMs and bare metal
    do. Some will succeed, others will cause a #VE. All of those that
    cause a #VE will be handled with a TDCALL.
    2. Use paravirt infrastructure. The paravirt hook has to keep a list
    of which MSRs would cause a #VE and use a TDCALL. All other MSRs
    execute RDMSR/WRMSR instructions directly.

    The second option can be ruled out because the list of MSRs was
    challenging to maintain. That leaves option #1 as the only viable
    solution for the minimal TDX support.

    For performance-critical MSR writes (like TSC_DEADLINE), future patches
    will replace the WRMSR/#VE sequence with the direct TDCALL.

    RDMSR and WRMSR specification details can be found in
    Guest-Host-Communication Interface (GHCI) for Intel Trust Domain
    Extensions (Intel TDX) specification, sec titled "TDG.VP.
    VMCALL<Instruction.RDMSR>" and "TDG.VP.VMCALL<Instruction.WRMSR>".

    Co-developed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
    Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
    Reviewed-by: Andi Kleen <ak@linux.intel.com>
    Reviewed-by: Tony Luck <tony.luck@intel.com>
    Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
    Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
    ---
    arch/x86/coco/tdx.c | 42 ++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 42 insertions(+)

    diff --git a/arch/x86/coco/tdx.c b/arch/x86/coco/tdx.c
    index 0c8214e1cdb5..f3c6767a42d2 100644
    --- a/arch/x86/coco/tdx.c
    +++ b/arch/x86/coco/tdx.c
    @@ -121,6 +121,44 @@ void __cpuidle tdx_safe_halt(void)
    WARN_ONCE(1, "HLT instruction emulation failed\n");
    }

    +static bool read_msr(struct pt_regs *regs)
    +{
    + struct tdx_hypercall_args args = {
    + .r10 = TDX_HYPERCALL_STANDARD,
    + .r11 = hcall_func(EXIT_REASON_MSR_READ),
    + .r12 = regs->cx,
    + };
    +
    + /*
    + * Emulate the MSR read via hypercall. More info about ABI
    + * can be found in TDX Guest-Host-Communication Interface
    + * (GHCI), section titled "TDG.VP.VMCALL<Instruction.RDMSR>".
    + */
    + if (__tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT))
    + return false;
    +
    + regs->ax = lower_32_bits(args.r11);
    + regs->dx = upper_32_bits(args.r11);
    + return true;
    +}
    +
    +static bool write_msr(struct pt_regs *regs)
    +{
    + struct tdx_hypercall_args args = {
    + .r10 = TDX_HYPERCALL_STANDARD,
    + .r11 = hcall_func(EXIT_REASON_MSR_WRITE),
    + .r12 = regs->cx,
    + .r13 = (u64)regs->dx << 32 | regs->ax,
    + };
    +
    + /*
    + * Emulate the MSR write via hypercall. More info about ABI
    + * can be found in TDX Guest-Host-Communication Interface
    + * (GHCI) section titled "TDG.VP.VMCALL<Instruction.WRMSR>".
    + */
    + return !__tdx_hypercall(&args, 0);
    +}
    +
    void tdx_get_ve_info(struct ve_info *ve)
    {
    struct tdx_module_output out;
    @@ -150,6 +188,10 @@ static bool virt_exception_kernel(struct pt_regs *regs, struct ve_info *ve)
    switch (ve->exit_reason) {
    case EXIT_REASON_HLT:
    return handle_halt();
    + case EXIT_REASON_MSR_READ:
    + return read_msr(regs);
    + case EXIT_REASON_MSR_WRITE:
    + return write_msr(regs);
    default:
    pr_warn("Unexpected #VE: %lld\n", ve->exit_reason);
    return false;
    --
    2.34.1
    \
     
     \ /
      Last update: 2022-03-02 15:29    [W:9.464 / U:0.196 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site