On Tue, Feb 11, 2025, Binbin Wu wrote: > +static int tdx_report_fatal_error(struct kvm_vcpu *vcpu) > +{ > + struct vcpu_tdx *tdx = to_tdx(vcpu); > + u64 reg_mask = tdx->vp_enter_args.rcx; > + u64 *opt_regs; > + > + /* > + * Skip sanity checks and let userspace decide what to do if sanity > + * checks fail. > + */ > + vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT; > + vcpu->run->system_event.type = KVM_SYSTEM_EVENT_TDX_FATAL; > + /* Error codes. */ > + vcpu->run->system_event.data[0] = tdx->vp_enter_args.r12; > + /* GPA of additional information page. */ > + vcpu->run->system_event.data[1] = tdx->vp_enter_args.r13; > + /* Information passed via registers (up to 64 bytes). */ > + opt_regs = &vcpu->run->system_event.data[2]; > + > +#define COPY_REG(REG, MASK) \ > + do { \ > + if (reg_mask & MASK) { \ Based on past experience with conditionally filling kvm_run fields, I think KVM should copy all registers and let userspace sort out the reg_mask. Unless the guest passes an ASCII byte stream exactly as the GHCI suggests, the information is quite useless because userspace doesn't have reg_mask and so can't know what's in data[4], data[5], etc... And I won't be the least bit surprised if guests deviate from the GHCI. > + *opt_regs = tdx->vp_enter_args.REG; \ > + opt_regs++; \ > + } \ > + } while (0) > + > + /* The order is defined in GHCI. */ Assuming I haven't missed something, to hell with the GCHI, just dump *all* registers, sorted by their index (ascending). Including RAX (TDCALL), RBP, and RSP.