The branch main has been updated by corvink:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=fefac543590db4e1461235b7c936f46026d0f318

commit fefac543590db4e1461235b7c936f46026d0f318
Author:     Bojan Novković <bojan.novko...@fer.hr>
AuthorDate: 2023-05-09 07:02:04 +0000
Commit:     Corvin Köhne <corv...@freebsd.org>
CommitDate: 2023-05-09 08:04:55 +0000

    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
---
 sys/amd64/include/vmm.h   | 1 +
 sys/amd64/vmm/intel/vmx.c | 7 +++++++
 usr.sbin/bhyve/gdb.c      | 5 +++++
 3 files changed, 13 insertions(+)

diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
index c3d1aa4f3866..a328404a89d5 100644
--- a/sys/amd64/include/vmm.h
+++ b/sys/amd64/include/vmm.h
@@ -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
 };
 
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index 8b8f8fe6cb25..69391f5b77de 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -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;
        }
diff --git a/usr.sbin/bhyve/gdb.c b/usr.sbin/bhyve/gdb.c
index 9e50602e92be..7a2c5aec0d86 100644
--- a/usr.sbin/bhyve/gdb.c
+++ b/usr.sbin/bhyve/gdb.c
@@ -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);

Reply via email to