From nobody Fri Jan 05 00:28:21 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4T5knx5MLhz55gFf; Fri, 5 Jan 2024 00:28:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4T5knx3xG0z4hfs; Fri, 5 Jan 2024 00:28:21 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1704414501; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LHVP6BIWeKa0aEYRUWcb01S20WiQV71B8B+ROIf2cko=; b=Ro9F1weNj7pVH50mBGMbjcgXmbL+DZBLIvZooJyE7TTLAE46JmeNqhCmKJiBNFPoE5EkGa CGE37GBGo+YNqiEa9N4wwNHJvORGZHpdszfQGL94Pg3kehdH5ZKMrZTH3+eM4lRrlV8UVp vu022ecT1AwcmHKIvb69UN/86nwGiEsl+9G2Mzru/k+o8k02qWiVQbGLfrKUk7LCjUddcC EngekbbKo2HZxa5kmJr+OZunDTp+AGXeG0XQDH17195mbgncd0XCMa3bjYRy/nXTEWMO7V VDpPR/R/RNz+X7Rg28CZpVWY9QY1Ukb6uO+0ZVTX0Dw8hoQ4+Qp+muGJJUkEZg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1704414501; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LHVP6BIWeKa0aEYRUWcb01S20WiQV71B8B+ROIf2cko=; b=Q3fKIWMZrCF8xvtMMjnr9Xb6FhmUyylcw8xtGFqKZgyDuXpIe71YYAvVcVlfoYU2ih+Vrq 3FPbXOgkJbB/Y7ju05GSN1lm8fO9JVwaujaRyLWHBLVAx+CPrroun0zH4FA+d4CYbkVAUr ssZdOlf+0d5QM937Ii6/UFeimeq76BwWl/1Za6sPDBFGC0G30fsi+jtvu28YOGsHHymVjf b7G7aXdgW5v5gtZBVd8Pvc83Xypv6TBSNC4yyPBPHWHurLeRELTKmGU1N6eCCE2qFLsUBV /Yiqhd/5bs7ve9CWo96MxULxfW7ig/ZePMUy3xoIEvgKuZ90EzujyVwm2lfV7g== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1704414501; a=rsa-sha256; cv=none; b=JFHs7uH8INCZpiC6qJQojKYFCbKIWoYGQvE/o81bg2uKzUAjcF4PHzug9u3uJyGpIAEIv8 syM1TyvTv7xcBJDd8bzgy74e8Zm/zs2a0wJ9KI3j3a5/QDPH/tcfbQLJRYKtitgbJuKUee bncJgmvoOpkp2ck3KoDCemHTlHTkQH8d1u35VZVB6YiEOlQDbJXydegBKiSs7y5NKn4eVt VTzIhjCNmZGvKmGpctTE5TxqAELWnTwYw8CbFEr8drTzFiO+sGEuzN5jDZGnOdT8oNpgKz RHeJyPtd1hYGKpD4l8fk7dCxv7kEUFZGOiAXuTphrNAVt3KfovQF6SUmCGzeqw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4T5knx32W1zbH4; Fri, 5 Jan 2024 00:28:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 4050SL1n026845; Fri, 5 Jan 2024 00:28:21 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 4050SLvQ026842; Fri, 5 Jan 2024 00:28:21 GMT (envelope-from git) Date: Fri, 5 Jan 2024 00:28:21 GMT Message-Id: <202401050028.4050SLvQ026842@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: John Baldwin Subject: git: 791e4d689520 - stable/14 - bhyve: refactor gdbstub to enable single-stepping on AMD CPUs List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 791e4d68952029e026b2a03b41f830386d5f9d71 Auto-Submitted: auto-generated The branch stable/14 has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=791e4d68952029e026b2a03b41f830386d5f9d71 commit 791e4d68952029e026b2a03b41f830386d5f9d71 Author: Bojan Novković AuthorDate: 2023-12-12 23:28:59 +0000 Commit: John Baldwin CommitDate: 2024-01-05 00:26:28 +0000 bhyve: refactor gdbstub to enable single-stepping on AMD CPUs This patch refactors the existing Intel-specific single-stepping mechanism in bhyve's GDB stub to work with both AMD and Intel CPUs. Reviewed by: jhb Sponsored by: Google, Inc. (GSoC 2022) Differential Revision: https://reviews.freebsd.org/D42298 (cherry picked from commit ca96a942cafb58476e10e887240e594e7923a6e8) --- usr.sbin/bhyve/amd64/vmexit.c | 15 +++++++ usr.sbin/bhyve/gdb.c | 94 +++++++++++++++++++++++++++++++++++-------- usr.sbin/bhyve/gdb.h | 1 + 3 files changed, 93 insertions(+), 17 deletions(-) diff --git a/usr.sbin/bhyve/amd64/vmexit.c b/usr.sbin/bhyve/amd64/vmexit.c index 2c01c63f6454..e0b9aec2d17a 100644 --- a/usr.sbin/bhyve/amd64/vmexit.c +++ b/usr.sbin/bhyve/amd64/vmexit.c @@ -439,6 +439,20 @@ vmexit_debug(struct vmctx *ctx __unused, struct vcpu *vcpu, 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 @@ const vmexit_handler_t vmexit_handlers[VM_EXITCODE_MAX] = { [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.c b/usr.sbin/bhyve/gdb.c index a6c0700308e7..9748f7d82b44 100644 --- a/usr.sbin/bhyve/gdb.c +++ b/usr.sbin/bhyve/gdb.c @@ -744,6 +744,43 @@ _gdb_cpu_suspend(struct vcpu *vcpu, bool report_stop) 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. @@ -798,10 +835,7 @@ gdb_cpu_resume(struct vcpu *vcpu) 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); } } @@ -836,26 +870,24 @@ gdb_suspend_vcpus(void) } /* - * 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) { @@ -870,6 +902,34 @@ gdb_cpu_mtrap(struct vcpu *vcpu) 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) { @@ -941,11 +1001,11 @@ gdb_cpu_breakpoint(struct vcpu *vcpu, struct vm_exit *vmexit) 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); diff --git a/usr.sbin/bhyve/gdb.h b/usr.sbin/bhyve/gdb.h index f06375d0d591..98f9ece2f60c 100644 --- a/usr.sbin/bhyve/gdb.h +++ b/usr.sbin/bhyve/gdb.h @@ -32,6 +32,7 @@ void gdb_cpu_add(struct vcpu *vcpu); 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__ */