[PATCH v10 09/11] x86/tdx: Add MSR support for TDX guest
From: Kuppuswamy Sathyanarayanan
<sathyanarayanan.kuppuswamy@linux.intel.com>
Date: 2021-10-09 05:38:27
Subsystem:
the rest, x86 architecture (32-bit and 64-bit) · Maintainers:
Linus Torvalds, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen
From: "Kirill A. Shutemov" <redacted> Use hypercall to emulate MSR read/write for TDX platform. TDVMCALL[Instruction.RDMSR] and TDVMCALL[Instruction.WRMSR] provide MSR oprations. 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>". Signed-off-by: Kirill A. Shutemov <redacted> Reviewed-by: Andi Kleen <redacted> Reviewed-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> --- Changes since v9: * None Changes since v8: * Changed tdx_read_msr_safe() return type to bool. * Changed tdx_write_msr_safe() return type to bool. * Changed second argument of tdx_read_msr_safe() from err to val. * Fixed compliation error due to use of tdx_is_context_switched_msr(). Changes since v7: * Removed tdx_is_context_switched_msr() support (since the list is incomplete). * Added section title to spec reference. Changes since v6: * None Changes since v5: * Renamed "tdg" prefix with "tdx". * Added comments for _tdx_hypercall() usage in MSR read/write functions. Change since v4: * Removed You usage from commit log. Changes since v3: * None arch/x86/kernel/tdx.c | 51 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/tdx.c b/arch/x86/kernel/tdx.c
index c05e8824e5e0..7c6c84015302 100644
--- a/arch/x86/kernel/tdx.c
+++ b/arch/x86/kernel/tdx.c@@ -110,6 +110,39 @@ static __cpuidle void tdx_safe_halt(void) _tdx_halt(irq_disabled, do_sti); } +static bool tdx_read_msr_safe(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_safe(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;
@@ -141,19 +174,33 @@ bool tdx_get_ve_info(struct ve_info *ve) bool tdx_handle_virtualization_exception(struct pt_regs *regs, struct ve_info *ve) { + bool ret = true; + u64 val; + switch (ve->exit_reason) { case EXIT_REASON_HLT: tdx_halt(); break; + case EXIT_REASON_MSR_READ: + ret = tdx_read_msr_safe(regs->cx, &val); + if (ret) { + regs->ax = (u32)val; + regs->dx = val >> 32; + } + break; + case EXIT_REASON_MSR_WRITE: + ret = tdx_write_msr_safe(regs->cx, regs->ax, regs->dx); + break; default: pr_warn("Unexpected #VE: %lld\n", ve->exit_reason); return false; } /* After successful #VE handling, move the IP */ - regs->ip += ve->instr_len; + if (ret) + regs->ip += ve->instr_len; - return true; + return ret; } void __init tdx_early_init(void)
--
2.25.1