bhyve: fix vCPU single-stepping on VMX
This patch fixes virtual machine single stepping on VMX hosts. Currently, when using bhyve's gdb stub, each attempt at single-stepping a vCPU lands in a timer interrupt. The current single-stepping mechanism uses the Monitor Trap Flag feature to cause VMEXIT after a single instruction is executed. Unfortunately, the SDM states that MTF causes VMEXITs for the next instruction that gets executed, which is often not what the person using the debugger expects. [1] This patch adds a new VM capability that masks interrupts on a vCPU by blocking interrupt injection and modifies the gdb stub to use the newly added capability while single-stepping a vCPU. [1] Intel SDM 26.5.2 Vol. 3C Reviewed by: corvink, jbh MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D39949
This commit is contained in:
parent
b0cf48305f
commit
fefac54359
@ -497,6 +497,7 @@ enum vm_cap_type {
|
||||
VM_CAP_RDPID,
|
||||
VM_CAP_RDTSCP,
|
||||
VM_CAP_IPI_EXIT,
|
||||
VM_CAP_MASK_HWINTR,
|
||||
VM_CAP_MAX
|
||||
};
|
||||
|
||||
|
@ -1439,6 +1439,10 @@ vmx_inject_interrupts(struct vmx_vcpu *vcpu, struct vlapic *vlapic,
|
||||
uint64_t rflags, entryinfo;
|
||||
uint32_t gi, info;
|
||||
|
||||
if (vcpu->cap.set & (1 << VM_CAP_MASK_HWINTR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (vcpu->state.nextrip != guestrip) {
|
||||
gi = vmcs_read(VMCS_GUEST_INTERRUPTIBILITY);
|
||||
if (gi & HWINTR_BLOCKING) {
|
||||
@ -3634,6 +3638,9 @@ vmx_setcap(void *vcpui, int type, int val)
|
||||
vlapic = vm_lapic(vcpu->vcpu);
|
||||
vlapic->ipi_exit = val;
|
||||
break;
|
||||
case VM_CAP_MASK_HWINTR:
|
||||
retval = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -801,6 +801,9 @@ gdb_cpu_resume(struct vcpu *vcpu)
|
||||
if (vs->stepping) {
|
||||
error = vm_set_capability(vcpu, VM_CAP_MTRAP_EXIT, 1);
|
||||
assert(error == 0);
|
||||
|
||||
error = vm_set_capability(vcpu, VM_CAP_MASK_HWINTR, 1);
|
||||
assert(error == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -853,6 +856,8 @@ gdb_cpu_mtrap(struct vcpu *vcpu)
|
||||
vs->stepping = false;
|
||||
vs->stepped = true;
|
||||
vm_set_capability(vcpu, VM_CAP_MTRAP_EXIT, 0);
|
||||
vm_set_capability(vcpu, VM_CAP_MASK_HWINTR, 0);
|
||||
|
||||
while (vs->stepped) {
|
||||
if (stopped_vcpu == -1) {
|
||||
debug("$vCPU %d reporting step\n", vcpuid);
|
||||
|
Loading…
Reference in New Issue
Block a user