Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107082012
D42298.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D42298.diff
View Options
diff --git a/usr.sbin/bhyve/amd64/vmexit.c b/usr.sbin/bhyve/amd64/vmexit.c
--- a/usr.sbin/bhyve/amd64/vmexit.c
+++ b/usr.sbin/bhyve/amd64/vmexit.c
@@ -439,6 +439,20 @@
return (VMEXIT_CONTINUE);
}
+static int
+vmexit_db(struct vmctx *ctx __unused, struct vcpu *vcpu, struct vm_run *vmrun)
+{
+
+#ifdef BHYVE_SNAPSHOT
+ checkpoint_cpu_suspend(vcpu_id(vcpu));
+#endif
+ gdb_cpu_debug(vcpu, vmrun->vm_exit);
+#ifdef BHYVE_SNAPSHOT
+ checkpoint_cpu_resume(vcpu_id(vcpu));
+#endif
+ return (VMEXIT_CONTINUE);
+}
+
static int
vmexit_breakpoint(struct vmctx *ctx __unused, struct vcpu *vcpu,
struct vm_run *vmrun)
@@ -503,4 +517,5 @@
[VM_EXITCODE_IPI] = vmexit_ipi,
[VM_EXITCODE_HLT] = vmexit_hlt,
[VM_EXITCODE_PAUSE] = vmexit_pause,
+ [VM_EXITCODE_DB] = vmexit_db,
};
diff --git a/usr.sbin/bhyve/gdb.h b/usr.sbin/bhyve/gdb.h
--- a/usr.sbin/bhyve/gdb.h
+++ b/usr.sbin/bhyve/gdb.h
@@ -32,6 +32,7 @@
void gdb_cpu_breakpoint(struct vcpu *vcpu, struct vm_exit *vmexit);
void gdb_cpu_mtrap(struct vcpu *vcpu);
void gdb_cpu_suspend(struct vcpu *vcpu);
+void gdb_cpu_debug(struct vcpu *vcpu, struct vm_exit *vmexit);
void init_gdb(struct vmctx *ctx);
#endif /* !__GDB_H__ */
diff --git a/usr.sbin/bhyve/gdb.c b/usr.sbin/bhyve/gdb.c
--- a/usr.sbin/bhyve/gdb.c
+++ b/usr.sbin/bhyve/gdb.c
@@ -743,6 +743,43 @@
debug("$vCPU %d resuming\n", vcpuid);
}
+/*
+ * Requests vCPU single-stepping using a
+ * VMEXIT suitable for the host platform.
+ */
+static int
+_gdb_set_step(struct vcpu *vcpu, int val)
+{
+ int error;
+
+ /*
+ * If the MTRAP cap fails, we are running on an AMD host.
+ * In that case, we request DB exits caused by RFLAGS.TF.
+ */
+ error = vm_set_capability(vcpu, VM_CAP_MTRAP_EXIT, val);
+ if (error != 0)
+ error = vm_set_capability(vcpu, VM_CAP_RFLAGS_TF, val);
+ if (error == 0)
+ (void)vm_set_capability(vcpu, VM_CAP_MASK_HWINTR, val);
+
+ return (error);
+}
+
+/*
+ * Checks whether single-stepping is enabled for a given vCPU.
+ */
+static int
+_gdb_check_step(struct vcpu *vcpu)
+{
+ int val;
+
+ if (vm_get_capability(vcpu, VM_CAP_MTRAP_EXIT, &val) != 0) {
+ if (vm_get_capability(vcpu, VM_CAP_RFLAGS_TF, &val) != 0)
+ return -1;
+ }
+ return 0;
+}
+
/*
* Invoked at the start of a vCPU thread's execution to inform the
* debug server about the new thread.
@@ -797,10 +834,7 @@
assert(vs->hit_swbreak == false);
assert(vs->stepped == false);
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);
+ error = _gdb_set_step(vcpu, 1);
assert(error == 0);
}
}
@@ -835,26 +869,24 @@
}
/*
- * Handler for VM_EXITCODE_MTRAP reported when a vCPU single-steps via
- * the VT-x-specific MTRAP exit.
+ * Invoked each time a vmexit handler needs to step a vCPU.
+ * Handles MTRAP and RFLAGS.TF vmexits.
*/
-void
-gdb_cpu_mtrap(struct vcpu *vcpu)
+static void
+gdb_cpu_step(struct vcpu *vcpu)
{
struct vcpu_state *vs;
- int vcpuid;
+ int vcpuid = vcpu_id(vcpu);
+ int error;
- if (!gdb_active)
- return;
- vcpuid = vcpu_id(vcpu);
- debug("$vCPU %d MTRAP\n", vcpuid);
+ debug("$vCPU %d stepped\n", vcpuid);
pthread_mutex_lock(&gdb_lock);
vs = &vcpu_state[vcpuid];
if (vs->stepping) {
vs->stepping = false;
vs->stepped = true;
- vm_set_capability(vcpu, VM_CAP_MTRAP_EXIT, 0);
- vm_set_capability(vcpu, VM_CAP_MASK_HWINTR, 0);
+ error = _gdb_set_step(vcpu, 0);
+ assert(error == 0);
while (vs->stepped) {
if (stopped_vcpu == -1) {
@@ -869,6 +901,34 @@
pthread_mutex_unlock(&gdb_lock);
}
+/*
+ * A general handler for VM_EXITCODE_DB.
+ * Handles RFLAGS.TF exits on AMD SVM.
+ */
+void
+gdb_cpu_debug(struct vcpu *vcpu, struct vm_exit *vmexit)
+{
+ if (!gdb_active)
+ return;
+
+ /* RFLAGS.TF exit? */
+ if (vmexit->u.dbg.trace_trap) {
+ gdb_cpu_step(vcpu);
+ }
+}
+
+/*
+ * Handler for VM_EXITCODE_MTRAP reported when a vCPU single-steps via
+ * the VT-x-specific MTRAP exit.
+ */
+void
+gdb_cpu_mtrap(struct vcpu *vcpu)
+{
+ if (!gdb_active)
+ return;
+ gdb_cpu_step(vcpu);
+}
+
static struct breakpoint *
find_breakpoint(uint64_t gpa)
{
@@ -940,11 +1000,11 @@
static bool
gdb_step_vcpu(struct vcpu *vcpu)
{
- int error, val, vcpuid;
+ int error, vcpuid;
vcpuid = vcpu_id(vcpu);
debug("$vCPU %d step\n", vcpuid);
- error = vm_get_capability(vcpu, VM_CAP_MTRAP_EXIT, &val);
+ error = _gdb_check_step(vcpu);
if (error < 0)
return (false);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 10, 8:15 PM (15 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15746099
Default Alt Text
D42298.diff (4 KB)
Attached To
Mode
D42298: bhyve: refactor gdbstub to enable single-stepping on AMD CPUs
Attached
Detach File
Event Timeline
Log In to Comment