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