Convert TDG.VP.VMCALL<ReportFatalError> to KVM_EXIT_SYSTEM_EVENT with a new type KVM_SYSTEM_EVENT_TDX_FATAL and forward it to userspace for handling. TD guest can use TDG.VP.VMCALL<ReportFatalError> to report the fatal error it has experienced. This hypercall is special because TD guest is requesting a termination with the error information, KVM needs to forward the hypercall to userspace anyway, KVM doesn't do parsing or conversion, it just dumps the 16 general-purpose registers to userspace and let userspace decide what to do.
Unified · Split
| @@ -6823,6 +6823,7 @@ should put the acknowledged interrupt vector into the 'epr' field. · 6822 unmodified lines | |||
| 6823 | #define KVM_SYSTEM_EVENT_WAKEUP 4 | 6823 | #define KVM_SYSTEM_EVENT_WAKEUP 4 |
| 6824 | #define KVM_SYSTEM_EVENT_SUSPEND 5 | 6824 | #define KVM_SYSTEM_EVENT_SUSPEND 5 |
| 6825 | #define KVM_SYSTEM_EVENT_SEV_TERM 6 | 6825 | #define KVM_SYSTEM_EVENT_SEV_TERM 6 |
| 6826 | #define KVM_SYSTEM_EVENT_TDX_FATAL 7 | ||
| 6826 | __u32 type; | 6827 | __u32 type; |
| 6827 | __u32 ndata; | 6828 | __u32 ndata; |
| 6828 | __u64 data[16]; | 6829 | __u64 data[16]; |
| @@ -6849,6 +6850,11 @@ Valid values for 'type' are: · 20 unmodified lines | |||
| 6849 | reset/shutdown of the VM. | 6850 | reset/shutdown of the VM. |
| 6850 | - KVM_SYSTEM_EVENT_SEV_TERM -- an AMD SEV guest requested termination. | 6851 | - KVM_SYSTEM_EVENT_SEV_TERM -- an AMD SEV guest requested termination. |
| 6851 | The guest physical address of the guest's GHCB is stored in `data[0]`. | 6852 | The guest physical address of the guest's GHCB is stored in `data[0]`. |
| 6853 | - KVM_SYSTEM_EVENT_TDX_FATAL -- a TDX guest reported a fatal error state. | ||
| 6854 | KVM doesn't do any parsing or conversion, it just dumps 16 general-purpose | ||
| 6855 | registers to userspace, in ascending order of the 4-bit indices for x86-64 | ||
| 6856 | general-purpose registers in instruction encoding, as defined in the Intel | ||
| 6857 | SDM. | ||
| 6852 | - KVM_SYSTEM_EVENT_WAKEUP -- the exiting vCPU is in a suspended state and | 6858 | - KVM_SYSTEM_EVENT_WAKEUP -- the exiting vCPU is in a suspended state and |
| 6853 | KVM has recognized a wakeup event. Userspace may honor this event by | 6859 | KVM has recognized a wakeup event. Userspace may honor this event by |
| 6854 | marking the exiting vCPU as runnable, or deny it and call KVM_RUN again. | 6860 | marking the exiting vCPU as runnable, or deny it and call KVM_RUN again. |
| @@ -1104,11 +1104,39 @@ error: · 1103 unmodified lines | |||
| 1104 | return 1; | 1104 | return 1; |
| 1105 | } | 1105 | } |
| 1106 | 1106 | ||
| 1107 | static int tdx_report_fatal_error(struct kvm_vcpu *vcpu) | ||
| 1108 | { | ||
| 1109 | struct vcpu_tdx *tdx = to_tdx(vcpu); | ||
| 1110 | u64 *regs = vcpu->run->system_event.data; | ||
| 1111 | u64 *module_regs = &tdx->vp_enter_args.r8; | ||
| 1112 | int index = VCPU_REGS_RAX; | ||
| 1113 | |||
| 1114 | vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT; | ||
| 1115 | vcpu->run->system_event.type = KVM_SYSTEM_EVENT_TDX_FATAL; | ||
| 1116 | vcpu->run->system_event.ndata = 16; | ||
| 1117 | |||
| 1118 | /* Dump 16 general-purpose registers to userspace in ascending order. */ | ||
| 1119 | regs[index++] = tdx->vp_enter_ret; | ||
| 1120 | regs[index++] = tdx->vp_enter_args.rcx; | ||
| 1121 | regs[index++] = tdx->vp_enter_args.rdx; | ||
| 1122 | regs[index++] = tdx->vp_enter_args.rbx; | ||
| 1123 | regs[index++] = 0; | ||
| 1124 | regs[index++] = 0; | ||
| 1125 | regs[index++] = tdx->vp_enter_args.rsi; | ||
| 1126 | regs[index] = tdx->vp_enter_args.rdi; | ||
| 1127 | for (index = 0; index < 8; index++) | ||
| 1128 | regs[VCPU_REGS_R8 + index] = module_regs[index]; | ||
| 1129 | |||
| 1130 | return 0; | ||
| 1131 | } | ||
| 1132 | |||
| 1107 | static int handle_tdvmcall(struct kvm_vcpu *vcpu) | 1133 | static int handle_tdvmcall(struct kvm_vcpu *vcpu) |
| 1108 | { | 1134 | { |
| 1109 | switch (tdvmcall_leaf(vcpu)) { | 1135 | switch (tdvmcall_leaf(vcpu)) { |
| 1110 | case TDVMCALL_MAP_GPA: | 1136 | case TDVMCALL_MAP_GPA: |
| 1111 | return tdx_map_gpa(vcpu); | 1137 | return tdx_map_gpa(vcpu); |
| 1138 | case TDVMCALL_REPORT_FATAL_ERROR: | ||
| 1139 | return tdx_report_fatal_error(vcpu); | ||
| 1112 | default: | 1140 | default: |
| 1113 | break; | 1141 | break; |
| 1114 | } | 1142 | } |
| @@ -375,6 +375,7 @@ struct kvm_run { · 374 unmodified lines | |||
| 375 | #define KVM_SYSTEM_EVENT_WAKEUP 4 | 375 | #define KVM_SYSTEM_EVENT_WAKEUP 4 |
| 376 | #define KVM_SYSTEM_EVENT_SUSPEND 5 | 376 | #define KVM_SYSTEM_EVENT_SUSPEND 5 |
| 377 | #define KVM_SYSTEM_EVENT_SEV_TERM 6 | 377 | #define KVM_SYSTEM_EVENT_SEV_TERM 6 |
| 378 | #define KVM_SYSTEM_EVENT_TDX_FATAL 7 | ||
| 378 | __u32 type; | 379 | __u32 type; |
| 379 | __u32 ndata; | 380 | __u32 ndata; |
| 380 | union { | 381 | union { |