TD guest can use TDG.VP.VMCALL<REPORT_FATAL_ERROR> to request termination with error message encoded in GPRs. Parse and print the error message, and terminate the TD guest in the handler. Signed-off-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx> --- target/i386/kvm/tdx.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c index 96a10b0bb190..a42b5cea36c5 100644 --- a/target/i386/kvm/tdx.c +++ b/target/i386/kvm/tdx.c @@ -1003,6 +1003,7 @@ static void tdx_guest_class_init(ObjectClass *oc, void *data) #define TDG_VP_VMCALL_MAP_GPA 0x10001ULL #define TDG_VP_VMCALL_GET_QUOTE 0x10002ULL +#define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003ULL #define TDG_VP_VMCALL_SETUP_EVENT_NOTIFY_INTERRUPT 0x10004ULL #define TDG_VP_VMCALL_SUCCESS 0x0000000000000000ULL @@ -1478,6 +1479,42 @@ static void tdx_handle_get_quote(X86CPU *cpu, struct kvm_tdx_vmcall *vmcall) vmcall->status_code = TDG_VP_VMCALL_SUCCESS; } +static void tdx_handle_report_fatal_error(X86CPU *cpu, + struct kvm_tdx_vmcall *vmcall) +{ + uint64_t error_code = vmcall->in_r12; + char *message = NULL; + + if (error_code & 0xffff) { + error_report("invalid error code of TDG.VP.VMCALL<REPORT_FATAL_ERROR>\n"); + exit(1); + } + + /* it has optional message */ + if (vmcall->in_r14) { + uint64_t * tmp; + +#define GUEST_PANIC_INFO_TDX_MESSAGE_MAX 64 + message = g_malloc0(GUEST_PANIC_INFO_TDX_MESSAGE_MAX + 1); + + tmp = (uint64_t *)message; + /* The order is defined in TDX GHCI spec */ + *(tmp++) = cpu_to_le64(vmcall->in_r14); + *(tmp++) = cpu_to_le64(vmcall->in_r15); + *(tmp++) = cpu_to_le64(vmcall->in_rbx); + *(tmp++) = cpu_to_le64(vmcall->in_rdi); + *(tmp++) = cpu_to_le64(vmcall->in_rsi); + *(tmp++) = cpu_to_le64(vmcall->in_r8); + *(tmp++) = cpu_to_le64(vmcall->in_r9); + *(tmp++) = cpu_to_le64(vmcall->in_rdx); + message[GUEST_PANIC_INFO_TDX_MESSAGE_MAX] = '\0'; + assert((char *)tmp == message + GUEST_PANIC_INFO_TDX_MESSAGE_MAX); + } + + error_report("TD guest reports fatal error. %s\n", message ? : ""); + exit(1); +} + static void tdx_handle_setup_event_notify_interrupt(X86CPU *cpu, struct kvm_tdx_vmcall *vmcall) { @@ -1512,6 +1549,9 @@ static void tdx_handle_vmcall(X86CPU *cpu, struct kvm_tdx_vmcall *vmcall) case TDG_VP_VMCALL_GET_QUOTE: tdx_handle_get_quote(cpu, vmcall); break; + case TDG_VP_VMCALL_REPORT_FATAL_ERROR: + tdx_handle_report_fatal_error(cpu, vmcall); + break; case TDG_VP_VMCALL_SETUP_EVENT_NOTIFY_INTERRUPT: tdx_handle_setup_event_notify_interrupt(cpu, vmcall); break; -- 2.34.1