From nobody Fri Mar 29 18:11:51 2024 X-Original-To: dev-commits-src-branches@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 4V5pQK1Spcz5FNbg; Fri, 29 Mar 2024 18:11:53 +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 4V5pQJ4mw0z4h8V; Fri, 29 Mar 2024 18:11:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1711735912; 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=wOOhVPbZhNNlpGqZJEVYbagOgQDN0FIAK0s6i7YtO4E=; b=hd/HAXfxBGTBgfV49v7cdJY3WasKQLv9vCbjR1a5iKOIQgbaLjr+NEb4K0QU0e3R3rT8Hx tobsgw541qUQCZkfnbc+5juBCK6H1JhkKYMt5lZNZSf9zQjsd1TVpEs9A0oD9MDzGJqdC1 /2jIkimxOw1mV4gqgtcuHUh+KtV97rOsb4DOkALtTVB5dDwaDbgLehOIyDullSyHpH3THj B4D+thb57oAH2tv/77kbkcmnuqYOrqv/gJMvFdvURrS4JOBfyAcp3NtxqFiERP2vF/9KPP pNXpOjnNrMB9sOWPwmhliOMQ/oCLmuqka6jSWOVuN9CkuxonotgiOtlp3UrLZw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1711735912; a=rsa-sha256; cv=none; b=oAO3wauFj9nLvOE4Q5uurI6tFU/yQqlTK4WcEAt6jeKTg7TtMiuIzpo6Fe3xv7XcOD7MdD OfuNrNHG9onx7ycBAjP0qMfka+FTGgw+wFacN0xWhe7yTkjE7oeaXfDRxAz1s0xyK4zYqb RES4pDI8qvN2m6tZJhlXtjRAzpJfdL30RrwQWuqB3K9h853LfABIcjBPzAX8UMzycIb0Up rl6SdxnMoA01MRXaLGUJTc8tcXwhlar8tEzbH0OOA5zj+rqd5xlNR99Rpaiuo7yv9SUfuP kPGjlMESeXydNBIpGXjYkI4tdbDpAsWRkntWL2JDKjc7a9I8OySLwWnX+lvhiQ== 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=1711735912; 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=wOOhVPbZhNNlpGqZJEVYbagOgQDN0FIAK0s6i7YtO4E=; b=hg+n8dkHs3lPsWHOgfoF9ziPs7s9H4p68l2Cpuq5LSn69qhhQbtmCKJ7MAAEmMff7E3s9o lVg3awUU9B3W6e1nQ7sLn27o+hLSB9M9kTNnwqV64sbZYrSWIO3dCtW5wp7Xx7A4DsJgVB 4BVy2h9aBpZzILxr2CRMlDaVskdYR584viqc47yQW2E3iz+C1IQdcBJRob83Kt3z6iMKnq oT0Dv3FwVUbQRwT8ubzi3EnLZrg6X9FzPz5llNBWgUteZik8VqLEQdPxAT4nNLZQmAu3tp niuAZYIpwfaMwePh2hcZOGEMx0a8TWGjnkpdt5gNZe2t9Wc6qRB6+DTEIKsPZg== 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 4V5pQJ1cd7zM3H; Fri, 29 Mar 2024 18:11:52 +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 42TIBpZM078274; Fri, 29 Mar 2024 18:11:51 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 42TIBpFx078271; Fri, 29 Mar 2024 18:11:51 GMT (envelope-from git) Date: Fri, 29 Mar 2024 18:11:51 GMT Message-Id: <202403291811.42TIBpFx078271@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: 683947e13fb8 - stable/14 - bhyve: Add support for XML register definitions List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@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/stable/14 X-Git-Reftype: branch X-Git-Commit: 683947e13fb8fdf5bee443cedd1b916238619998 Auto-Submitted: auto-generated The branch stable/14 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=683947e13fb8fdf5bee443cedd1b916238619998 commit 683947e13fb8fdf5bee443cedd1b916238619998 Author: Mark Johnston AuthorDate: 2024-02-21 00:21:29 +0000 Commit: Mark Johnston CommitDate: 2024-03-29 13:53:05 +0000 bhyve: Add support for XML register definitions This is useful for exposing additional registers to debuggers. For instance, control registers are now available on amd64 when using gdb to debug a guest. The stub indicates support by including the string "qXfer:features:read+" in its feature list. The debugger queries for target descriptions by sending the query "qXfer:features:read:" followed by a file path. The XML definitions are copied from QEMU and installed to /usr/share/bhyve/gdb. Note that we currently don't handle the SIMD registers at all, since that's of somewhat limited utility (for me at least) and since that requires new ioctls to fetch the register values. Reviewed by: jhb MFC after: 2 weeks Sponsored by: Innovate UK Differential Revision: https://reviews.freebsd.org/D43666 (cherry picked from commit f81cdf24ba5436367377f7c8e8f51f6df2a75ca7) --- etc/mtree/BSD.usr.dist | 2 + usr.sbin/bhyve/Makefile | 1 + usr.sbin/bhyve/gdb.c | 106 ++++++++++++++++++++++++++- usr.sbin/bhyve/gdb/Makefile | 21 ++++++ usr.sbin/bhyve/gdb/amd64.xml | 165 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 294 insertions(+), 1 deletion(-) diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index a7738aaf6f78..0d43b657530b 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -184,6 +184,8 @@ atf tags=package=tests .. bhyve + gdb + .. kbdlayout .. .. diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile index b6cad38a6c39..c9d571daebbc 100644 --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -75,6 +75,7 @@ CFLAGS+= -DBHYVE_GDB .ifdef GDB_LOG CFLAGS+=-DGDB_LOG .endif +SUBDIR+= gdb .endif CFLAGS+=-I${.CURDIR} \ diff --git a/usr.sbin/bhyve/gdb.c b/usr.sbin/bhyve/gdb.c index 6bdfbc5e8536..2a075cd10ca6 100644 --- a/usr.sbin/bhyve/gdb.c +++ b/usr.sbin/bhyve/gdb.c @@ -35,6 +35,8 @@ #include #include #include +#include + #include #include #include @@ -64,6 +66,8 @@ #include "mem.h" #include "mevent.h" +#define _PATH_GDB_XML "/usr/share/bhyve/gdb" + /* * GDB_SIGNAL_* numbers are part of the GDB remote protocol. Most stops * use SIGTRAP. @@ -86,6 +90,7 @@ static cpuset_t vcpus_active, vcpus_suspended, vcpus_waiting; static pthread_mutex_t gdb_lock; static pthread_cond_t idle_vcpus; static bool first_stop, report_next_stop, swbreak_enabled; +static int xml_dfd = -1; /* * An I/O buffer contains 'capacity' bytes of room at 'data'. For a @@ -170,8 +175,25 @@ static const struct gdb_reg { { .id = VM_REG_GUEST_ES, .size = 4 }, { .id = VM_REG_GUEST_FS, .size = 4 }, { .id = VM_REG_GUEST_GS, .size = 4 }, + /* + * Registers past this point are not included in a reply to a 'g' query, + * to provide compatibility with debuggers that do not fetch a target + * description. The debugger can query them individually with 'p' if it + * knows about them. + */ +#define GDB_REG_FIRST_EXT VM_REG_GUEST_FS_BASE + { .id = VM_REG_GUEST_FS_BASE, .size = 8 }, + { .id = VM_REG_GUEST_GS_BASE, .size = 8 }, + { .id = VM_REG_GUEST_KGS_BASE, .size = 8 }, + { .id = VM_REG_GUEST_CR0, .size = 8 }, + { .id = VM_REG_GUEST_CR2, .size = 8 }, + { .id = VM_REG_GUEST_CR3, .size = 8 }, + { .id = VM_REG_GUEST_CR4, .size = 8 }, + { .id = VM_REG_GUEST_TPR, .size = 8 }, + { .id = VM_REG_GUEST_EFER, .size = 8 }, }; +#define GDB_LOG #ifdef GDB_LOG #include #include @@ -1030,9 +1052,13 @@ gdb_read_regs(void) send_error(errno); return; } + start_packet(); - for (size_t i = 0; i < nitems(gdb_regset); i++) + for (size_t i = 0; i < nitems(gdb_regset); i++) { + if (gdb_regset[i].id == GDB_REG_FIRST_EXT) + break; append_unsigned_native(regvals[i], gdb_regset[i].size); + } finish_packet(); } @@ -1520,6 +1546,7 @@ check_features(const uint8_t *data, size_t len) /* This is an arbitrary limit. */ append_string("PacketSize=4096"); append_string(";swbreak+"); + append_string(";qXfer:features:read+"); finish_packet(); } @@ -1591,6 +1618,71 @@ gdb_query(const uint8_t *data, size_t len) start_packet(); append_asciihex(buf); finish_packet(); + } else if (command_equals(data, len, "qXfer:features:read:")) { + struct stat sb; + const char *xml; + const uint8_t *pathend; + char buf[64], path[PATH_MAX]; + size_t xmllen; + unsigned int doff, dlen; + int fd; + + data += strlen("qXfer:features:read:"); + len -= strlen("qXfer:features:read:"); + + pathend = memchr(data, ':', len); + if (pathend == NULL || + (size_t)(pathend - data) >= sizeof(path) - 1) { + send_error(EINVAL); + return; + } + memcpy(path, data, pathend - data); + path[pathend - data] = '\0'; + data += (pathend - data) + 1; + len -= (pathend - data) + 1; + + if (len > sizeof(buf) - 1) { + send_error(EINVAL); + return; + } + memcpy(buf, data, len); + buf[len] = '\0'; + if (sscanf(buf, "%x,%x", &doff, &dlen) != 2) { + send_error(EINVAL); + return; + } + + fd = openat(xml_dfd, path, O_RDONLY | O_RESOLVE_BENEATH); + if (fd < 0) { + send_error(errno); + return; + } + if (fstat(fd, &sb) < 0) { + send_error(errno); + close(fd); + return; + } + xml = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (xml == MAP_FAILED) { + send_error(errno); + close(fd); + return; + } + close(fd); + xmllen = sb.st_size; + + start_packet(); + if (doff >= xmllen) { + append_char('l'); + } else if (doff + dlen >= xmllen) { + append_char('l'); + append_packet_data(xml + doff, xmllen - doff); + } else { + append_char('m'); + append_packet_data(xml + doff, dlen); + } + finish_packet(); + (void)munmap(__DECONST(void *, xml), xmllen); } else send_empty_response(); } @@ -1918,6 +2010,9 @@ limit_gdb_socket(int s) void init_gdb(struct vmctx *_ctx) { +#ifndef WITHOUT_CAPSICUM + cap_rights_t rights; +#endif int error, flags, optval, s; struct addrinfo hints; struct addrinfo *gdbaddr; @@ -1998,4 +2093,13 @@ init_gdb(struct vmctx *_ctx) gdb_active = true; freeaddrinfo(gdbaddr); free(sport); + + xml_dfd = open(_PATH_GDB_XML, O_DIRECTORY); + if (xml_dfd == -1) + err(1, "Failed to open gdb xml directory"); +#ifndef WITHOUT_CAPSICUM + cap_rights_init(&rights, CAP_FSTAT, CAP_LOOKUP, CAP_MMAP_R, CAP_PREAD); + if (caph_rights_limit(xml_dfd, &rights) == -1) + err(1, "cap_rights_init"); +#endif } diff --git a/usr.sbin/bhyve/gdb/Makefile b/usr.sbin/bhyve/gdb/Makefile new file mode 100644 index 000000000000..a444b0cc4c69 --- /dev/null +++ b/usr.sbin/bhyve/gdb/Makefile @@ -0,0 +1,21 @@ +PACKAGE= bhyve +FILESDIR= ${SHAREDIR}/bhyve/gdb + +FILES+= target.xml + +.if ${MACHINE_ARCH} == "amd64" +XMLARCH= i386:x86-64 +FILES+= amd64.xml +.endif + +target.xml: .PHONY + @echo "" > ${.TARGET} + @echo "" >> ${.TARGET} + @echo "" >> ${.TARGET} + @echo " ${XMLARCH}" >> ${.TARGET} +.for file in ${FILES:Ntarget.xml} + @echo " " >> ${.TARGET} +.endfor + @echo "" >> ${.TARGET} + +.include diff --git a/usr.sbin/bhyve/gdb/amd64.xml b/usr.sbin/bhyve/gdb/amd64.xml new file mode 100644 index 000000000000..15bd270120d8 --- /dev/null +++ b/usr.sbin/bhyve/gdb/amd64.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +