Index | Thread | Search

From:
Hans-Jörg Höxer <hshoexer@genua.de>
Subject:
SEV-ES: vmm(4): Handle IOIO gexit
To:
<tech@openbsd.org>
Date:
Tue, 20 May 2025 12:23:11 +0200

Download raw body.

Thread
Hi,

and the last chunk, in/out related 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.

With this diff vmm(8)/vmd(8) will be able to deal with all GEXITs that
will be generated by openbsd SEV-ES enabled guest (for now).

Take care,
HJ.
-------------------------------------------------------------------------
commit 270c450535e0465ede449f02bf11faac624037d8
Author: Hans-Joerg Hoexer <hshoexer@genua.de>
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 9bcf3f3fffe..9049bc6340d 100644
--- a/sys/arch/amd64/amd64/vmm_machdep.c
+++ b/sys/arch/amd64/amd64/vmm_machdep.c
@@ -4393,6 +4393,14 @@ svm_gexit_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);
 	}
@@ -4458,6 +4466,14 @@ svm_gexit_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);
 	}
@@ -4523,6 +4539,10 @@ svm_handle_gexit(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;
@@ -6468,6 +6488,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_gexit_sync_guest(vcpu))
+			return (EINVAL);
 		break;
 	case SVM_VMEXIT_NPF:
 		ret = vcpu_writeregs_svm(vcpu, VM_RWREGS_GPRS,