diff mbox series

[v6,29/60] i386/tdx: Handle KVM_SYSTEM_EVENT_TDX_FATAL

Message ID 20241105062408.3533704-30-xiaoyao.li@intel.com (mailing list archive)
State New
Headers show
Series QEMU TDX support | expand

Commit Message

Xiaoyao Li Nov. 5, 2024, 6:23 a.m. UTC
TD guest can use TDG.VP.VMCALL<REPORT_FATAL_ERROR> to request
termination. KVM translates such request into KVM_EXIT_SYSTEM_EVENT with
type of KVM_SYSTEM_EVENT_TDX_FATAL.

Add hanlder for such exit. Parse and print the error message, and
terminate the TD guest in the handler.

Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
---
Changes in v6:
 - replace the patch " i386/tdx: Handle TDG.VP.VMCALL<REPORT_FATAL_ERROR>"
   in v5;
---
 target/i386/kvm/kvm.c      | 10 ++++++++++
 target/i386/kvm/tdx-stub.c |  5 +++++
 target/i386/kvm/tdx.c      | 24 ++++++++++++++++++++++++
 target/i386/kvm/tdx.h      |  2 ++
 4 files changed, 41 insertions(+)

Comments

Edgecombe, Rick P Nov. 5, 2024, 8:55 p.m. UTC | #1
+Binbin

On Tue, 2024-11-05 at 01:23 -0500, Xiaoyao Li wrote:
> TD guest can use TDG.VP.VMCALL<REPORT_FATAL_ERROR> to request
> termination. KVM translates such request into KVM_EXIT_SYSTEM_EVENT with
> type of KVM_SYSTEM_EVENT_TDX_FATAL.
> 
> Add hanlder for such exit. Parse and print the error message, and
> terminate the TD guest in the handler.
> 
> Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
> ---

Binbin was looking at re-arranging the TDX dev branch to try to move these
patches earlier in the series so we could get them finalized for the purpose of
fully settling the uAPI for QEMU.

I wonder if we should just post a very small series with the KVM implementations
for MapGPA and ReportFatalError and we could try to get some stability
established. Maybe that would be enough?

Paolo, any thoughts on the merits of trying to get to that part earlier?
Edgecombe, Rick P Nov. 6, 2024, 2:28 p.m. UTC | #2
On Tue, 2024-11-05 at 12:55 -0800, Rick Edgecombe wrote:
> Binbin was looking at re-arranging the TDX dev branch to try to move these
> patches earlier in the series so we could get them finalized for the purpose of
> fully settling the uAPI for QEMU.
> 
> I wonder if we should just post a very small series with the KVM implementations
> for MapGPA and ReportFatalError and we could try to get some stability
> established. Maybe that would be enough?
> 
> Paolo, any thoughts on the merits of trying to get to that part earlier?

Circling back after some discussion on the PUCK call. We don't need to rush them
out urgently. We can post them after the TD vcpu enter/exit series.
diff mbox series

Patch

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 4fafc003e9a7..dea0f83370d5 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -6116,6 +6116,16 @@  int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
     case KVM_EXIT_HYPERCALL:
         ret = kvm_handle_hypercall(run);
         break;
+    case KVM_EXIT_SYSTEM_EVENT:
+        switch (run->system_event.type) {
+        case KVM_SYSTEM_EVENT_TDX_FATAL:
+            ret = tdx_handle_report_fatal_error(cpu, run);
+            break;
+        default:
+            ret = -1;
+            break;
+        }
+        break;
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
         ret = -1;
diff --git a/target/i386/kvm/tdx-stub.c b/target/i386/kvm/tdx-stub.c
index a064d583d393..b5cb6d56c46a 100644
--- a/target/i386/kvm/tdx-stub.c
+++ b/target/i386/kvm/tdx-stub.c
@@ -11,3 +11,8 @@  int tdx_parse_tdvf(void *flash_ptr, int size)
 {
     return -EINVAL;
 }
+
+int tdx_handle_report_fatal_error(X86CPU *cpu, struct kvm_run *run)
+{
+    return -EINVAL;
+}
diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c
index b34707e93f4d..3f44dfbf6585 100644
--- a/target/i386/kvm/tdx.c
+++ b/target/i386/kvm/tdx.c
@@ -574,6 +574,30 @@  int tdx_parse_tdvf(void *flash_ptr, int size)
     return tdvf_parse_metadata(&tdx_guest->tdvf, flash_ptr, size);
 }
 
+int tdx_handle_report_fatal_error(X86CPU *cpu, struct kvm_run *run)
+{
+    uint64_t error_code = run->system_event.data[0];
+    char *message = NULL;
+
+    if (error_code & 0xffff) {
+        error_report("TDX: REPORT_FATAL_ERROR: invalid error code: 0x%lx",
+                     error_code);
+        return -1;
+    }
+
+    /* It has optional message */
+    if (run->system_event.data[2]) {
+#define TDX_FATAL_MESSAGE_MAX        64
+        message = g_malloc0(TDX_FATAL_MESSAGE_MAX + 1);
+
+        memcpy(message, &run->system_event.data[2], TDX_FATAL_MESSAGE_MAX);
+        message[TDX_FATAL_MESSAGE_MAX] = '\0';
+    }
+
+    error_report("TD guest reports fatal error. %s", message ? : "");
+    return -1;
+}
+
 static bool tdx_guest_get_sept_ve_disable(Object *obj, Error **errp)
 {
     TdxGuest *tdx = TDX_GUEST(obj);
diff --git a/target/i386/kvm/tdx.h b/target/i386/kvm/tdx.h
index c669e0d0daca..7222a5d31359 100644
--- a/target/i386/kvm/tdx.h
+++ b/target/i386/kvm/tdx.h
@@ -6,6 +6,7 @@ 
 #endif
 
 #include "confidential-guest.h"
+#include "cpu.h"
 #include "hw/i386/tdvf.h"
 
 #define TYPE_TDX_GUEST "tdx-guest"
@@ -57,5 +58,6 @@  bool is_tdx_vm(void);
 int tdx_pre_create_vcpu(CPUState *cpu, Error **errp);
 void tdx_set_tdvf_region(MemoryRegion *tdvf_mr);
 int tdx_parse_tdvf(void *flash_ptr, int size);
+int tdx_handle_report_fatal_error(X86CPU *cpu, struct kvm_run *run);
 
 #endif /* QEMU_I386_TDX_H */