From nobody Tue Jun 04 20:06:30 2024 X-Original-To: dev-commits-src-main@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 4Vv1ng0kssz5MQ8C; Tue, 04 Jun 2024 20:06:31 +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 4Vv1nf6vz5z4fcp; Tue, 4 Jun 2024 20:06:30 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1717531591; 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=lhWDlSSg6Q6S7OoP2DI7Qq9dNRIx5AB2R4/omjPWnu4=; b=OtafCPhdH9mYPdrGTtHrtLumJQy6JUdzd8m3Kayj4mjqcAynUYccXs008+jksuG4MHVxkI rIgq58907Zhg7pToAosr2tA77wg8DcSC0/zUmqmZtmCoMAt4UXcNzWUtYoA95zbVU/GFIh ui+uTnBnu+InoCbMLq+HD6rYVQ1nx5zLzAjtluVTE+KJtjegANggcTudhdNhK39gitzbOC CfrYE8aE+eV+uOPElsYHTqluJhQnjHUahBtXXCgfKIF4IZADEeQXP3YCHS9claLqLqrKTb +zBDf7FPyFnejetPNkWBpi9EmPBbbQqq4bEmxTpsbrsZpu1dywZF+jye4Arkpw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1717531591; a=rsa-sha256; cv=none; b=H/rZRc7maK6/1wkVq/v/qoQB36RVdKsCtv9hP8yL583tuA8REarsLERm/kMGWzCSRayPDb /5mK1evjiPpAglOF+MSF3DSItkpqmXkNzS9DDQ1M4I51IuGx6ud9dLUCHgxWmGuDA3CFvu Bv91ltN9wOsfB9qHIEWRZI6T3e/MG/7906SiRumJ0YXAjklorn/r1yC5qv7emil2hYuuOJ 18DZ58QkdtnJGzJNgEGMpRov7oheukt4nGL8L+hHikDN170/j1Azz8gSEr82uJdgjJ1FyV Rru/86VrIJNDn6U7O7ipgA3SWogMNuGmnO5X4iQnh2/5N+akMBA4O27i8kevfw== 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=1717531591; 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=lhWDlSSg6Q6S7OoP2DI7Qq9dNRIx5AB2R4/omjPWnu4=; b=EHzsFSZ8GoBs6X0TRpPec64N5wn+FGkh+f1I4DLaoPPXXwYJsq7KpWTxc698wuziw2cPSL EO9I95nNCHUtjGkkMCCyDhjGSiZF1ZveR4TL0tMfRVX7yEmTTr2StQA7PSAA8ghhadk31l dfLWKf8PMk908YwM9FG73y3x/22BOiBTFpAfSBAgvEqm35QDEE58MgplfXds7p2aVUKvPU 9Qk8mMH8DBppPC5aynxrVtPG6KxeQxkeZxRAuvvvF2onDnXCzM2qDRcC7qpGrAc7nE2Dbc y+bgqPhIpF872wdNCU+XXHB2q2F7IjsOWqvzAPAug82yjrUFZ+sjh4blvwIA+A== 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 4Vv1nf6W58zXls; Tue, 4 Jun 2024 20:06:30 +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 454K6U3N075071; Tue, 4 Jun 2024 20:06:30 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 454K6UG9075068; Tue, 4 Jun 2024 20:06:30 GMT (envelope-from git) Date: Tue, 4 Jun 2024 20:06:30 GMT Message-Id: <202406042006.454K6UG9075068@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mark Johnston Subject: git: 75cb949228bb - main - arm64/vmm: Add breakpoint and single-stepping support List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 75cb949228bb97e49f35fd2b2585293a6b9212aa Auto-Submitted: auto-generated The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=75cb949228bb97e49f35fd2b2585293a6b9212aa commit 75cb949228bb97e49f35fd2b2585293a6b9212aa Author: Mark Johnston AuthorDate: 2024-06-04 18:58:08 +0000 Commit: Mark Johnston CommitDate: 2024-06-04 18:58:08 +0000 arm64/vmm: Add breakpoint and single-stepping support This will be used to implement parts of bhyve's gdb stub. Three VM capabilities are added, similar to amd64 without monitor mode. Two cause breakpoint and single-step exceptions to be raised to EL2 and then down to bhyve. One lets the gdb stub mask hardware interrupts while single-stepping, since otherwise the guest will handle a timer interrupt before executing the target instruction and thus fail to make progress. Reviewed by: bnovkov, andrew Sponsored by: Innovate UK Differential Revision: https://reviews.freebsd.org/D44739 --- sys/arm64/include/vmm.h | 6 +++- sys/arm64/vmm/arm64.h | 9 ++++++ sys/arm64/vmm/vmm_arm64.c | 79 +++++++++++++++++++++++++++++++++++++++++++++-- sys/arm64/vmm/vmm_stat.c | 2 ++ sys/arm64/vmm/vmm_stat.h | 2 ++ 5 files changed, 95 insertions(+), 3 deletions(-) diff --git a/sys/arm64/include/vmm.h b/sys/arm64/include/vmm.h index 8e2c9c868635..c06d2ad947e4 100644 --- a/sys/arm64/include/vmm.h +++ b/sys/arm64/include/vmm.h @@ -295,9 +295,11 @@ struct vre { */ enum vm_cap_type { VM_CAP_HALT_EXIT, - VM_CAP_MTRAP_EXIT, VM_CAP_PAUSE_EXIT, VM_CAP_UNRESTRICTED_GUEST, + VM_CAP_BRK_EXIT, + VM_CAP_SS_EXIT, + VM_CAP_MASK_HWINTR, VM_CAP_MAX }; @@ -312,6 +314,8 @@ enum vm_exitcode { VM_EXITCODE_PAGING, VM_EXITCODE_SMCCC, VM_EXITCODE_DEBUG, + VM_EXITCODE_BRK, + VM_EXITCODE_SS, VM_EXITCODE_MAX }; diff --git a/sys/arm64/vmm/arm64.h b/sys/arm64/vmm/arm64.h index 43459d14e143..8cfe77dcde6f 100644 --- a/sys/arm64/vmm/arm64.h +++ b/sys/arm64/vmm/arm64.h @@ -39,6 +39,9 @@ struct vgic_v3; struct vgic_v3_cpu; +/* + * Per-vCPU hypervisor state. + */ struct hypctx { struct trapframe tf; @@ -104,6 +107,12 @@ struct hypctx { struct vtimer_cpu vtimer_cpu; + uint64_t setcaps; /* Currently enabled capabilities. */ + + /* vCPU state used to handle guest debugging. */ + uint64_t debug_spsr; /* Saved guest SPSR */ + uint64_t debug_mdscr; /* Saved guest MDSCR */ + struct vgic_v3_regs vgic_v3_regs; struct vgic_v3_cpu *vgic_cpu; bool has_exception; diff --git a/sys/arm64/vmm/vmm_arm64.c b/sys/arm64/vmm/vmm_arm64.c index e71761f9ccef..e0547bcef914 100644 --- a/sys/arm64/vmm/vmm_arm64.c +++ b/sys/arm64/vmm/vmm_arm64.c @@ -700,7 +700,14 @@ handle_el1_sync_excp(struct hypctx *hypctx, struct vm_exit *vme_ret, arm64_gen_reg_emul_data(esr_iss, vme_ret); vme_ret->exitcode = VM_EXITCODE_REG_EMUL; break; - + case EXCP_BRK: + vmm_stat_incr(hypctx->vcpu, VMEXIT_BRK, 1); + vme_ret->exitcode = VM_EXITCODE_BRK; + break; + case EXCP_SOFTSTP_EL0: + vmm_stat_incr(hypctx->vcpu, VMEXIT_SS, 1); + vme_ret->exitcode = VM_EXITCODE_SS; + break; case EXCP_INSN_ABORT_L: case EXCP_DATA_ABORT_L: vmm_stat_incr(hypctx->vcpu, esr_ec == EXCP_DATA_ABORT_L ? @@ -1313,6 +1320,7 @@ vmmops_exception(void *vcpui, uint64_t esr, uint64_t far) int vmmops_getcap(void *vcpui, int num, int *retval) { + struct hypctx *hypctx = vcpui; int ret; ret = ENOENT; @@ -1322,6 +1330,11 @@ vmmops_getcap(void *vcpui, int num, int *retval) *retval = 1; ret = 0; break; + case VM_CAP_BRK_EXIT: + case VM_CAP_SS_EXIT: + case VM_CAP_MASK_HWINTR: + *retval = (hypctx->setcaps & (1ul << num)) != 0; + break; default: break; } @@ -1332,6 +1345,68 @@ vmmops_getcap(void *vcpui, int num, int *retval) int vmmops_setcap(void *vcpui, int num, int val) { + struct hypctx *hypctx = vcpui; + int ret; + + ret = 0; - return (ENOENT); + switch (num) { + case VM_CAP_BRK_EXIT: + if ((val != 0) == (hypctx->setcaps & (1ul << num)) != 0) + break; + if (val != 0) + hypctx->mdcr_el2 |= MDCR_EL2_TDE; + else + hypctx->mdcr_el2 &= ~MDCR_EL2_TDE; + break; + case VM_CAP_SS_EXIT: + if ((val != 0) == (hypctx->setcaps & (1ul << num)) != 0) + break; + + if (val != 0) { + hypctx->debug_spsr |= (hypctx->tf.tf_spsr & PSR_SS); + hypctx->debug_mdscr |= hypctx->mdscr_el1 & + (MDSCR_SS | MDSCR_KDE); + + hypctx->tf.tf_spsr |= PSR_SS; + hypctx->mdscr_el1 |= MDSCR_SS | MDSCR_KDE; + hypctx->mdcr_el2 |= MDCR_EL2_TDE; + } else { + hypctx->tf.tf_spsr &= ~PSR_SS; + hypctx->tf.tf_spsr |= hypctx->debug_spsr; + hypctx->debug_spsr &= ~PSR_SS; + hypctx->mdscr_el1 &= ~(MDSCR_SS | MDSCR_KDE); + hypctx->mdscr_el1 |= hypctx->debug_mdscr; + hypctx->debug_mdscr &= ~(MDSCR_SS | MDSCR_KDE); + hypctx->mdcr_el2 &= ~MDCR_EL2_TDE; + } + break; + case VM_CAP_MASK_HWINTR: + if ((val != 0) == (hypctx->setcaps & (1ul << num)) != 0) + break; + + if (val != 0) { + hypctx->debug_spsr |= (hypctx->tf.tf_spsr & + (PSR_I | PSR_F)); + hypctx->tf.tf_spsr |= PSR_I | PSR_F; + } else { + hypctx->tf.tf_spsr &= ~(PSR_I | PSR_F); + hypctx->tf.tf_spsr |= (hypctx->debug_spsr & + (PSR_I | PSR_F)); + hypctx->debug_spsr &= ~(PSR_I | PSR_F); + } + break; + default: + ret = ENOENT; + break; + } + + if (ret == 0) { + if (val == 0) + hypctx->setcaps &= ~(1ul << num); + else + hypctx->setcaps |= (1ul << num); + } + + return (ret); } diff --git a/sys/arm64/vmm/vmm_stat.c b/sys/arm64/vmm/vmm_stat.c index 858ce980843a..05ece6f30579 100644 --- a/sys/arm64/vmm/vmm_stat.c +++ b/sys/arm64/vmm/vmm_stat.c @@ -161,5 +161,7 @@ VMM_STAT(VMEXIT_INSN_ABORT, "number of vmexits for an instruction abort"); VMM_STAT(VMEXIT_UNHANDLED_SYNC, "number of vmexits for an unhandled synchronous exception"); VMM_STAT(VMEXIT_IRQ, "number of vmexits for an irq"); VMM_STAT(VMEXIT_FIQ, "number of vmexits for an interrupt"); +VMM_STAT(VMEXIT_BRK, "number of vmexits for a breakpoint exception"); +VMM_STAT(VMEXIT_SS, "number of vmexits for a single-step exception"); VMM_STAT(VMEXIT_UNHANDLED_EL2, "number of vmexits for an unhandled EL2 exception"); VMM_STAT(VMEXIT_UNHANDLED, "number of vmexits for an unhandled exception"); diff --git a/sys/arm64/vmm/vmm_stat.h b/sys/arm64/vmm/vmm_stat.h index b0a06ef79253..402fa2f1b1e4 100644 --- a/sys/arm64/vmm/vmm_stat.h +++ b/sys/arm64/vmm/vmm_stat.h @@ -140,6 +140,8 @@ VMM_STAT_DECLARE(VMEXIT_INSN_ABORT); VMM_STAT_DECLARE(VMEXIT_UNHANDLED_SYNC); VMM_STAT_DECLARE(VMEXIT_IRQ); VMM_STAT_DECLARE(VMEXIT_FIQ); +VMM_STAT_DECLARE(VMEXIT_BRK); +VMM_STAT_DECLARE(VMEXIT_SS); VMM_STAT_DECLARE(VMEXIT_UNHANDLED_EL2); VMM_STAT_DECLARE(VMEXIT_UNHANDLED); #endif