Problem with vmexit on mtrap

Martin Steegmanns martin at unix-users.de
Tue Aug 12 09:44:25 UTC 2014


Hello list!
I modified bhyve to toggle the MTF bit on an UD2 instruction.
In a guest system, a program does:
__asm__ __volatile__(
    "UD2"
    "NOP"      
    "xor %rax,%rax"
    "NOP"            
    "UD2"
);

On the first UD2, MTF bit is correctly set, but the second
UD2 is never reached (waited some hours). 
If I manually reset the MTF bit via bhyvectl --setcap,
guest executione reaches the second UD2 instruction.

A diff of my modifications is attached to this mail.

Am I missing something on vmenter that makes the guest loop forever?

Regards,
Martin

<snippet of ktr dump>
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:1074 vm vm1[0]: unhandled mtf vmexit at 0xffffffff804dde70
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:1063 vm vm1[0]: Resume execution at 0xffffffff804dde41
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:2652 vm vm1[0]: returning from vmx_run: exitcode 6
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:1074 vm vm1[0]: unhandled mtf vmexit at 0xffffffff804dde41
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:1063 vm vm1[0]: Resume execution at 0xffffffff804dde39
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:2652 vm vm1[0]: returning from vmx_run: exitcode 6
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:1074 vm vm1[0]: unhandled mtf vmexit at 0xffffffff804dde39
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:1063 vm vm1[0]: Resume execution at 0xffffffff804dde30
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:2652 vm vm1[0]: returning from vmx_run: exitcode 6
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:1074 vm vm1[0]: unhandled mtf vmexit at 0xffffffff804dde30
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:1063 vm vm1[0]: Resume execution at 0xffffffff804dde27
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:2652 vm vm1[0]: returning from vmx_run: exitcode 6
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:1074 vm vm1[0]: unhandled mtf vmexit at 0xffffffff804dde27
/usr/src/sys/modules/vmm/../../amd64/vmm/intel/vmx.c:1063 vm vm1[0]: Resume execution at 0xffffffff804dde1f
</snippet>
-------------- next part --------------
Index: sys/amd64/vmm/intel/vmcs.c
===================================================================
--- sys/amd64/vmm/intel/vmcs.c	(revision 269497)
+++ sys/amd64/vmm/intel/vmcs.c	(working copy)
@@ -418,7 +418,7 @@
 		goto done;
 
 	/* exception bitmap */
-	exc_bitmap = 1 << IDT_MC;
+	exc_bitmap = 1 << IDT_MC | 1 << IDT_UD;
 	if ((error = vmwrite(VMCS_EXCEPTION_BITMAP, exc_bitmap)) != 0)
 		goto done;
 
Index: sys/amd64/vmm/intel/vmx.c
===================================================================
--- sys/amd64/vmm/intel/vmx.c	(revision 269497)
+++ sys/amd64/vmm/intel/vmx.c	(working copy)
@@ -1024,6 +1024,20 @@
 }
 
 static int
+vmx_handle_exception(struct vmx *vmx, int vcpu, struct vm_exit *vme)
+{
+
+	return (HANDLED);
+}
+
+static int
+vmx_handle_ud_exception(struct vmx *vmx, int vcpu, struct vm_exit *vme)
+{
+
+	return (UNHANDLED);
+}
+
+static int
 vmx_handle_cpuid(struct vm *vm, int vcpu, struct vmxctx *vmxctx)
 {
 	int handled, func;
@@ -2256,6 +2270,8 @@
 		break;
 	case EXIT_REASON_MTF:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_MTRAP, 1);
+		vmexit_inst_emul(vmexit, vmcs_gpa(), vmcs_gla());
+		vmexit->inst_length = vmexit_instruction_length();
 		vmexit->exitcode = VM_EXITCODE_MTRAP;
 		break;
 	case EXIT_REASON_PAUSE:
@@ -2334,6 +2350,14 @@
 		KASSERT((intr_info & VMCS_INTR_VALID) != 0,
 		    ("VM exit interruption info invalid: %#x", intr_info));
 
+		if (intr_info & IDT_UD) {
+			vmexit->exitcode = VM_EXITCODE_UD;
+			handled = vmx_handle_ud_exception(vmx, vcpu, vmexit);
+		} else {
+			vmexit->exitcode = VM_EXITCODE_EXCEPTION;
+			handled = vmx_handle_exception(vmx, vcpu, vmexit);
+		}		
+
 		/*
 		 * If Virtual NMIs control is 1 and the VM-exit is due to a
 		 * fault encountered during the execution of IRET then we must
Index: sys/amd64/vmm/vmm.c
===================================================================
--- sys/amd64/vmm/vmm.c	(revision 269497)
+++ sys/amd64/vmm/vmm.c	(working copy)
@@ -1153,6 +1153,14 @@
 }
 
 static int
+vm_handle_mtf(struct vm *vm, int vcpuid, bool *retu)
+{
+	*retu = true;
+
+	return (0);
+}
+
+static int
 vm_handle_paging(struct vm *vm, int vcpuid, bool *retu)
 {
 	int rv, ftype;
@@ -1380,6 +1388,7 @@
 	bool retu, intr_disabled;
 	pmap_t pmap;
 	void *rptr, *sptr;
+	int val;
 
 	vcpuid = vmrun->cpuid;
 
@@ -1441,6 +1450,9 @@
 			intr_disabled = ((vme->u.hlt.rflags & PSL_I) == 0);
 			error = vm_handle_hlt(vm, vcpuid, intr_disabled, &retu);
 			break;
+		case VM_EXITCODE_MTRAP:
+			error = vm_handle_mtf(vm, vcpuid, &retu);
+			break;
 		case VM_EXITCODE_PAGING:
 			error = vm_handle_paging(vm, vcpuid, &retu);
 			break;
@@ -1451,6 +1463,12 @@
 		case VM_EXITCODE_INOUT_STR:
 			error = vm_handle_inout(vm, vcpuid, vme, &retu);
 			break;
+		case VM_EXITCODE_UD:
+			val = 1;
+			VMGETCAP(vm->cookie, vcpuid, VM_CAP_MTRAP_EXIT, &val);
+			val = (val == 1)? 0 : 1;
+			VMSETCAP(vm->cookie, vcpuid, VM_CAP_MTRAP_EXIT, val);
+			break;
 		default:
 			retu = true;	/* handled in userland */
 			break;
Index: sys/modules/vmm/Makefile
===================================================================
--- sys/modules/vmm/Makefile	(revision 269497)
+++ sys/modules/vmm/Makefile	(working copy)
@@ -4,7 +4,7 @@
 
 SRCS=	opt_acpi.h opt_ddb.h device_if.h bus_if.h pci_if.h
 
-CFLAGS+= -DVMM_KEEP_STATS -DSMP
+CFLAGS+= -DVMM_KEEP_STATS -DSMP -DKTR
 CFLAGS+= -I${.CURDIR}/../../amd64/vmm
 CFLAGS+= -I${.CURDIR}/../../amd64/vmm/io
 CFLAGS+= -I${.CURDIR}/../../amd64/vmm/intel


More information about the freebsd-virtualization mailing list