lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCHv2 06/29] 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>
    ---
    arch/x86/kernel/tdx.c | 44 +++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 44 insertions(+)

    diff --git a/arch/x86/kernel/tdx.c b/arch/x86/kernel/tdx.c
    index eeb456631a65..29a03a4bdb53 100644
    --- a/arch/x86/kernel/tdx.c
    +++ b/arch/x86/kernel/tdx.c
    @@ -91,6 +91,39 @@ void __cpuidle tdx_safe_halt(void)
    WARN_ONCE(1, "HLT instruction emulation failed\n");
    }

    +static bool tdx_read_msr(unsigned int msr, u64 *val)
    +{
    + struct tdx_hypercall_output out;
    +
    + /*
    + * Emulate the MSR read via hypercall. More info about ABI
    + * can be found in TDX Guest-Host-Communication Interface
    + * (GHCI), sec titled "TDG.VP.VMCALL<Instruction.RDMSR>".
    + */
    + if (_tdx_hypercall(EXIT_REASON_MSR_READ, msr, 0, 0, 0, &out))
    + return false;
    +
    + *val = out.r11;
    +
    + return true;
    +}
    +
    +static bool tdx_write_msr(unsigned int msr, unsigned int low,
    + unsigned int high)
    +{
    + u64 ret;
    +
    + /*
    + * Emulate the MSR write via hypercall. More info about ABI
    + * can be found in TDX Guest-Host-Communication Interface
    + * (GHCI) sec titled "TDG.VP.VMCALL<Instruction.WRMSR>".
    + */
    + ret = _tdx_hypercall(EXIT_REASON_MSR_WRITE, msr, (u64)high << 32 | low,
    + 0, 0, NULL);
    +
    + return ret ? false : true;
    +}
    +
    bool tdx_get_ve_info(struct ve_info *ve)
    {
    struct tdx_module_output out;
    @@ -132,11 +165,22 @@ static bool tdx_virt_exception_user(struct pt_regs *regs, struct ve_info *ve)
    static bool tdx_virt_exception_kernel(struct pt_regs *regs, struct ve_info *ve)
    {
    bool ret = false;
    + u64 val;

    switch (ve->exit_reason) {
    case EXIT_REASON_HLT:
    ret = tdx_halt();
    break;
    + case EXIT_REASON_MSR_READ:
    + ret = tdx_read_msr(regs->cx, &val);
    + if (ret) {
    + regs->ax = lower_32_bits(val);
    + regs->dx = upper_32_bits(val);
    + }
    + break;
    + case EXIT_REASON_MSR_WRITE:
    + ret = tdx_write_msr(regs->cx, regs->ax, regs->dx);
    + break;
    default:
    pr_warn("Unexpected #VE: %lld\n", ve->exit_reason);
    break;
    --
    2.34.1
    \
     
     \ /
      Last update: 2022-01-24 16:03    [W:4.038 / U:0.308 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site