From: Hans-Jörg Höxer Subject: Re: SEV-ES: vmm(4): Handle IOIO gexit To: Date: Wed, 21 May 2025 12:33:15 +0200 Hi, updated diff addressing name tweak svm_gexit_sync_guest() to svm_vmgexit_sync_guest() (last diff chunk). Otherwise no change. Take care, HJ. ---------------------------------------------------------------------- commit a2d66c5c2c3a1c9339c5c583cda088d64513f20c Author: Hans-Joerg Hoexer Date: Wed Jan 22 14:38:33 2025 +0100 vmm(4): Handle IOIO gexit Fill in the actual handler for IOIO related GEXIT: The actual in/out instruction is encoded in the exitinfo provided by the guest in the GHCB. For in vmm(4) returns the result in the A GPR. The actual emulation is done by svm_handle_inout() and vmd(8). On the way back into the guest, vmm(4) synchronizes the computed result back to the GHCB. diff --git a/sys/arch/amd64/amd64/vmm_machdep.c b/sys/arch/amd64/amd64/vmm_machdep.c index a8cc195c78f..76cdaf4f74e 100644 --- a/sys/arch/amd64/amd64/vmm_machdep.c +++ b/sys/arch/amd64/amd64/vmm_machdep.c @@ -4359,6 +4359,14 @@ svm_vmgexit_sync_host(struct vcpu *vcpu) ghcb_valbm_set(expected_bm, GHCB_RCX); } break; + case SVM_VMEXIT_IOIO: + if (ghcb->v_sw_exitinfo1 & 0x1) { + /* in instruction, no registers used */ + } else { + /* out instruction */ + ghcb_valbm_set(expected_bm, GHCB_RAX); + } + break; default: return (EINVAL); } @@ -4424,6 +4432,14 @@ svm_vmgexit_sync_guest(struct vcpu *vcpu) ghcb_valbm_set(valid_bm, GHCB_RDX); } break; + case SVM_VMEXIT_IOIO: + if (svm_sw_exitinfo1 & 0x1) { + /* IN */ + ghcb_valbm_set(valid_bm, GHCB_RAX); + } else { + /* OUT -- nothing to return */ + } + break; default: return (EINVAL); } @@ -4489,6 +4505,10 @@ svm_handle_vmgexit(struct vcpu *vcpu) vcpu->vc_gueststate.vg_rax = vmcb->v_rax; syncout = 1; break; + case SVM_VMEXIT_IOIO: + if (svm_handle_inout(vcpu) == 0) + error = EAGAIN; + break; case SVM_VMEXIT_MSR: error = svm_handle_msr(vcpu); vmcb->v_rip = vcpu->vc_gueststate.vg_rip; @@ -6515,6 +6535,8 @@ vcpu_run_svm(struct vcpu *vcpu, struct vm_run_params *vrp) vcpu->vc_gueststate.vg_rip = vcpu->vc_exit.vrs.vrs_gprs[VCPU_REGS_RIP]; vmcb->v_rip = vcpu->vc_gueststate.vg_rip; + if (svm_vmgexit_sync_guest(vcpu)) + return (EINVAL); break; case SVM_VMEXIT_NPF: ret = vcpu_writeregs_svm(vcpu, VM_RWREGS_GPRS,