]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: log the crash information for TDX
authorZhenzhong Duan <zhenzhong.duan@intel.com>
Thu, 10 Jul 2025 07:21:14 +0000 (03:21 -0400)
committerDaniel P. Berrangé <berrange@redhat.com>
Fri, 25 Jul 2025 10:36:08 +0000 (11:36 +0100)
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é <berrange@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c

index 95c88fd5e8fa933f1b1d5c065629f17f3786fa8c..b06949ab6634966b544cb47b6c36ab15d4fde805 100644 (file)
@@ -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:
index 6030c31598ca45f3db0db23b2f24ce7a52a70fb9..98eabbb89f689a303ddbbcced4bcbb53b0c679bc 100644 (file)
@@ -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;
 };
 
index 5297ffb0270581677a299ebb22470ed79d2652cc..6697b747b0f8b34c0ac6d4d527707d4cef05deea 100644 (file)
@@ -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 = 0;
+    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));