From nobody Tue Dec 12 23:29:13 2023 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 4SqZZK2J0Gz53T5S; Tue, 12 Dec 2023 23:29:13 +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 4SqZZK1rlRz4G1h; Tue, 12 Dec 2023 23:29:13 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1702423753; 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=hcve0D8eycoYvbbXdwE3hQOr7giHgDYBSK14u0iLRJc=; b=eShlcM/tkxon1QzUE24ssMRqORN4dtorstTJEuWxab4jUV5hryLMPjGvdwQ/pskeb6e7TE Ne3SktYHRIn+U8k0SpZ9KWUPfNRRNq+qHj6Xfd072HT6dWkOO4/axJmEDVLT63DEvUiGpu kDZ8Tp/dDpPwsh2GrY5uucXHIRl2waUXy3sgAgC5Rv/FO7yJauGDJR2KzTSVgpeyJrOdYF ymoDYjouqo5qhwD069nUmmDtknn34vnizcQ9SE6YIXe6b0nfrxyrnuuZRE3EFWwoi2XwWW hCynb4BsAPV8L7eqbDlnzAAQrS45A9CgL6caJD8QZZUT9mtgpZE7eHXCDZc39g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1702423753; a=rsa-sha256; cv=none; b=Z5Ctxf418kQZJq2QT0iFgCniTB9UEi8iazsCnAop8cMZ4BBoDXU3M87yqWsfpqeC6/8etG 0SrRLJIb4SPMBbcgYgpccPIvcyy30qtfObw3WOTMTU2Y1mafxNa9jgDx7pWvHJ+PoeHLYQ 4BxhSTOVO0/pm/nvOcTOE3wr8FgULdWzJ7HqhApxm+97VmWaofVxXKlMrkK+Mu1bpzwgTR uItihXLtqhoVTICqUSiiECsN7X6ODi5BEACK+av/dVI3/fk4oRIVNuLVybmh7rvB+F37ps 9o2FOmJk3FriWap+Vt025vB0Yxk0JhEBgicmvHnkD7cpy4roSUZaQ/eTBaBx5Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1702423753; 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=hcve0D8eycoYvbbXdwE3hQOr7giHgDYBSK14u0iLRJc=; b=Aqk22XyONVBEBuEXgrtaJXs1VugJioRCny7mJwAglEWWNB+gJ0ddKDjnbAvKK60FoTBofT Y56j6bffWc7qZBjy7mk7fy43HaeEGk3gS6RqNyUqheshYollOrpYAgdw9xwFoV1EbDBmFA 8UzXw/K+1QkYkO4E711mZuB7vQNsI2OhH27T+SHFBa9bJbp28XSWo4+cSLOYpaCqvC6gME euXJgwbNgu0hLVFhk+G39DNfb15YtZKjF3eqTdfenjDyJEx7VXPFKLRuK0abIQt2rr6Dci o5Qw8DjC44fwMCDGob79+G3FN1dfQGAWFG3hm+HJ/gQbtGpB0dMHkCvcUF3L2w== 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 4SqZZK0wGszbKl; Tue, 12 Dec 2023 23:29:13 +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 3BCNTDig007671; Tue, 12 Dec 2023 23:29:13 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 3BCNTDwe007668; Tue, 12 Dec 2023 23:29:13 GMT (envelope-from git) Date: Tue, 12 Dec 2023 23:29:13 GMT Message-Id: <202312122329.3BCNTDwe007668@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: John Baldwin Subject: git: ca96a942cafb - main - 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/main X-Git-Reftype: branch X-Git-Commit: ca96a942cafb58476e10e887240e594e7923a6e8 Auto-Submitted: auto-generated The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=ca96a942cafb58476e10e887240e594e7923a6e8 commit ca96a942cafb58476e10e887240e594e7923a6e8 Author: Bojan Novković AuthorDate: 2023-12-12 23:28:59 +0000 Commit: John Baldwin CommitDate: 2023-12-12 23:28:59 +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 --- 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 be730a75b3e6..2d49469c2e11 100644 --- a/usr.sbin/bhyve/gdb.c +++ b/usr.sbin/bhyve/gdb.c @@ -743,6 +743,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. @@ -797,10 +834,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); } } @@ -835,26 +869,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) { @@ -869,6 +901,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) { @@ -940,11 +1000,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__ */