diff --git a/core/cpu.c b/core/cpu.c index 050cc169..1c593210 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -222,6 +222,7 @@ bool vcpu_is_panic(struct vcpu_t *vcpu) if (vcpu->panicked) { hax_log(HAX_LOGE, "vcpu has panicked, id:%d\n", vcpu->vcpu_id); hax_panic_log(vcpu); + htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason; htun->_exit_status = HAX_EXIT_STATECHANGE; return 1; } diff --git a/core/include/hax_core_interface.h b/core/include/hax_core_interface.h index d974ce2f..81cdfcb4 100644 --- a/core/include/hax_core_interface.h +++ b/core/include/hax_core_interface.h @@ -94,6 +94,7 @@ int hax_vm_set_qemuversion(struct vm_t *vm, struct hax_qemu_version *ver); struct vm_t * hax_create_vm(int *vm_id); int hax_teardown_vm(struct vm_t *vm); int vcpu_event_pending(struct vcpu_t *vcpu); +void vcpu_setexcbmp(struct vcpu_t *vcpu, uint32_t excbmp); #ifdef __cplusplus } diff --git a/core/include/vcpu.h b/core/include/vcpu.h index c81349b7..389733f6 100644 --- a/core/include/vcpu.h +++ b/core/include/vcpu.h @@ -237,6 +237,8 @@ struct vcpu_t { #ifdef CONFIG_HAX_EPT2 struct mmio_fetch_cache mmio_fetch; #endif // CONFIG_HAX_EPT2 + + uint32_t user_excbmp; }; #define vmx(v, field) v->vmx.field @@ -263,6 +265,7 @@ int vcpu_put_fpu(struct vcpu_t *vcpu, struct fx_layout *fl); int vcpu_get_msr(struct vcpu_t *vcpu, uint64_t entry, uint64_t *val); int vcpu_put_msr(struct vcpu_t *vcpu, uint64_t entry, uint64_t val); void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug); +void vcpu_setexcbmp(struct vcpu_t *vcpu, uint32_t excbmp); /* The declaration for OS wrapper code */ int hax_vcpu_destroy_host(struct vcpu_t *cvcpu, void *vcpu_host); diff --git a/core/include/vm.h b/core/include/vm.h index 08e33849..4ff10588 100644 --- a/core/include/vm.h +++ b/core/include/vm.h @@ -111,7 +111,8 @@ enum exit_status { HAX_EXIT_PAUSED, HAX_EXIT_FAST_MMIO, HAX_EXIT_PAGEFAULT, - HAX_EXIT_DEBUG + HAX_EXIT_DEBUG, + HAX_EXIT_NMI }; enum run_flag { diff --git a/core/vcpu.c b/core/vcpu.c index 9a505568..e68dd032 100644 --- a/core/vcpu.c +++ b/core/vcpu.c @@ -1073,6 +1073,11 @@ static void load_dirty_vmcs_fields(struct vcpu_t *vcpu) vcpu->rflags_dirty = 1; vcpu->debug_control_dirty = 0; } + if ((vcpu->debug_control & HAX_DEBUG_STEP) && + (vmx(vcpu, interruptibility_state).raw & 3u)) { + vmx(vcpu, interruptibility_state).raw &= ~3u; + vcpu->interruptibility_dirty = 1; + } if (vcpu->rflags_dirty) { vmwrite(vcpu, GUEST_RFLAGS, state->_rflags); vcpu->rflags_dirty = 0; @@ -1327,6 +1332,7 @@ static void vcpu_update_exception_bitmap(struct vcpu_t *vcpu) if (vcpu->debug_control & HAX_DEBUG_USE_SW_BP) { exc_bitmap |= (1u << VECTOR_BP); } + exc_bitmap |= vcpu->user_excbmp; vmwrite(vcpu, VMX_EXCEPTION_BITMAP, exc_bitmap); } @@ -2421,6 +2427,17 @@ static int exit_exc_nmi(struct vcpu_t *vcpu, struct hax_tunnel *htun) htun->debug.dr7 = 0; return HAX_EXIT; } + default: + if (vcpu->user_excbmp & (1 << exit_intr_info.vector)) + { + uint64_t va; + + htun->_exit_status = HAX_EXIT_NMI; + htun->nmi.exit_intr_info = exit_intr_info.raw; + va = vcpu->state->_cs.long_mode == 1 ? vcpu->state->_rip : vcpu->state->_cs.base + vcpu->state->_rip; + vcpu_read_guest_virtual(vcpu, va, vcpu->io_buf, INSTR_MAX_LEN, INSTR_MAX_LEN, 0); + return HAX_EXIT; + } } if (exit_intr_info.vector == VECTOR_PF) { @@ -4187,6 +4204,13 @@ void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug) vcpu_update_exception_bitmap(vcpu); }; +void vcpu_setexcbmp(struct vcpu_t *vcpu, uint32_t excbmp) +{ + vcpu->user_excbmp = excbmp; + hax_log(HAX_LOGE, "set user_excbmp = %08X", vcpu->user_excbmp); + vcpu_update_exception_bitmap(vcpu); +} + static void vcpu_dump(struct vcpu_t *vcpu, uint32_t mask, const char *caption) { vcpu_vmread_all(vcpu); diff --git a/include/hax_interface.h b/include/hax_interface.h index 25c08b31..396062f0 100644 --- a/include/hax_interface.h +++ b/include/hax_interface.h @@ -153,6 +153,9 @@ struct hax_tunnel { uint64_t dr6; uint64_t dr7; } debug; + struct { + uint32_t exit_intr_info; + } nmi; }; uint64_t apic_base; } PACKED; diff --git a/platforms/windows/hax_entry.c b/platforms/windows/hax_entry.c index f56335e8..d3a1ea8e 100644 --- a/platforms/windows/hax_entry.c +++ b/platforms/windows/hax_entry.c @@ -430,6 +430,10 @@ NTSTATUS HaxVcpuControl(PDEVICE_OBJECT DeviceObject, vcpu_debug(cvcpu, (struct hax_debug_t*)inBuf); break; } + case HAX_VCPU_IOCTL_SET_EXCBMP: { + vcpu_setexcbmp(cvcpu, *(uint32_t*)inBuf); + break; + } default: hax_log(HAX_LOGE, "Unknow vcpu ioctl %lx\n", irpSp->Parameters.DeviceIoControl.IoControlCode); diff --git a/platforms/windows/hax_entry.h b/platforms/windows/hax_entry.h index 52613f7d..a441d478 100644 --- a/platforms/windows/hax_entry.h +++ b/platforms/windows/hax_entry.h @@ -166,4 +166,7 @@ extern PDRIVER_OBJECT HaxDriverObject; #define HAX_IOCTL_VCPU_DEBUG \ CTL_CODE(HAX_DEVICE_TYPE, 0x916, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VCPU_IOCTL_SET_EXCBMP \ + CTL_CODE(HAX_DEVICE_TYPE, 0x919, METHOD_BUFFERED, FILE_ANY_ACCESS) + #endif // HAX_WINDOWS_HAX_ENTRY_H_