Index: sys/amd64/vmm/intel/vmx.c =================================================================== --- sys/amd64/vmm/intel/vmx.c (revision 269700) +++ sys/amd64/vmm/intel/vmx.c (working copy) @@ -1894,6 +1894,37 @@ ept_emulation_fault(uint64_t ept_qual) return (TRUE); } +/* + * Workaround an intermittent bug when running in VMware Fusion. + * + * An EPT-violation exit may be caused by a guest accessing an MMIO region + * (e.g. APIC) that is marked not-present in the nested page tables. In this + * case the exit qualification must indicate that: + * - the guest-linear-address field is valid + * - the GPA causing the EPT-violation is the translation of a linear address + * + * If the exit qualification does not have these bits set and we are running + * nested then restart the instruction assuming that the bug is intermittent. + */ +static u_long ept_violation_restarts; +SYSCTL_ULONG(_hw_vmm_vmx, OID_AUTO, ept_violation_restarts, CTLFLAG_RW, + &ept_violation_restarts, 0, NULL); + +static boolean_t +ept_fault_restart(uint64_t ept_qual) +{ + int nested = 1; /* XXX */ + + if (nested) { + if ((ept_qual & EPT_VIOLATION_GLA_VALID) == 0 && + (ept_qual & EPT_VIOLATION_XLAT_VALID) == 0) { + atomic_add_long(&ept_violation_restarts, 1); + return (TRUE); + } + } + return (FALSE); +} + static __inline int apic_access_virtualization(struct vmx *vmx, int vcpuid) { @@ -2370,6 +2401,9 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct } else if (ept_emulation_fault(qual)) { vmexit_inst_emul(vmexit, gpa, vmcs_gla()); vmm_stat_incr(vmx->vm, vcpu, VMEXIT_INST_EMUL, 1); + } else if (ept_fault_restart(qual)) { + vmexit->inst_length = 0; + handled = 1; } /* * If Virtual NMIs control is 1 and the VM-exit is due to an