Since QEMU 10.1.0 commit id '6e250463b08b' guest crash information for TDX is available in the QEMU monitor, e.g.:
{ "timestamp": { "seconds": 1752118704, "microseconds": 27480 }, "event": "GUEST_PANICKED", "data": { "action": "pause", "info": { "error-code": 0, "message": "TD misconfiguration: SEPT #VE has to be disabled", "type": "tdx" } } } Let's log this information into the domain log file, e.g.: 2025-07-10 03:39:18.243+0000: panic tdx: error_code='0x0' message='TD misconfiguration: SEPT #VE has to be disabled' Suggested-by: Daniel P. Berrangé <berra...@redhat.com> Signed-off-by: Zhenzhong Duan <zhenzhong.d...@intel.com> --- src/qemu/qemu_monitor.c | 16 ++++++++++++++++ src/qemu/qemu_monitor.h | 11 +++++++++++ src/qemu/qemu_monitor_json.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 95c88fd5e8..b06949ab66 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3912,6 +3912,19 @@ qemuMonitorGuestPanicEventInfoFormatMsg(qemuMonitorEventPanicInfo *info) info->data.s390.psw_addr, info->data.s390.reason); break; + case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_TDX: + if (info->data.tdx.has_gpa) + ret = g_strdup_printf("tdx: error_code='0x%x' message='%s' " + "additional error information can be found " + "at gpa page: '0x%016llx'", + info->data.tdx.error_code, + info->data.tdx.message, + info->data.tdx.gpa); + else + ret = g_strdup_printf("tdx: error_code='0x%x' message='%s'", + info->data.tdx.error_code, + info->data.tdx.message); + break; case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_NONE: case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_LAST: break; @@ -3931,6 +3944,9 @@ qemuMonitorEventPanicInfoFree(qemuMonitorEventPanicInfo *info) case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_S390: g_free(info->data.s390.reason); break; + case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_TDX: + g_free(info->data.tdx.message); + break; case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_NONE: case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_HYPERV: case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_LAST: diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 6030c31598..98eabbb89f 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -38,6 +38,7 @@ typedef enum { QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_NONE = 0, QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_HYPERV, QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_S390, + QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_TDX, QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_LAST } qemuMonitorEventPanicInfoType; @@ -61,12 +62,22 @@ struct _qemuMonitorEventPanicInfoS390 { char *reason; }; +typedef struct _qemuMonitorEventPanicInfoTDX qemuMonitorEventPanicInfoTDX; +struct _qemuMonitorEventPanicInfoTDX { + /* TDX specific guest panic information */ + int error_code; + char *message; + bool has_gpa; + unsigned long long gpa; +}; + typedef struct _qemuMonitorEventPanicInfo qemuMonitorEventPanicInfo; struct _qemuMonitorEventPanicInfo { qemuMonitorEventPanicInfoType type; union { qemuMonitorEventPanicInfoHyperv hyperv; qemuMonitorEventPanicInfoS390 s390; + qemuMonitorEventPanicInfoTDX tdx; } data; }; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 5297ffb027..6c2051ebfb 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -621,6 +621,36 @@ qemuMonitorJSONGuestPanicExtractInfoS390(virJSONValue *data) return g_steal_pointer(&ret); } +static qemuMonitorEventPanicInfo * +qemuMonitorJSONGuestPanicExtractInfoTDX(virJSONValue *data) +{ + g_autoptr(qemuMonitorEventPanicInfo) ret = NULL; + int error_code; + unsigned long long gpa; + const char *message = NULL; + bool has_gpa; + + ret = g_new0(qemuMonitorEventPanicInfo, 1); + + ret->type = QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_TDX; + has_gpa = virJSONValueObjectHasKey(data, "gpa"); + + if (virJSONValueObjectGetNumberInt(data, "error-code", &error_code) < 0 || + !(message = virJSONValueObjectGetString(data, "message")) || + (has_gpa && virJSONValueObjectGetNumberUlong(data, "gpa", &gpa) < 0)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed TDX panic data")); + return NULL; + } + + ret->data.tdx.error_code = error_code; + ret->data.tdx.gpa = gpa; + ret->data.tdx.has_gpa = has_gpa; + + ret->data.tdx.message = g_strdup(message); + + return g_steal_pointer(&ret); +} + static qemuMonitorEventPanicInfo * qemuMonitorJSONGuestPanicExtractInfo(virJSONValue *data) { @@ -630,6 +660,8 @@ qemuMonitorJSONGuestPanicExtractInfo(virJSONValue *data) return qemuMonitorJSONGuestPanicExtractInfoHyperv(data); else if (STREQ_NULLABLE(type, "s390")) return qemuMonitorJSONGuestPanicExtractInfoS390(data); + else if (STREQ_NULLABLE(type, "tdx")) + return qemuMonitorJSONGuestPanicExtractInfoTDX(data); virReportError(VIR_ERR_INTERNAL_ERROR, _("unknown panic info type '%1$s'"), NULLSTR(type)); -- 2.47.1