From 15fa1d047e03d3f123546d72f130c5ce4b278eba Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Wed, 15 Apr 2020 17:43:51 +0300 Subject: 12519 Targetdirs: remove left over /usr/4lib Reviewed by: Gergő Doma Reviewed by: Yuri Pankov Reviewed by: Andy Fiddaman Approved by: Robert Mustacchi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usr/src/man/man1/crle.1 | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'usr/src/man/man1') diff --git a/usr/src/man/man1/crle.1 b/usr/src/man/man1/crle.1 index ecab0fa618..c6dabcf56f 100644 --- a/usr/src/man/man1/crle.1 +++ b/usr/src/man/man1/crle.1 @@ -3,11 +3,10 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH CRLE 1 "Oct 6, 2008" +.TH CRLE 1 "Apr 15, 2020" .SH NAME crle \- configure runtime linking environment .SH SYNOPSIS -.LP .nf \fBcrle\fR [\fB-64\fR] [\fB-a\fR \fIname\fR] [\fB-A\fR \fIname\fR] [\fB-c\fR \fIconf\fR] [\fB-e\fR \fIenv\fR] [\fB-E\fR \fIenv\fR] [\fB-f\fR \fIflags\fR] [\fB-i\fR \fIname\fR] [\fB-I\fR \fIname\fR] [\fB-g\fR \fIname\fR] [\fB-G\fR \fIname\fR] @@ -15,7 +14,6 @@ crle \- configure runtime linking environment .fi .SH DESCRIPTION -.LP The \fBcrle\fR utility provides for the creation and display of a runtime linking configuration file. The configuration file is read and interpreted by the runtime linker, \fBld.so.1\fR(1), during process startup. The runtime @@ -182,7 +180,6 @@ alternate object is created in the directory specified by the preceding is created. The flags used by \fBdldump()\fR are specified using the \fB-f\fR option, or default to \fBRTLD_REL_RELATIVE\fR. .SH OPTIONS -.LP The following options are supported. .sp .ne 2 @@ -383,8 +380,8 @@ The default search paths for 32-bit \fBELF\fR objects are \fB/lib\fR followed by \fB/usr/lib\fR. For 64-bit \fBELF\fR objects, the default search paths are \fB/lib/64\fR followed by \fB/usr/lib/64\fR. .sp -The default search paths for \fBAOUT\fR objects are \fB/usr/4lib\fR, followed -by \fB/usr/lib\fR and finally \fB/usr/local/lib\fR. +The default search paths for \fBAOUT\fR objects are \fB/usr/lib\fR and +\fB/usr/local/lib\fR. .sp Use of this option \fBreplaces\fR the default search path. Therefore, a \fB-l\fR option is normally required to specify the original system default in @@ -502,7 +499,6 @@ the \fBLD_CONFIG\fR environment variable. An alternative configuration file can also be specified by recording the configuration file name in the application at the time the application is built. See the \fB-c\fR option of \fBld\fR(1). .SH EXAMPLES -.LP \fBExample 1 \fRExperimenting With a Temporary Configuration File .sp .LP @@ -792,12 +788,10 @@ together with a permanent preload object which becomes appended to the process environment definition. .SH EXIT STATUS -.LP The creation or display of a configuration file results in a \fB0\fR being returned. Otherwise, any error condition is accompanied with a diagnostic message and a non-zero value being returned. .SH NOTES -.LP The ability to tag an alternative application to use an application-specific configuration file, is possible if the original application contains one of the \fI\&.dynamic\fR tags \fBDT_FLAGS_1\fR or \fBDT_FEATURE_1\fR. Without these @@ -914,7 +908,6 @@ Audit library that is employed to \fBdldump\fR(3C) 64-bit objects. .RE .SH ENVIRONMENT VARIABLES -.LP There are no environment variables that are referenced by \fBcrle\fR. However, several environment variables affect the runtime linkers behavior in regard to the processing of configuration files that are created by \fBcrle\fR. @@ -969,7 +962,6 @@ Disable alternative object processing from a configuration file. .RE .SH ATTRIBUTES -.LP See \fBattributes\fR(5) for descriptions of the following attributes. .sp @@ -984,7 +976,6 @@ Interface Stability Committed .TE .SH SEE ALSO -.LP \fBfile\fR(1), \fBld\fR(1), \fBld.so.1\fR(1), \fBdldump\fR(3C), \fBtempnam\fR(3C), \fBattributes\fR(5) .sp -- cgit v1.2.3 From 9c3024a3457d2d1269be18124a1ac69e33000da7 Mon Sep 17 00:00:00 2001 From: Hans Rosenfeld Date: Tue, 15 Jan 2019 16:29:40 +0100 Subject: 12682 want mdb-bhyve module Portions contributed by: Andy Fiddaman Portions contributed by: John Levon Portions contributed by: Patrick Mooney Reviewed by: John Levon Approved by: Dan McDonald --- exception_lists/packaging | 2 + usr/src/cmd/bhyve/bhyverun.c | 30 +- usr/src/cmd/bhyve/bhyverun.h | 5 + usr/src/cmd/bhyve/gdb.c | 4 + usr/src/cmd/bhyve/spinup_ap.c | 4 + usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c | 2 + usr/src/cmd/mdb/common/mdb/mdb_cmds.c | 7 +- usr/src/cmd/mdb/common/mdb/mdb_create.c | 9 +- usr/src/cmd/mdb/common/mdb/mdb_fmt.c | 6 + usr/src/cmd/mdb/common/mdb/mdb_kproc.c | 3 +- usr/src/cmd/mdb/common/mdb/mdb_kvm.c | 2 + usr/src/cmd/mdb/common/mdb/mdb_main.c | 32 +- usr/src/cmd/mdb/common/mdb/mdb_rawfile.c | 4 + usr/src/cmd/mdb/common/mdb/mdb_target.c | 4 + usr/src/cmd/mdb/common/mdb/mdb_target.h | 13 +- usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile | 3 +- usr/src/cmd/mdb/i86pc/modules/unix/unix.c | 79 +- usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile | 3 +- usr/src/cmd/mdb/intel/Makefile.kmdb | 3 +- usr/src/cmd/mdb/intel/amd64/Makefile.kmdb | 5 +- usr/src/cmd/mdb/intel/amd64/mdb/Makefile | 17 +- usr/src/cmd/mdb/intel/kmdb/kaif.c | 34 +- usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c | 1 + usr/src/cmd/mdb/intel/mdb/kvm_ia32dep.c | 1 + usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c | 35 +- usr/src/cmd/mdb/intel/mdb/mdb_amd64util.h | 7 +- usr/src/cmd/mdb/intel/mdb/mdb_bhyve.c | 1461 ++++++++++++++++++++ usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c | 83 +- usr/src/cmd/mdb/intel/mdb/mdb_ia32util.h | 7 +- usr/src/cmd/mdb/intel/mdb/mdb_isautil.h | 7 +- usr/src/cmd/mdb/intel/mdb/mdb_kreg.h | 12 + usr/src/cmd/mdb/intel/mdb/mdb_x86util.c | 215 +++ usr/src/cmd/mdb/intel/mdb/mdb_x86util.h | 68 + usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c | 4 +- usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c | 6 +- usr/src/compat/freebsd/amd64/machine/specialreg.h | 1 + usr/src/lib/Makefile | 3 + usr/src/lib/libvmm/Makefile | 43 + usr/src/lib/libvmm/Makefile.com | 51 + usr/src/lib/libvmm/amd64/Makefile | 19 + usr/src/lib/libvmm/libvmm.c | 860 ++++++++++++ usr/src/lib/libvmm/libvmm.h | 122 ++ usr/src/lib/libvmm/mapfile-vers | 60 + usr/src/lib/libvmmapi/common/mapfile-vers | 2 + usr/src/lib/libvmmapi/common/vmmapi.c | 51 +- usr/src/lib/libvmmapi/common/vmmapi.h | 10 + usr/src/man/man1/mdb.1 | 26 +- usr/src/pkg/manifests/system-library-bhyve.mf | 1 + usr/src/uts/i86pc/io/vmm/vmm.c | 4 + usr/src/uts/intel/sys/controlregs.h | 22 +- usr/src/uts/intel/sys/debugreg.h | 7 + 51 files changed, 3273 insertions(+), 187 deletions(-) create mode 100644 usr/src/cmd/mdb/intel/mdb/mdb_bhyve.c create mode 100644 usr/src/cmd/mdb/intel/mdb/mdb_x86util.c create mode 100644 usr/src/cmd/mdb/intel/mdb/mdb_x86util.h create mode 100644 usr/src/lib/libvmm/Makefile create mode 100644 usr/src/lib/libvmm/Makefile.com create mode 100644 usr/src/lib/libvmm/amd64/Makefile create mode 100644 usr/src/lib/libvmm/libvmm.c create mode 100644 usr/src/lib/libvmm/libvmm.h create mode 100644 usr/src/lib/libvmm/mapfile-vers (limited to 'usr/src/man/man1') diff --git a/exception_lists/packaging b/exception_lists/packaging index 981eb8aa91..556a6012f6 100644 --- a/exception_lists/packaging +++ b/exception_lists/packaging @@ -819,8 +819,10 @@ usr/lib/libsff.so # # private bhyve files # +lib/amd64/libvmm.so i386 lib/amd64/libvmmapi.so i386 usr/include/libppt.h i386 +usr/include/libvmm.h i386 usr/include/vmmapi.h i386 usr/lib/amd64/libppt.so i386 usr/lib/libppt.so i386 diff --git a/usr/src/cmd/bhyve/bhyverun.c b/usr/src/cmd/bhyve/bhyverun.c index 928d2dc811..07489ad8d5 100644 --- a/usr/src/cmd/bhyve/bhyverun.c +++ b/usr/src/cmd/bhyve/bhyverun.c @@ -251,6 +251,9 @@ usage(int code) " -A: create ACPI tables\n" " -c: number of cpus and/or topology specification\n" " -C: include guest memory in core file\n" +#ifndef __FreeBSD__ + " -d: suspend cpu at boot\n" +#endif " -e: exit on unhandled I/O access\n" " -g: gdb port\n" " -h: help\n" @@ -500,8 +503,14 @@ fbsdrun_start_thread(void *param) return (NULL); } +#ifdef __FreeBSD__ void fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip) +#else +void +fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip, + bool suspend) +#endif { int error; @@ -519,6 +528,11 @@ fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip) CPU_SET_ATOMIC(newcpu, &cpumask); +#ifndef __FreeBSD__ + if (suspend) + (void) vm_suspend_cpu(ctx, newcpu); +#endif + /* * Set up the vmexit struct to allow execution to start * at the given RIP @@ -1057,6 +1071,9 @@ main(int argc, char *argv[]) int max_vcpus, mptgen, memflags; int rtc_localtime; bool gdb_stop; +#ifndef __FreeBSD__ + bool suspend = false; +#endif struct vmctx *ctx; uint64_t rip; size_t memsize; @@ -1078,7 +1095,7 @@ main(int argc, char *argv[]) #ifdef __FreeBSD__ optstr = "abehuwxACHIPSWYp:g:G:c:s:m:l:B:U:"; #else - optstr = "abehuwxACHIPSWYg:G:c:s:m:l:B:U:"; + optstr = "abdehuwxACHIPSWYg:G:c:s:m:l:B:U:"; #endif while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { @@ -1097,7 +1114,11 @@ main(int argc, char *argv[]) "configuration '%s'", optarg); } break; -#ifdef __FreeBSD__ +#ifndef __FreeBSD__ + case 'd': + suspend = true; + break; +#else case 'p': if (pincpu_parse(optarg) != 0) { errx(EX_USAGE, "invalid vcpu pinning " @@ -1331,8 +1352,11 @@ main(int argc, char *argv[]) /* * Add CPU 0 */ +#ifdef __FreeBSD__ fbsdrun_addcpu(ctx, BSP, BSP, rip); - +#else + fbsdrun_addcpu(ctx, BSP, BSP, rip, suspend); +#endif /* * Head off to the main event dispatch loop */ diff --git a/usr/src/cmd/bhyve/bhyverun.h b/usr/src/cmd/bhyve/bhyverun.h index 78b3f1111f..8df8e01a73 100644 --- a/usr/src/cmd/bhyve/bhyverun.h +++ b/usr/src/cmd/bhyve/bhyverun.h @@ -61,7 +61,12 @@ extern pthread_cond_t bcons_wait_done; void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len); void fbsdrun_set_capabilities(struct vmctx *ctx, int cpu); +#ifdef __FreeBSD__ void fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip); +#else +void fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip, + bool suspend); +#endif int fbsdrun_muxed(void); int fbsdrun_vmexit_on_hlt(void); int fbsdrun_vmexit_on_pause(void); diff --git a/usr/src/cmd/bhyve/gdb.c b/usr/src/cmd/bhyve/gdb.c index 20c2de1dec..71cb780544 100644 --- a/usr/src/cmd/bhyve/gdb.c +++ b/usr/src/cmd/bhyve/gdb.c @@ -75,7 +75,11 @@ static cpuset_t vcpus_active, vcpus_suspended, vcpus_waiting; static pthread_mutex_t gdb_lock; static pthread_cond_t idle_vcpus; static bool stop_pending, first_stop; +#ifdef __FreeBSD__ static int stepping_vcpu, stopped_vcpu; +#else +static int stepping_vcpu = -1, stopped_vcpu = -1; +#endif /* * An I/O buffer contains 'capacity' bytes of room at 'data'. For a diff --git a/usr/src/cmd/bhyve/spinup_ap.c b/usr/src/cmd/bhyve/spinup_ap.c index 7c4186f5ed..ecdd05694c 100644 --- a/usr/src/cmd/bhyve/spinup_ap.c +++ b/usr/src/cmd/bhyve/spinup_ap.c @@ -100,7 +100,11 @@ spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip) spinup_ap_realmode(ctx, newcpu, &rip); +#ifdef __FreeBSD__ fbsdrun_addcpu(ctx, vcpu, newcpu, rip); +#else + fbsdrun_addcpu(ctx, vcpu, newcpu, rip, false); +#endif return (newcpu); } diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c b/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c index 90fd098d1c..628503d179 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c @@ -286,6 +286,8 @@ kmt_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap) case (uintptr_t)MDB_TGT_AS_IO: return (set_errno(EINVAL)); case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: if ((asp = (struct as *)kmt_read_kas(t)) == NULL) return (-1); /* errno is set for us */ break; diff --git a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c index b7b15aa507..10c622443a 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c @@ -2090,7 +2090,7 @@ cmd_dis(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (opt_f) as = MDB_TGT_AS_FILE; else - as = MDB_TGT_AS_VIRT; + as = MDB_TGT_AS_VIRT_I; if (opt_w == FALSE) { n++; @@ -2635,8 +2635,9 @@ tgt_status(const mdb_tgt_status_t *tsp) return (DCMD_OK); if (tsp->st_pc != 0) { - if (mdb_dis_ins2str(mdb.m_disasm, mdb.m_target, MDB_TGT_AS_VIRT, - buf, sizeof (buf), tsp->st_pc) != tsp->st_pc) + if (mdb_dis_ins2str(mdb.m_disasm, mdb.m_target, + MDB_TGT_AS_VIRT_I, buf, sizeof (buf), tsp->st_pc) != + tsp->st_pc) format = "target stopped at:\n%-#16a%8T%s\n"; else format = "target stopped at %a:\n"; diff --git a/usr/src/cmd/mdb/common/mdb/mdb_create.c b/usr/src/cmd/mdb/common/mdb/mdb_create.c index ea30457ef0..86490bf825 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_create.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_create.c @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2018 Joyent, Inc. + */ #include #include @@ -51,6 +53,11 @@ mdb_create_builtin_tgts(void) if ((mp = mdb_module_load_builtin("mdb_raw")) != NULL) mp->mod_tgt_ctor = mdb_rawfile_tgt_create; + +#ifdef __amd64 + if ((mp = mdb_module_load_builtin("mdb_bhyve")) != NULL) + mp->mod_tgt_ctor = mdb_bhyve_tgt_create; +#endif } void diff --git a/usr/src/cmd/mdb/common/mdb/mdb_fmt.c b/usr/src/cmd/mdb/common/mdb/mdb_fmt.c index 662cf7bea5..6a745b2ac4 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_fmt.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_fmt.c @@ -411,6 +411,9 @@ fmt_instr(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt) char buf[BUFSIZ]; uintptr_t naddr; + if (as == MDB_TGT_AS_VIRT) + as = MDB_TGT_AS_VIRT_I; + while (cnt-- != 0) { naddr = mdb_dis_ins2str(mdb.m_disasm, t, as, buf, sizeof (buf), addr); @@ -431,6 +434,9 @@ fmt_dotinstr(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt) uintptr_t naddr; uint32_t i; + if (as == MDB_TGT_AS_VIRT) + as = MDB_TGT_AS_VIRT_I; + for (mdb_iob_clrflags(mdb.m_out, oflags); cnt-- != 0; addr = naddr) { if (mdb_tgt_aread(t, as, &i, sizeof (i), addr) != sizeof (i)) { warn("failed to read data from target"); diff --git a/usr/src/cmd/mdb/common/mdb/mdb_kproc.c b/usr/src/cmd/mdb/common/mdb/mdb_kproc.c index e13dcea53f..4eeb8ac708 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_kproc.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_kproc.c @@ -553,7 +553,8 @@ kp_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap) kp_data_t *kp = t->t_data; physaddr_t pa; - if (as != MDB_TGT_AS_VIRT) + if (as != MDB_TGT_AS_VIRT && as != MDB_TGT_AS_VIRT_I && + as != MDB_TGT_AS_VIRT_S) return (set_errno(EINVAL)); if ((pa = kvm_physaddr(kp->kp_cookie, kp->kp_as, va)) != -1ULL) { diff --git a/usr/src/cmd/mdb/common/mdb/mdb_kvm.c b/usr/src/cmd/mdb/common/mdb/mdb_kvm.c index fe280c05c7..27ca238ca9 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_kvm.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_kvm.c @@ -814,6 +814,8 @@ kt_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap) case (uintptr_t)MDB_TGT_AS_IO: return (set_errno(EINVAL)); case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: asp = kt->k_as; break; default: diff --git a/usr/src/cmd/mdb/common/mdb/mdb_main.c b/usr/src/cmd/mdb/common/mdb/mdb_main.c index eea4b5b60e..8747464328 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_main.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_main.c @@ -322,12 +322,13 @@ static void usage(int status) { mdb_iob_printf(mdb.m_err, "Usage: %s [-fkmuwyAFKMSUW] [+/-o option] " - "[-p pid] [-s dist] [-I path] [-L path]\n\t[-P prompt] " + "[-b VM] [-p pid] [-s dist] [-I path] [-L path]\n\t[-P prompt] " "[-R root] [-V dis-version] [-e expr] " "[object [core] | core | suffix]\n\n", mdb.m_pname); mdb_iob_puts(mdb.m_err, + "\t-b attach to specified bhyve VM\n" "\t-e evaluate expr and return status\n" "\t-f force raw file debugging mode\n" "\t-k force kernel debugging mode\n" @@ -405,6 +406,19 @@ identify_xvm_file(const char *file, int *longmode) } #endif /* __x86 */ +#ifndef __amd64 +/* + * There is no bhyve target in a 32bit x86 or any SPARC mdb. This dummy helps + * keep the code simpler. + */ +/*ARGSUSED*/ +static int +mdb_bhyve_tgt_create(mdb_tgt_t *t, int argc, const char *argv[]) +{ + return (set_errno(EINVAL)); +} +#endif + int main(int argc, char *argv[], char *envp[]) { @@ -424,6 +438,7 @@ main(int argc, char *argv[], char *envp[]) const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL; const char *eflag = NULL; int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0; + int bflag = 0; int ttylike; int longmode = 0; @@ -513,8 +528,12 @@ main(int argc, char *argv[], char *envp[]) while (optind < argc) { while ((c = getopt(argc, argv, - "e:fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) { + "be:fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) { switch (c) { + case 'b': + bflag++; + tgt_ctor = mdb_bhyve_tgt_create; + break; case 'e': if (eflag != NULL) { warn("-e already specified\n"); @@ -830,6 +849,15 @@ main(int argc, char *argv[], char *envp[]) if (fflag) goto tcreate; /* skip re-exec and just create target */ + /* bhyve: directly create target, or re-exec in case of 32bit */ + if (bflag) { +#ifndef __amd64 + goto reexec; +#else + goto tcreate; +#endif + } + /* * If we just have an object file name, and that file doesn't * exist, and it's a string of digits, infer it to be a diff --git a/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c b/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c index 086639de74..d21ad0f38a 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c @@ -143,6 +143,8 @@ rf_aread(mdb_tgt_t *t, mdb_tgt_as_t as, void *buf, { switch ((uintptr_t)as) { case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: case (uintptr_t)MDB_TGT_AS_PHYS: if (RF_CORE(t->t_data) != NULL) return (rf_read(RF_CORE(t->t_data), buf, len, addr)); @@ -160,6 +162,8 @@ rf_awrite(mdb_tgt_t *t, mdb_tgt_as_t as, const void *buf, { switch ((uintptr_t)as) { case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: case (uintptr_t)MDB_TGT_AS_PHYS: if (RF_CORE(t->t_data) != NULL) return (rf_write(RF_CORE(t->t_data), buf, len, addr)); diff --git a/usr/src/cmd/mdb/common/mdb/mdb_target.c b/usr/src/cmd/mdb/common/mdb/mdb_target.c index 17aef0aac1..e0ae29bd99 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_target.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_target.c @@ -398,6 +398,8 @@ mdb_tgt_aread(mdb_tgt_t *t, mdb_tgt_as_t as, switch ((uintptr_t)as) { case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: return (t->t_ops->t_vread(t, buf, n, addr)); case (uintptr_t)MDB_TGT_AS_PHYS: return (t->t_ops->t_pread(t, buf, n, addr)); @@ -421,6 +423,8 @@ mdb_tgt_awrite(mdb_tgt_t *t, mdb_tgt_as_t as, switch ((uintptr_t)as) { case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: return (t->t_ops->t_vwrite(t, buf, n, addr)); case (uintptr_t)MDB_TGT_AS_PHYS: return (t->t_ops->t_pwrite(t, buf, n, addr)); diff --git a/usr/src/cmd/mdb/common/mdb/mdb_target.h b/usr/src/cmd/mdb/common/mdb/mdb_target.h index c36b85e2f3..e385caa38e 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_target.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_target.h @@ -64,6 +64,9 @@ extern int mdb_kvm_tgt_create(mdb_tgt_t *, int, const char *[]); extern int mdb_proc_tgt_create(mdb_tgt_t *, int, const char *[]); extern int mdb_kproc_tgt_create(mdb_tgt_t *, int, const char *[]); extern int mdb_rawfile_tgt_create(mdb_tgt_t *, int, const char *[]); +#ifdef __amd64 +extern int mdb_bhyve_tgt_create(mdb_tgt_t *, int, const char *[]); +#endif #else extern int kmdb_kvm_create(mdb_tgt_t *, int, const char *[]); #endif @@ -139,10 +142,12 @@ typedef void * mdb_tgt_as_t; /* Opaque address space id */ typedef uint64_t mdb_tgt_addr_t; /* Generic unsigned address */ typedef uint64_t physaddr_t; /* Physical memory address */ -#define MDB_TGT_AS_VIRT ((mdb_tgt_as_t)-1L) /* Virtual address space */ -#define MDB_TGT_AS_PHYS ((mdb_tgt_as_t)-2L) /* Physical address space */ -#define MDB_TGT_AS_FILE ((mdb_tgt_as_t)-3L) /* Object file address space */ -#define MDB_TGT_AS_IO ((mdb_tgt_as_t)-4L) /* I/o address space */ +#define MDB_TGT_AS_VIRT ((mdb_tgt_as_t)-1L) /* Virtual address space: */ +#define MDB_TGT_AS_VIRT_I ((mdb_tgt_as_t)-2L) /* special case for code */ +#define MDB_TGT_AS_VIRT_S ((mdb_tgt_as_t)-3L) /* special case for stack */ +#define MDB_TGT_AS_PHYS ((mdb_tgt_as_t)-4L) /* Physical address space */ +#define MDB_TGT_AS_FILE ((mdb_tgt_as_t)-5L) /* Object file address space */ +#define MDB_TGT_AS_IO ((mdb_tgt_as_t)-6L) /* I/o address space */ extern ssize_t mdb_tgt_aread(mdb_tgt_t *, mdb_tgt_as_t, void *, size_t, mdb_tgt_addr_t); diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile b/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile index efcfad5375..54bc62a086 100644 --- a/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile +++ b/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile @@ -22,7 +22,7 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# Copyright 2018 Joyent, Inc. +# Copyright 2019 Joyent, Inc. MODULE = unix.so MDBTGT = kvm @@ -38,6 +38,7 @@ include ../../../../Makefile.module CPPFLAGS += -DMP -D_MACHDEP CPPFLAGS += -I../../../../common +CPPFLAGS += -I../../../../intel CPPFLAGS += -I$(SRC)/uts/i86pc CPPFLAGS += -I$(SRC)/uts/intel diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/unix.c b/usr/src/cmd/mdb/i86pc/modules/unix/unix.c index e91321b235..c3b7e809e4 100644 --- a/usr/src/cmd/mdb/i86pc/modules/unix/unix.c +++ b/usr/src/cmd/mdb/i86pc/modules/unix/unix.c @@ -20,11 +20,13 @@ */ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2018 Joyent, Inc. + * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. + * Copyright 2019 Joyent, Inc. */ #include #include +#include #include #include #include @@ -963,73 +965,24 @@ x86_featureset_dcmd(uintptr_t addr, uint_t flags, int argc, static int sysregs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - ulong_t cr0, cr2, cr3, cr4; + struct sysregs sregs = { 0 }; desctbr_t gdtr; + boolean_t longmode = B_FALSE; - static const mdb_bitmask_t cr0_flag_bits[] = { - { "PE", CR0_PE, CR0_PE }, - { "MP", CR0_MP, CR0_MP }, - { "EM", CR0_EM, CR0_EM }, - { "TS", CR0_TS, CR0_TS }, - { "ET", CR0_ET, CR0_ET }, - { "NE", CR0_NE, CR0_NE }, - { "WP", CR0_WP, CR0_WP }, - { "AM", CR0_AM, CR0_AM }, - { "NW", CR0_NW, CR0_NW }, - { "CD", CR0_CD, CR0_CD }, - { "PG", CR0_PG, CR0_PG }, - { NULL, 0, 0 } - }; - - static const mdb_bitmask_t cr3_flag_bits[] = { - { "PCD", CR3_PCD, CR3_PCD }, - { "PWT", CR3_PWT, CR3_PWT }, - { NULL, 0, 0, } - }; - - static const mdb_bitmask_t cr4_flag_bits[] = { - { "VME", CR4_VME, CR4_VME }, - { "PVI", CR4_PVI, CR4_PVI }, - { "TSD", CR4_TSD, CR4_TSD }, - { "DE", CR4_DE, CR4_DE }, - { "PSE", CR4_PSE, CR4_PSE }, - { "PAE", CR4_PAE, CR4_PAE }, - { "MCE", CR4_MCE, CR4_MCE }, - { "PGE", CR4_PGE, CR4_PGE }, - { "PCE", CR4_PCE, CR4_PCE }, - { "OSFXSR", CR4_OSFXSR, CR4_OSFXSR }, - { "OSXMMEXCPT", CR4_OSXMMEXCPT, CR4_OSXMMEXCPT }, - { "VMXE", CR4_VMXE, CR4_VMXE }, - { "SMXE", CR4_SMXE, CR4_SMXE }, - { "PCIDE", CR4_PCIDE, CR4_PCIDE }, - { "OSXSAVE", CR4_OSXSAVE, CR4_OSXSAVE }, - { "SMEP", CR4_SMEP, CR4_SMEP }, - { "SMAP", CR4_SMAP, CR4_SMAP }, - { NULL, 0, 0 } - }; - - cr0 = kmdb_unix_getcr0(); - cr2 = kmdb_unix_getcr2(); - cr3 = kmdb_unix_getcr3(); - cr4 = kmdb_unix_getcr4(); - - kmdb_unix_getgdtr(&gdtr); +#ifdef __amd64 + longmode = B_TRUE; +#endif - mdb_printf("%%cr0 = 0x%lx <%b>\n", cr0, cr0, cr0_flag_bits); - mdb_printf("%%cr2 = 0x%lx <%a>\n", cr2, cr2); + sregs.sr_cr0 = kmdb_unix_getcr0(); + sregs.sr_cr2 = kmdb_unix_getcr2(); + sregs.sr_cr3 = kmdb_unix_getcr3(); + sregs.sr_cr4 = kmdb_unix_getcr4(); - if ((cr4 & CR4_PCIDE)) { - mdb_printf("%%cr3 = 0x%lx \n", cr3, - cr3 >> MMU_PAGESHIFT, cr3 & MMU_PAGEOFFSET); - } else { - mdb_printf("%%cr3 = 0x%lx \n", cr3, - cr3 >> MMU_PAGESHIFT, cr3, cr3_flag_bits); - } - - mdb_printf("%%cr4 = 0x%lx <%b>\n", cr4, cr4, cr4_flag_bits); + kmdb_unix_getgdtr(&gdtr); + sregs.sr_gdtr.d_base = gdtr.dtr_base; + sregs.sr_gdtr.d_lim = gdtr.dtr_limit; - mdb_printf("%%gdtr.base = 0x%lx, %%gdtr.limit = 0x%hx\n", - gdtr.dtr_base, gdtr.dtr_limit); + mdb_x86_print_sysregs(&sregs, longmode); return (DCMD_OK); } diff --git a/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile b/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile index 32c1fe33fd..5854a1610e 100644 --- a/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile +++ b/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile @@ -22,7 +22,7 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# Copyright 2018 Joyent, Inc. +# Copyright 2019 Joyent, Inc. MODULE = unix.so MDBTGT = kvm @@ -40,6 +40,7 @@ MODSRCS_DIR = ../../../../i86pc/modules/unix/ CPPFLAGS += -DMP -D_MACHDEP -D__xpv CPPFLAGS += -I../../../../common +CPPFLAGS += -I../../../../intel CPPFLAGS += -I$(SRC)/uts/common CPPFLAGS += -I$(SRC)/uts/i86xpv CPPFLAGS += -I$(SRC)/uts/i86pc diff --git a/usr/src/cmd/mdb/intel/Makefile.kmdb b/usr/src/cmd/mdb/intel/Makefile.kmdb index 1e9efcbc83..6151a2e46a 100644 --- a/usr/src/cmd/mdb/intel/Makefile.kmdb +++ b/usr/src/cmd/mdb/intel/Makefile.kmdb @@ -22,7 +22,7 @@ # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# Copyright 2019, Joyent, Inc. +# Copyright 2019 Joyent, Inc. # PROMSRCS += \ @@ -68,6 +68,7 @@ KMDBLIBS = $(STANDLIBS) ../mdb_ks/kmod/mdb_ks MAPFILE_SOURCES = \ $(MAPFILE_SOURCES_COMMON) \ ../../kmdb/kmdb_dpi_isadep.h \ + ../../mdb/mdb_x86util.h \ $(MAPFILE_SOURCES_$(MACH)) %.o: ../../../../../uts/intel/promif/%.c diff --git a/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb b/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb index 61cf1541a2..8cee9ff049 100644 --- a/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb +++ b/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb @@ -22,6 +22,8 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2019 Joyent, Inc. +# KMDBML += \ kaif_invoke.s \ @@ -29,6 +31,7 @@ KMDBML += \ KMDBSRCS += \ kmdb_makecontext.c \ - mdb_amd64util.c + mdb_amd64util.c \ + mdb_x86util.c SACPPFLAGS = -D__$(MACH64) -U__$(MACH) diff --git a/usr/src/cmd/mdb/intel/amd64/mdb/Makefile b/usr/src/cmd/mdb/intel/amd64/mdb/Makefile index 3dfa7a34d5..918aa71ea1 100644 --- a/usr/src/cmd/mdb/intel/amd64/mdb/Makefile +++ b/usr/src/cmd/mdb/intel/amd64/mdb/Makefile @@ -22,10 +22,15 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2019 Joyent, Inc. +# SRCS = kvm_amd64dep.c \ kvm_isadep.c \ mdb_amd64util.c \ + mdb_ia32util.c \ + mdb_x86util.c \ + mdb_bhyve.c \ proc_amd64dep.c %.o: %.c @@ -42,12 +47,14 @@ SRCS = kvm_amd64dep.c \ %.ln: ../../mdb/%.c $(LINT.c) -c $< -include ../../../../Makefile.cmd -include ../../../../Makefile.cmd.64 -include ../../Makefile.amd64 -include ../../../Makefile.mdb +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.cmd.64 +include $(SRC)/cmd/mdb/intel/Makefile.amd64 +include $(SRC)/cmd/mdb/Makefile.mdb +include $(SRC)/Makefile.psm CPPFLAGS += -I../../mdb -LDLIBS += -lsaveargs + +LDLIBS += -lsaveargs -lvmm install: all $(ISAEXEC) $(ROOTPROG64) $(ROOTLINK64) diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif.c b/usr/src/cmd/mdb/intel/kmdb/kaif.c index 39cc9b620a..e4f80ad228 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kaif.c +++ b/usr/src/cmd/mdb/intel/kmdb/kaif.c @@ -296,12 +296,12 @@ kaif_brkpt_arm(uintptr_t addr, mdb_instr_t *instrp) return (set_errno(EMDB_TGTNOTSUP)); } - if (mdb_tgt_vread(mdb.m_target, instrp, sizeof (mdb_instr_t), addr) != - sizeof (mdb_instr_t)) + if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_I, instrp, + sizeof (mdb_instr_t), addr) != sizeof (mdb_instr_t)) return (-1); /* errno is set for us */ - if (mdb_tgt_vwrite(mdb.m_target, &bkpt, sizeof (mdb_instr_t), addr) != - sizeof (mdb_instr_t)) + if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_I, &bkpt, + sizeof (mdb_instr_t), addr) != sizeof (mdb_instr_t)) return (-1); /* errno is set for us */ return (0); @@ -310,8 +310,8 @@ kaif_brkpt_arm(uintptr_t addr, mdb_instr_t *instrp) static int kaif_brkpt_disarm(uintptr_t addr, mdb_instr_t instrp) { - if (mdb_tgt_vwrite(mdb.m_target, &instrp, sizeof (mdb_instr_t), addr) != - sizeof (mdb_instr_t)) + if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_I, &instrp, + sizeof (mdb_instr_t), addr) != sizeof (mdb_instr_t)) return (-1); /* errno is set for us */ return (0); @@ -486,7 +486,7 @@ kaif_step(void) } if ((npc = mdb_dis_nextins(mdb.m_disasm, mdb.m_target, - MDB_TGT_AS_VIRT, pc)) == pc) { + MDB_TGT_AS_VIRT_I, pc)) == pc) { warn("failed to decode instruction at %a for step\n", pc); return (set_errno(EINVAL)); } @@ -498,8 +498,8 @@ kaif_step(void) * versus their 64-bit counterparts. */ do { - if (mdb_tgt_vread(mdb.m_target, &instr, sizeof (mdb_instr_t), - pc + pcoff) != sizeof (mdb_instr_t)) { + if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_I, &instr, + sizeof (mdb_instr_t), pc + pcoff) != sizeof (mdb_instr_t)) { warn("failed to read at %p for step", (void *)(pc + pcoff)); return (-1); @@ -518,8 +518,8 @@ kaif_step(void) return (set_errno(EMDB_TGTNOTSUP)); case M_ESC: - if (mdb_tgt_vread(mdb.m_target, &instr, sizeof (mdb_instr_t), - pc + pcoff) != sizeof (mdb_instr_t)) { + if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_I, &instr, + sizeof (mdb_instr_t), pc + pcoff) != sizeof (mdb_instr_t)) { warn("failed to read at %p for step", (void *)(pc + pcoff)); return (-1); @@ -568,8 +568,8 @@ kaif_step(void) (void) kmdb_dpi_get_register("sp", &sp); (void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl); - if (mdb_tgt_vread(mdb.m_target, &newfl, sizeof (kreg_t), - sp) != sizeof (kreg_t)) { + if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_S, &newfl, + sizeof (kreg_t), sp) != sizeof (kreg_t)) { warn("failed to read " FLAGS_REG_NAME " at %p for popfl step\n", (void *)sp); return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */ @@ -577,8 +577,8 @@ kaif_step(void) fl = (fl & ~KREG_EFLAGS_IF_MASK) | KREG_EFLAGS_TF_MASK; - if (mdb_tgt_vwrite(mdb.m_target, &fl, sizeof (kreg_t), - sp) != sizeof (kreg_t)) { + if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_S, &fl, + sizeof (kreg_t), sp) != sizeof (kreg_t)) { warn("failed to update " FLAGS_REG_NAME " at %p for popfl step\n", (void *)sp); return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */ @@ -617,8 +617,8 @@ kaif_step(void) */ (void) kmdb_dpi_get_register("sp", &sp); - if (mdb_tgt_vwrite(mdb.m_target, &oldfl, sizeof (kreg_t), - sp) != sizeof (kreg_t)) { + if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_S, &oldfl, + sizeof (kreg_t), sp) != sizeof (kreg_t)) { warn("failed to update pushed " FLAGS_REG_NAME " at %p after pushfl step\n", (void *)sp); return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */ diff --git a/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c b/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c index f3352b6e21..0382c7e0fb 100644 --- a/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c +++ b/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include diff --git a/usr/src/cmd/mdb/intel/mdb/kvm_ia32dep.c b/usr/src/cmd/mdb/intel/mdb/kvm_ia32dep.c index 2dfced82d3..7a6ecaeb6b 100644 --- a/usr/src/cmd/mdb/intel/mdb/kvm_ia32dep.c +++ b/usr/src/cmd/mdb/intel/mdb/kvm_ia32dep.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c index 14c81f47fd..7740a82d8f 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c +++ b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -244,7 +245,8 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, while (fp != 0) { int args_style = 0; - if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) != sizeof (fr)) { + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &fr, sizeof (fr), fp) != + sizeof (fr)) { err = EMDB_NOMAP; goto badfp; } @@ -259,8 +261,9 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, if (advance_tortoise != 0) { struct fr tfr; - if (mdb_tgt_vread(t, &tfr, sizeof (tfr), - tortoise_fp) != sizeof (tfr)) { + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &tfr, + sizeof (tfr), tortoise_fp) != + sizeof (tfr)) { err = EMDB_NOMAP; goto badfp; } @@ -330,7 +333,8 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, insnsize = MIN(MIN(s.st_size, SAVEARGS_INSN_SEQ_LEN), pc - s.st_value); - if (mdb_tgt_vread(t, ins, insnsize, s.st_value) != insnsize) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, ins, insnsize, + s.st_value) != insnsize) argc = 0; if ((argc != 0) && @@ -349,8 +353,8 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, if (args_style == SAVEARGS_STRUCT_ARGS) size += sizeof (long); - if (mdb_tgt_vread(t, fr_argv, size, (fp - size)) - != size) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, fr_argv, size, + (fp - size)) != size) return (-1); /* errno has been set for us */ /* @@ -369,7 +373,8 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, sizeof (fr_argv) - (reg_argc * sizeof (long))); - if (mdb_tgt_vread(t, &fr_argv[reg_argc], size, + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, + &fr_argv[reg_argc], size, fp + sizeof (fr)) != size) return (-1); /* errno has been set */ } @@ -434,14 +439,15 @@ mdb_amd64_step_out(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, kreg_t fp, kreg_t sp, if (pc == s.st_value && curinstr == M_PUSHQ_RBP) fp = sp - 8; else if (pc == s.st_value + 1 && curinstr == M_REX_W) { - if (mdb_tgt_vread(t, &curinstr, sizeof (curinstr), - pc + 1) == sizeof (curinstr) && curinstr == - M_MOVL_RBP) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &curinstr, + sizeof (curinstr), pc + 1) == sizeof (curinstr) && + curinstr == M_MOVL_RBP) fp = sp; } } - if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) == sizeof (fr)) { + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &fr, sizeof (fr), fp) == + sizeof (fr)) { *p = fr.fr_savpc; return (0); } @@ -476,8 +482,8 @@ mdb_amd64_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr) /* Skip the rex prefix, if any */ callpc = pc; while (curinstr >= M_REX_LO && curinstr <= M_REX_HI) { - if (mdb_tgt_vread(t, &curinstr, sizeof (curinstr), ++callpc) != - sizeof (curinstr)) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &curinstr, + sizeof (curinstr), ++callpc) != sizeof (curinstr)) return (-1); /* errno is set for us */ } @@ -486,7 +492,8 @@ mdb_amd64_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr) return (set_errno(EAGAIN)); } - if ((npc = mdb_dis_nextins(mdb.m_disasm, t, MDB_TGT_AS_VIRT, pc)) == pc) + npc = mdb_dis_nextins(mdb.m_disasm, t, MDB_TGT_AS_VIRT_I, pc); + if (npc == pc) return (-1); /* errno is set for us */ *p = npc; diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.h b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.h index f8c6097cef..b3f060bf05 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.h +++ b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.h @@ -22,12 +22,13 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2018, Joyent, Inc. All rights reserved. + */ #ifndef _MDB_AMD64UTIL_H #define _MDB_AMD64UTIL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include @@ -35,8 +36,6 @@ extern "C" { #endif -typedef uchar_t mdb_instr_t; - extern const mdb_tgt_regdesc_t mdb_amd64_kregs[]; extern void mdb_amd64_printregs(const mdb_tgt_gregset_t *); diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_bhyve.c b/usr/src/cmd/mdb/intel/mdb/mdb_bhyve.c new file mode 100644 index 0000000000..9477bf5056 --- /dev/null +++ b/usr/src/cmd/mdb/intel/mdb/mdb_bhyve.c @@ -0,0 +1,1461 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +/* + * bhyve target + * + * The bhyve target is used to examine and manipulate a bhyve VM. Access to + * a bhyve VM is provided by libvmm, which itself uses libvmmapi, which uses + * the vmm driver's ioctl interface to carry out requests. + * + * The bhyve target does not know about threads or processes, but it handles + * multiple vCPUs and can switch between them. Execution control is currently + * limited to completely stopping or resuming all vCPUs of a VM, or single- + * stepping a particular vCPU while all other vCPUs remain stopped. Breakpoints + * are not implemented yet, and as such step-out and step-over don't work yet. + * All known x86 instruction sets are support, legacy IA-16, IA-32 and AMD64. + * The current CPU instruction set is automatically determined by parsing the + * code segment (CS) attributes in the current vCPU. + * + * All of the VMs physical memory and device memory segments are mapped R/W + * into mdb's address space by libvmm. All accesses to those memory are + * facilitated through libvmm calls, which may include virtual address + * translation according to the current vCPU mode. Both real-mode and protected- + * mode segmentation are understood and used for translating virtual addresses + * into linear addresses, which may further be translated using 2-level, 3-level + * or 4-level paging. + * + * To handle disassembly and stack tracing properly when segmentation is used by + * a vCPU (always in real mode, sometimes in protected mode) the bhyve target + * has a notion of three virtual address spaces used for reading/writing memory: + * - MDB_TGT_AS_VIRT, the default virtual address space uses the DS segment + * by default, but this default can be changed with the ::defseg dcmd. + * - MDB_TGT_AS_VIRT_I, the virtual address space for instructions always + * uses the code segment (CS) for translation + * - MDB_TGT_AS_VIRT_S, the virtual address space for the stack always uses + * the stack segment (SS) for translation + * + * Register printing and stack tracing is using the common x86 ISA-specific code + * in IA-32 and AMD64 modes. There is no stack tracing for IA-16 mode yet. + * + * Todo: + * - support for breakpoint, step-out, and step-over + * - support for x86 stack tracing + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define MDB_DEF_PROMPT "[%<_cpuid>]> " + +typedef struct bhyve_data { + vmm_t *bd_vmm; + uint_t bd_curcpu; + int bd_defseg; + + /* must be last */ + char bd_name[]; +} bhyve_data_t; + + +const mdb_tgt_regdesc_t bhyve_kregs[] = { + { "rdi", KREG_RDI, MDB_TGT_R_EXPORT }, + { "edi", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "di", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "dil", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rsi", KREG_RSI, MDB_TGT_R_EXPORT }, + { "esi", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "si", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "sil", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rdx", KREG_RDX, MDB_TGT_R_EXPORT }, + { "edx", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "dx", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "dh", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "dl", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rcx", KREG_RCX, MDB_TGT_R_EXPORT }, + { "ecx", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "cx", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ch", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "cl", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r8", KREG_R8, MDB_TGT_R_EXPORT }, + { "r8d", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r8w", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r8l", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r9", KREG_R9, MDB_TGT_R_EXPORT }, + { "r9d", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r9w", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r9l", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rax", KREG_RAX, MDB_TGT_R_EXPORT }, + { "eax", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "ax", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ah", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "al", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rbx", KREG_RBX, MDB_TGT_R_EXPORT }, + { "ebx", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "bx", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "bh", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "bl", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rbp", KREG_RBP, MDB_TGT_R_EXPORT }, + { "ebp", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "bp", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "bpl", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r10", KREG_R10, MDB_TGT_R_EXPORT }, + { "r10d", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r10w", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r10l", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r11", KREG_R11, MDB_TGT_R_EXPORT }, + { "r11d", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r11w", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r11l", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r12", KREG_R12, MDB_TGT_R_EXPORT }, + { "r12d", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r12w", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r12l", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r13", KREG_R13, MDB_TGT_R_EXPORT }, + { "r13d", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r13w", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r13l", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r14", KREG_R14, MDB_TGT_R_EXPORT }, + { "r14d", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r14w", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r14l", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r15", KREG_R15, MDB_TGT_R_EXPORT }, + { "r15d", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r15w", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r15l", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "ds", KREG_DS, MDB_TGT_R_EXPORT }, + { "es", KREG_ES, MDB_TGT_R_EXPORT }, + { "fs", KREG_FS, MDB_TGT_R_EXPORT }, + { "gs", KREG_GS, MDB_TGT_R_EXPORT }, + { "rip", KREG_RIP, MDB_TGT_R_EXPORT }, + { "cs", KREG_CS, MDB_TGT_R_EXPORT }, + { "rflags", KREG_RFLAGS, MDB_TGT_R_EXPORT }, + { "eflags", KREG_RFLAGS, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "rsp", KREG_RSP, MDB_TGT_R_EXPORT }, + { "esp", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "sp", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "spl", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "ss", KREG_SS, MDB_TGT_R_EXPORT }, + { "cr2", KREG_CR2, MDB_TGT_R_EXPORT }, + { "cr3", KREG_CR3, MDB_TGT_R_EXPORT }, + { NULL, 0, 0 } +}; + +static const char *segments[] = { "CS", "DS", "ES", "FS", "GS", "SS" }; + + +/*ARGSUSED*/ +static uintmax_t +bhyve_cpuid_get(const mdb_var_t *v) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + + return (bd->bd_curcpu); +} + +static const mdb_nv_disc_t bhyve_cpuid_disc = { + .disc_get = bhyve_cpuid_get +}; + + +static uintmax_t +bhyve_reg_get(const mdb_var_t *v) +{ + mdb_tgt_reg_t r = 0; + + if (mdb_tgt_getareg(MDB_NV_COOKIE(v), 0, mdb_nv_get_name(v), &r) == -1) + mdb_warn("failed to get %%%s register", mdb_nv_get_name(v)); + + return (r); +} + +static void +bhyve_reg_set(mdb_var_t *v, uintmax_t r) +{ + if (mdb_tgt_putareg(MDB_NV_COOKIE(v), 0, mdb_nv_get_name(v), r) == -1) + mdb_warn("failed to modify %%%s register", mdb_nv_get_name(v)); +} + +static const mdb_nv_disc_t bhyve_reg_disc = { + .disc_set = bhyve_reg_set, + .disc_get = bhyve_reg_get +}; + +static int +bhyve_get_gregset(bhyve_data_t *bd, int cpu, mdb_tgt_gregset_t *gregs) +{ + vmm_desc_t fs, gs; + + /* + * Register numbers to get, the order must match the definitions of + * KREG_* in mdb_kreg.h so that we get a proper mdb_tgt_gregset_t + * that the register printing functions will understand. + * + * There are a few fields in mdb_tgt_gregset_t that can't be accessed + * with vmm_get_regset(), either because they don't exist in bhyve or + * or because they need to be accessed with vmm_get_desc(). For these + * cases we ask for RAX instead and fill it with 0 or the real value, + * respectively. + */ + static const int regnums[] = { + KREG_RAX, /* dummy for SAVFP */ + KREG_RAX, /* dummy for SAVFP */ + KREG_RDI, + KREG_RSI, + KREG_RDX, + KREG_RCX, + KREG_R8, + KREG_R9, + KREG_RAX, + KREG_RBX, + KREG_RBP, + KREG_R10, + KREG_R11, + KREG_R12, + KREG_R13, + KREG_R14, + KREG_R15, + KREG_RAX, /* dummy for FSBASE */ + KREG_RAX, /* dummy for GSBASE */ + KREG_RAX, /* dummy for KGSBASE */ + KREG_CR2, + KREG_CR3, + KREG_DS, + KREG_ES, + KREG_FS, + KREG_GS, + KREG_RAX, /* dummy for TRAPNO */ + KREG_RAX, /* dummy for ERR */ + KREG_RIP, + KREG_CS, + KREG_RFLAGS, + KREG_RSP, + KREG_SS + }; + + if (vmm_get_regset(bd->bd_vmm, cpu, KREG_NGREG, regnums, + &gregs->kregs[0]) != 0) { + mdb_warn("failed to get general-purpose registers for CPU %d", + cpu); + return (-1); + } + + if (vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_FS, &fs) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_GS, &gs) != 0) { + mdb_warn("failed to get FS/GS descriptors for CPU %d", cpu); + return (-1); + } + + gregs->kregs[KREG_SAVFP] = 0; + gregs->kregs[KREG_SAVPC] = 0; + gregs->kregs[KREG_KGSBASE] = 0; + gregs->kregs[KREG_TRAPNO] = 0; + gregs->kregs[KREG_ERR] = 0; + + gregs->kregs[KREG_FSBASE] = fs.vd_base; + gregs->kregs[KREG_GSBASE] = gs.vd_base; + + return (0); +} + +static int +bhyve_cpuregs_dcmd(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + uint64_t cpu = bd->bd_curcpu; + mdb_tgt_gregset_t gregs; + int i; + + + if (flags & DCMD_ADDRSPEC) { + if (argc != 0) + return (DCMD_USAGE); + + cpu = (uint64_t)addr; + } + + i = mdb_getopts(argc, argv, 'c', MDB_OPT_UINT64, &cpu, NULL); + + argc -= i; + argv += i; + + if (argc != 0) + return (DCMD_USAGE); + + if (cpu >= vmm_ncpu(bd->bd_vmm)) { + mdb_warn("no such CPU\n"); + return (DCMD_ERR); + } + + if (bhyve_get_gregset(bd, cpu, &gregs) != 0) + return (DCMD_ERR); + + + switch (vmm_vcpu_isa(bd->bd_vmm, cpu)) { + case VMM_ISA_64: + mdb_amd64_printregs(&gregs); + break; + case VMM_ISA_32: + case VMM_ISA_16: + mdb_ia32_printregs(&gregs); + break; + default: + mdb_warn("CPU %d mode unknown", cpu); + return (DCMD_ERR); + } + + return (0); +} + +static int +bhyve_regs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + if ((flags & DCMD_ADDRSPEC) || argc != 0) + return (DCMD_USAGE); + + return (bhyve_cpuregs_dcmd(addr, flags, argc, argv)); +} + +static int +bhyve_stack_common(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv, int vcpu, boolean_t verbose) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + void *arg = (void *)(uintptr_t)mdb.m_nargs; + + mdb_tgt_gregset_t gregs; + mdb_tgt_stack_f *func; + + if (vcpu == -1) + vcpu = bd->bd_curcpu; + + if (flags & DCMD_ADDRSPEC) { + bzero(&gregs, sizeof (gregs)); + gregs.kregs[KREG_RBP] = addr; + } else if (bhyve_get_gregset(bd, vcpu, &gregs) != 0) + return (DCMD_ERR); + + switch (vmm_vcpu_isa(bd->bd_vmm, vcpu)) { + case VMM_ISA_64: + func = verbose ? mdb_amd64_kvm_framev : mdb_amd64_kvm_frame; + (void) mdb_amd64_kvm_stack_iter(mdb.m_target, &gregs, func, + arg); + break; + case VMM_ISA_32: + func = verbose ? mdb_ia32_kvm_framev : mdb_amd64_kvm_frame; + (void) mdb_ia32_kvm_stack_iter(mdb.m_target, &gregs, func, arg); + break; + case VMM_ISA_16: + mdb_warn("IA16 stack tracing not implemented\n"); + return (DCMD_ERR); + default: + mdb_warn("CPU %d mode unknown", vcpu); + return (DCMD_ERR); + } + + return (DCMD_OK); +} + +static int +bhyve_cpustack_dcmd(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + uint64_t cpu = bd->bd_curcpu; + boolean_t verbose; + int i; + + if (flags & DCMD_ADDRSPEC) { + if (argc != 0) + return (DCMD_USAGE); + + if (addr < vmm_ncpu(bd->bd_vmm)) { + cpu = (uint64_t)addr; + flags &= ~DCMD_ADDRSPEC; + } + } + + i = mdb_getopts(argc, argv, + 'c', MDB_OPT_UINT64, &cpu, + 'v', MDB_OPT_SETBITS, 1, &verbose, + NULL); + + argc -= i; + argv += i; + + if (argc != 0) + return (DCMD_USAGE); + + return (bhyve_stack_common(addr, flags, argc, argv, cpu, verbose)); +} + +static int +bhyve_stack_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + return (bhyve_stack_common(addr, flags, argc, argv, -1, B_FALSE)); +} + +static int +bhyve_stackv_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + return (bhyve_stack_common(addr, flags, argc, argv, -1, B_TRUE)); +} + +static int +bhyve_stackr_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + return (bhyve_stack_common(addr, flags, argc, argv, -1, B_TRUE)); +} + +static int +bhyve_status_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + vmm_mode_t mode; + vmm_isa_t isa; + + static const char *modes[] = { + "unknown mode", + "real mode", + "protected mode, no PAE", + "protected mode, PAE", + "long mode" + }; + static const char *isas[] = { + "unknown ISA", + "IA16", + "IA32", + "AMD64" + }; + + if ((flags & DCMD_ADDRSPEC) || argc != 0) + return (DCMD_USAGE); + + mode = vmm_vcpu_mode(bd->bd_vmm, bd->bd_curcpu); + isa = vmm_vcpu_isa(bd->bd_vmm, bd->bd_curcpu); + + mdb_printf("debugging live VM '%s'\n", bd->bd_name); + mdb_printf("VM memory size: %d MB\n", + vmm_memsize(bd->bd_vmm) / 1024 / 1024); + mdb_printf("vCPUs: %d\n", vmm_ncpu(bd->bd_vmm)); + mdb_printf("current CPU: %d (%s, %s)\n", bd->bd_curcpu, modes[mode], + isas[isa]); + mdb_printf("default segment: %s", + segments[bd->bd_defseg - VMM_DESC_CS]); + + return (DCMD_OK); +} + + +static int +bhyve_sysregs_dcmd(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + uint64_t cpu = bd->bd_curcpu; + int ret = DCMD_ERR; + struct sysregs sregs; + int i; + + /* + * This array must use the order of the elements of struct sysregs. + */ + static const int regnums[] = { + VMM_REG_CR0, + VMM_REG_CR2, + VMM_REG_CR3, + VMM_REG_CR4, + VMM_REG_DR0, + VMM_REG_DR1, + VMM_REG_DR2, + VMM_REG_DR3, + VMM_REG_DR6, + VMM_REG_DR7, + VMM_REG_EFER, + VMM_REG_PDPTE0, + VMM_REG_PDPTE1, + VMM_REG_PDPTE2, + VMM_REG_PDPTE3, + VMM_REG_INTR_SHADOW + }; + + if (flags & DCMD_ADDRSPEC) { + if (argc != 0) + return (DCMD_USAGE); + + cpu = (uint64_t)addr; + } + + i = mdb_getopts(argc, argv, 'c', MDB_OPT_UINT64, &cpu, NULL); + + argc -= i; + argv += i; + + if (argc != 0) + return (DCMD_USAGE); + + if (cpu >= vmm_ncpu(bd->bd_vmm)) { + mdb_warn("no such CPU\n"); + return (DCMD_ERR); + } + + if (vmm_get_regset(bd->bd_vmm, cpu, ARRAY_SIZE(regnums), regnums, + (uint64_t *)&sregs) != 0) + goto fail; + + if (vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_GDTR, + (vmm_desc_t *)&sregs.sr_gdtr) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_IDTR, + (vmm_desc_t *)&sregs.sr_idtr) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_LDTR, + (vmm_desc_t *)&sregs.sr_ldtr) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_TR, + (vmm_desc_t *)&sregs.sr_tr) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_CS, + (vmm_desc_t *)&sregs.sr_cs) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_DS, + (vmm_desc_t *)&sregs.sr_ds) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_ES, + (vmm_desc_t *)&sregs.sr_es) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_FS, + (vmm_desc_t *)&sregs.sr_fs) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_GS, + (vmm_desc_t *)&sregs.sr_gs) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_SS, + (vmm_desc_t *)&sregs.sr_ss) != 0) + goto fail; + + mdb_x86_print_sysregs(&sregs, vmm_vcpu_mode(bd->bd_vmm, cpu) == + VMM_MODE_LONG); + + ret = DCMD_OK; + +fail: + if (ret != DCMD_OK) + mdb_warn("failed to get system registers for CPU %d\n", cpu); + return (ret); +} + +static int +bhyve_dbgregs_dcmd(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + uint64_t cpu = bd->bd_curcpu; + int ret = DCMD_ERR; + vmm_desc_t gdtr, ldtr, idtr, tr, cs, ds, es, fs, gs, ss; + uint64_t *regvals; + int i; + + /* + * This array must use the order of definitions set in libvmm.h + * to make GETREG() work. + */ +#define GETREG(r) (regvals[r - VMM_REG_DR0]) + static const int regnums[] = { + VMM_REG_DR0, + VMM_REG_DR1, + VMM_REG_DR2, + VMM_REG_DR3, + VMM_REG_DR6, + VMM_REG_DR7, + }; + + static const mdb_bitmask_t dr6_flag_bits[] = { + { "DR0", DR_TRAP0, DR_TRAP0 }, + { "DR1", DR_TRAP1, DR_TRAP1 }, + { "DR2", DR_TRAP2, DR_TRAP2 }, + { "DR3", DR_TRAP3, DR_TRAP3 }, + { "debug reg", DR_ICEALSO, DR_ICEALSO }, + { "single step", DR_SINGLESTEP, DR_SINGLESTEP }, + { "task switch", DR_TASKSWITCH, DR_TASKSWITCH }, + { NULL, 0, 0 } + }; + +#define DR_RW(x, m) \ + ((DR_RW_MASK & (m)) << (DR_CONTROL_SHIFT + (x) * DR_CONTROL_SIZE)) +#define DR_LEN(x, m) \ + ((DR_LEN_MASK & (m)) << (DR_CONTROL_SHIFT + (x) * DR_CONTROL_SIZE)) + + static const mdb_bitmask_t dr7_flag_bits[] = { + { "L0", DR_ENABLE0, DR_LOCAL_ENABLE_MASK & DR_ENABLE0 }, + { "G0", DR_ENABLE0, DR_GLOBAL_ENABLE_MASK & DR_ENABLE0 }, + { "L1", DR_ENABLE1, DR_LOCAL_ENABLE_MASK & DR_ENABLE1 }, + { "G1", DR_ENABLE1, DR_GLOBAL_ENABLE_MASK & DR_ENABLE1 }, + { "L2", DR_ENABLE2, DR_LOCAL_ENABLE_MASK & DR_ENABLE2 }, + { "G2", DR_ENABLE2, DR_GLOBAL_ENABLE_MASK & DR_ENABLE2 }, + { "L3", DR_ENABLE3, DR_LOCAL_ENABLE_MASK & DR_ENABLE3 }, + { "G3", DR_ENABLE3, DR_GLOBAL_ENABLE_MASK & DR_ENABLE3 }, + { "LE", DR_LOCAL_SLOWDOWN, DR_LOCAL_SLOWDOWN }, + { "GE", DR_GLOBAL_SLOWDOWN, DR_GLOBAL_SLOWDOWN }, + { "RTM", DR_RTM, DR_RTM }, + { "GD", DR_GENERAL_DETECT, DR_GENERAL_DETECT }, + { "0:X", DR_RW(0, DR_RW_MASK), DR_RW(0, DR_RW_EXECUTE) }, + { "0:W", DR_RW(0, DR_RW_MASK), DR_RW(0, DR_RW_WRITE) }, + { "0:IO", DR_RW(0, DR_RW_MASK), DR_RW(0, DR_RW_IO_RW) }, + { "0:RW", DR_RW(0, DR_RW_MASK), DR_RW(0, DR_RW_READ) }, + { "1:X", DR_RW(1, DR_RW_MASK), DR_RW(1, DR_RW_EXECUTE) }, + { "1:W", DR_RW(1, DR_RW_MASK), DR_RW(1, DR_RW_WRITE) }, + { "1:IO", DR_RW(1, DR_RW_MASK), DR_RW(1, DR_RW_IO_RW) }, + { "1:RW", DR_RW(1, DR_RW_MASK), DR_RW(1, DR_RW_READ) }, + { "2:X", DR_RW(2, DR_RW_MASK), DR_RW(2, DR_RW_EXECUTE) }, + { "2:W", DR_RW(2, DR_RW_MASK), DR_RW(2, DR_RW_WRITE) }, + { "2:IO", DR_RW(2, DR_RW_MASK), DR_RW(2, DR_RW_IO_RW) }, + { "2:RW", DR_RW(2, DR_RW_MASK), DR_RW(2, DR_RW_READ) }, + { "3:X", DR_RW(3, DR_RW_MASK), DR_RW(3, DR_RW_EXECUTE) }, + { "3:W", DR_RW(3, DR_RW_MASK), DR_RW(3, DR_RW_WRITE) }, + { "3:IO", DR_RW(3, DR_RW_MASK), DR_RW(3, DR_RW_IO_RW) }, + { "3:RW", DR_RW(3, DR_RW_MASK), DR_RW(3, DR_RW_READ) }, + { "0:1", DR_LEN(0, DR_LEN_MASK), DR_LEN(0, DR_LEN_1) }, + { "0:2", DR_LEN(0, DR_LEN_MASK), DR_LEN(0, DR_LEN_2) }, + { "0:4", DR_LEN(0, DR_LEN_MASK), DR_LEN(0, DR_LEN_4) }, + { "0:8", DR_LEN(0, DR_LEN_MASK), DR_LEN(0, DR_LEN_8) }, + { "1:1", DR_LEN(1, DR_LEN_MASK), DR_LEN(1, DR_LEN_1) }, + { "1:2", DR_LEN(1, DR_LEN_MASK), DR_LEN(1, DR_LEN_2) }, + { "1:4", DR_LEN(1, DR_LEN_MASK), DR_LEN(1, DR_LEN_4) }, + { "1:8", DR_LEN(1, DR_LEN_MASK), DR_LEN(1, DR_LEN_8) }, + { "2:1", DR_LEN(2, DR_LEN_MASK), DR_LEN(2, DR_LEN_1) }, + { "2:2", DR_LEN(2, DR_LEN_MASK), DR_LEN(2, DR_LEN_2) }, + { "2:4", DR_LEN(2, DR_LEN_MASK), DR_LEN(2, DR_LEN_4) }, + { "2:8", DR_LEN(2, DR_LEN_MASK), DR_LEN(2, DR_LEN_8) }, + { "3:1", DR_LEN(3, DR_LEN_MASK), DR_LEN(3, DR_LEN_1) }, + { "3:2", DR_LEN(3, DR_LEN_MASK), DR_LEN(3, DR_LEN_2) }, + { "3:4", DR_LEN(3, DR_LEN_MASK), DR_LEN(3, DR_LEN_4) }, + { "3:8", DR_LEN(3, DR_LEN_MASK), DR_LEN(3, DR_LEN_8) }, + { NULL, 0, 0 }, + }; + + + if (flags & DCMD_ADDRSPEC) { + if (argc != 0) + return (DCMD_USAGE); + + cpu = (uint64_t)addr; + } + + i = mdb_getopts(argc, argv, 'c', MDB_OPT_UINT64, &cpu, NULL); + + argc -= i; + argv += i; + + if (argc != 0) + return (DCMD_USAGE); + + if (cpu >= vmm_ncpu(bd->bd_vmm)) { + mdb_warn("no such CPU\n"); + return (DCMD_ERR); + } + + regvals = mdb_zalloc(ARRAY_SIZE(regnums) * sizeof (uint64_t), UM_SLEEP); + + if (vmm_get_regset(bd->bd_vmm, cpu, ARRAY_SIZE(regnums), regnums, + regvals) != 0) + goto fail; + + mdb_printf("%%dr0 = 0x%0?p %A\n", + GETREG(VMM_REG_DR0), GETREG(VMM_REG_DR0)); + mdb_printf("%%dr1 = 0x%0?p %A\n", + GETREG(VMM_REG_DR1), GETREG(VMM_REG_DR1)); + mdb_printf("%%dr2 = 0x%0?p %A\n", + GETREG(VMM_REG_DR2), GETREG(VMM_REG_DR2)); + mdb_printf("%%dr3 = 0x%0?p %A\n", + GETREG(VMM_REG_DR3), GETREG(VMM_REG_DR3)); + mdb_printf("%%dr6 = 0x%0lx <%b>\n", + GETREG(VMM_REG_DR6), GETREG(VMM_REG_DR6), dr6_flag_bits); + mdb_printf("%%dr7 = 0x%0lx <%b>\n", + GETREG(VMM_REG_DR7), GETREG(VMM_REG_DR7), dr7_flag_bits); +#undef GETREG + + ret = DCMD_OK; + +fail: + if (ret != DCMD_OK) + mdb_warn("failed to get debug registers for CPU %d\n", cpu); + mdb_free(regvals, ARRAY_SIZE(regnums) * sizeof (uint64_t)); + return (ret); +} + +static int +bhyve_switch_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + size_t cpu = (int)addr; + + if (!(flags & DCMD_ADDRSPEC) || argc != 0) + return (DCMD_USAGE); + + if (cpu >= vmm_ncpu(bd->bd_vmm)) { + mdb_warn("no such CPU\n"); + return (DCMD_ERR); + } + + bd->bd_curcpu = cpu; + return (DCMD_OK); + +} + +static int +bhyve_seg2reg(const char *seg) +{ + if (strcasecmp(seg, "cs") == 0) + return (VMM_DESC_CS); + else if (strcasecmp(seg, "ds") == 0) + return (VMM_DESC_DS); + else if (strcasecmp(seg, "es") == 0) + return (VMM_DESC_ES); + else if (strcasecmp(seg, "fs") == 0) + return (VMM_DESC_FS); + else if (strcasecmp(seg, "gs") == 0) + return (VMM_DESC_GS); + else if (strcasecmp(seg, "ss") == 0) + return (VMM_DESC_SS); + else + return (-1); +} + +static int +bhyve_vtol_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + int segreg = bd->bd_defseg; + char *seg = ""; + uint64_t laddr; + int i; + + if (!(flags & DCMD_ADDRSPEC)) + return (DCMD_USAGE); + + i = mdb_getopts(argc, argv, 's', MDB_OPT_STR, &seg, NULL); + + argc -= i; + argv += i; + + if (i != 0) { + if (argc != 0) + return (DCMD_USAGE); + + segreg = bhyve_seg2reg(seg); + if (segreg == -1) + return (DCMD_USAGE); + } + + if (vmm_vtol(bd->bd_vmm, bd->bd_curcpu, segreg, addr, &laddr) != 0) { + if (errno == EFAULT) + (void) set_errno(EMDB_NOMAP); + return (DCMD_ERR); + } + + if (flags & DCMD_PIPE_OUT) + mdb_printf("%llr\n", laddr); + else + mdb_printf("virtual %lr mapped to linear %llr\n", addr, laddr); + + return (DCMD_OK); +} + +static int +bhyve_vtop_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + int segreg = bd->bd_defseg; + char *seg = ""; + physaddr_t pa; + int i; + + if (!(flags & DCMD_ADDRSPEC)) + return (DCMD_USAGE); + + i = mdb_getopts(argc, argv, 's', MDB_OPT_STR, &seg, NULL); + + argc -= i; + argv += i; + + if (i != 0) { + segreg = bhyve_seg2reg(seg); + if (segreg == -1) + return (DCMD_USAGE); + } + + if (vmm_vtop(bd->bd_vmm, bd->bd_curcpu, segreg, addr, &pa) == -1) { + mdb_warn("failed to get physical mapping"); + return (DCMD_ERR); + } + + if (flags & DCMD_PIPE_OUT) + mdb_printf("%llr\n", pa); + else + mdb_printf("virtual %lr mapped to physical %llr\n", addr, pa); + return (DCMD_OK); +} + +static int +bhyve_defseg_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + int segreg = bd->bd_defseg; + char *seg = ""; + int i; + + if (flags & DCMD_ADDRSPEC) + return (DCMD_USAGE); + + i = mdb_getopts(argc, argv, 's', MDB_OPT_STR, &seg, NULL); + + argc -= i; + argv += i; + + if (i != 0) { + if (argc != 0) + return (DCMD_USAGE); + + segreg = bhyve_seg2reg(seg); + if (segreg == -1) + return (DCMD_USAGE); + + bd->bd_defseg = segreg; + } + + mdb_printf("using segment %s for virtual to linear address translation", + segments[bd->bd_defseg - VMM_DESC_CS]); + + return (DCMD_OK); +} + +static const mdb_dcmd_t bhyve_dcmds[] = { + { "$c", NULL, "print stack backtrace", bhyve_stack_dcmd }, + { "$C", NULL, "print stack backtrace", bhyve_stackv_dcmd }, + { "$r", NULL, "print general-purpose registers", bhyve_regs_dcmd }, + { "$?", NULL, "print status and registers", bhyve_regs_dcmd }, + { ":x", ":", "change the active CPU", bhyve_switch_dcmd }, + { "cpustack", "?[-v] [-c cpuid] [cnt]", "print stack backtrace for a " + "specific CPU", bhyve_cpustack_dcmd }, + { "cpuregs", "?[-c cpuid]", "print general-purpose registers for a " + "specific CPU", bhyve_cpuregs_dcmd }, + { "dbgregs", "?[-c cpuid]", "print debug registers for a specific CPU", + bhyve_dbgregs_dcmd }, + { "defseg", "?[-s segment]", "change the default segment used to " + "translate addresses", bhyve_defseg_dcmd }, + { "regs", NULL, "print general-purpose registers", bhyve_regs_dcmd }, + { "stack", NULL, "print stack backtrace", bhyve_stack_dcmd }, + { "stackregs", NULL, "print stack backtrace and registers", + bhyve_stackr_dcmd }, + { "status", NULL, "print summary of current target", + bhyve_status_dcmd }, + { "sysregs", "?[-c cpuid]", "print system registers for a specific CPU", + bhyve_sysregs_dcmd }, + { "switch", ":", "change the active CPU", bhyve_switch_dcmd }, + { "vtol", ":[-s segment]", "print linear mapping of virtual address", + bhyve_vtol_dcmd }, + { "vtop", ":[-s segment]", "print physical mapping of virtual " + "address", bhyve_vtop_dcmd }, + { NULL } +}; + + +/* + * t_setflags: change target flags + */ +static int +bhyve_setflags(mdb_tgt_t *tgt, int flags) +{ + bhyve_data_t *bd = tgt->t_data; + + if (((tgt->t_flags ^ flags) & MDB_TGT_F_RDWR) != 0) { + boolean_t writable = (flags & MDB_TGT_F_RDWR) != 0; + + vmm_unmap(bd->bd_vmm); + if (vmm_map(bd->bd_vmm, writable) != 0) { + mdb_warn("failed to map guest memory"); + return (set_errno(EMDB_TGT)); + } + } + + tgt->t_flags = flags; + + return (0); +} + +/* + * t_activate: activate target + */ +static void +bhyve_activate(mdb_tgt_t *tgt) +{ + mdb_tgt_status_t *tsp = &tgt->t_status; + bhyve_data_t *bd = tgt->t_data; + const char *format; + char buf[BUFSIZ]; + + (void) mdb_set_prompt(MDB_DEF_PROMPT); + + (void) mdb_tgt_register_dcmds(tgt, bhyve_dcmds, MDB_MOD_FORCE); + mdb_tgt_register_regvars(tgt, bhyve_kregs, &bhyve_reg_disc, 0); + + (void) vmm_stop(bd->bd_vmm); + + if (mdb_tgt_status(tgt, tsp) != 0) + return; + + if (tsp->st_pc != 0) { + if (mdb_dis_ins2str(mdb.m_disasm, mdb.m_target, + MDB_TGT_AS_VIRT_I, buf, sizeof (buf), tsp->st_pc) != + tsp->st_pc) + format = "target stopped at:\n%-#16a%8T%s\n"; + else + format = "target stopped at %a:\n"; + mdb_warn(format, tsp->st_pc, buf); + } +} + +/* + * t_deactivate: deactivate target + */ +static void +bhyve_deactivate(mdb_tgt_t *tgt) +{ + bhyve_data_t *bd = tgt->t_data; + const mdb_tgt_regdesc_t *rd; + const mdb_dcmd_t *dc; + + for (rd = bhyve_kregs; rd->rd_name != NULL; rd++) { + mdb_var_t *var; + + if (!(rd->rd_flags & MDB_TGT_R_EXPORT)) + continue; /* didn't export register as variable */ + + if ((var = mdb_nv_lookup(&mdb.m_nv, rd->rd_name)) != NULL) { + var->v_flags &= ~MDB_NV_PERSIST; + mdb_nv_remove(&mdb.m_nv, var); + } + } + + for (dc = bhyve_dcmds; dc->dc_name != NULL; dc++) + if (mdb_module_remove_dcmd(tgt->t_module, dc->dc_name) == -1) + mdb_warn("failed to remove dcmd %s", dc->dc_name); + + (void) vmm_cont(bd->bd_vmm); +} + +/* + * t_name: return name of target + */ +static const char * +bhyve_name(mdb_tgt_t *tgt) +{ + _NOTE(ARGUNUSED(tgt)); + + return ("bhyve"); +} + +/* + * t_destroy: cleanup target private resources + */ +static void +bhyve_destroy(mdb_tgt_t *tgt) +{ + bhyve_data_t *bd = tgt->t_data; + + (void) vmm_cont(bd->bd_vmm); + vmm_unmap(bd->bd_vmm); + vmm_close_vm(bd->bd_vmm); + mdb_free(bd, sizeof (bhyve_data_t)); + tgt->t_data = NULL; +} + +/* + * t_isa: return name of target ISA + */ +const char * +bhyve_isa(mdb_tgt_t *tgt) +{ + _NOTE(ARGUNUSED(tgt)); + + return ("amd64"); +} + +/* + * t_dmodel: return target data model + */ +static int +bhyve_dmodel(mdb_tgt_t *tgt) +{ + _NOTE(ARGUNUSED(tgt)); + + return (MDB_TGT_MODEL_LP64); +} + +/*ARGSUSED*/ +static ssize_t +bhyve_aread(mdb_tgt_t *tgt, mdb_tgt_as_t as, void *buf, size_t nbytes, + mdb_tgt_addr_t addr) +{ + bhyve_data_t *bd = tgt->t_data; + ssize_t cnt; + + switch ((uintptr_t)as) { + case (uintptr_t)MDB_TGT_AS_VIRT: + cnt = vmm_vread(bd->bd_vmm, bd->bd_curcpu, bd->bd_defseg, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_I: + cnt = vmm_vread(bd->bd_vmm, bd->bd_curcpu, VMM_DESC_CS, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_S: + cnt = vmm_vread(bd->bd_vmm, bd->bd_curcpu, VMM_DESC_SS, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_PHYS: + cnt = vmm_pread(bd->bd_vmm, buf, nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_FILE: + case (uintptr_t)MDB_TGT_AS_IO: + return (set_errno(EMDB_TGTNOTSUP)); + } + + if (errno == EFAULT) + return (set_errno(EMDB_NOMAP)); + + return (cnt); +} + +/*ARGSUSED*/ +static ssize_t +bhyve_awrite(mdb_tgt_t *tgt, mdb_tgt_as_t as, const void *buf, size_t nbytes, + mdb_tgt_addr_t addr) +{ + bhyve_data_t *bd = tgt->t_data; + ssize_t cnt; + + switch ((uintptr_t)as) { + case (uintptr_t)MDB_TGT_AS_VIRT: + cnt = vmm_vwrite(bd->bd_vmm, bd->bd_curcpu, bd->bd_defseg, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_I: + cnt = vmm_vwrite(bd->bd_vmm, bd->bd_curcpu, VMM_DESC_CS, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_S: + cnt = vmm_vwrite(bd->bd_vmm, bd->bd_curcpu, VMM_DESC_SS, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_PHYS: + cnt = vmm_pwrite(bd->bd_vmm, buf, nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_FILE: + case (uintptr_t)MDB_TGT_AS_IO: + return (set_errno(EMDB_TGTNOTSUP)); + } + + if (errno == EFAULT) + return (set_errno(EMDB_NOMAP)); + + return (cnt); +} + +/* + * t_vread: read from virtual memory + */ +/*ARGSUSED*/ +static ssize_t +bhyve_vread(mdb_tgt_t *tgt, void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_aread(tgt, MDB_TGT_AS_VIRT, buf, nbytes, addr)); +} + +/* + * t_vwrite: write to virtual memory + */ +/*ARGSUSED*/ +static ssize_t +bhyve_vwrite(mdb_tgt_t *tgt, const void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_awrite(tgt, MDB_TGT_AS_VIRT, buf, nbytes, addr)); +} + +/* + * t_pread: read from physical memory + */ +/*ARGSUSED*/ +static ssize_t +bhyve_pread(mdb_tgt_t *tgt, void *buf, size_t nbytes, physaddr_t addr) +{ + return (bhyve_aread(tgt, MDB_TGT_AS_PHYS, buf, nbytes, addr)); +} + +/* + * t_pwrite: write to physical memory + */ +/*ARGSUSED*/ +static ssize_t +bhyve_pwrite(mdb_tgt_t *tgt, const void *buf, size_t nbytes, physaddr_t addr) +{ + return (bhyve_awrite(tgt, MDB_TGT_AS_PHYS, buf, nbytes, addr)); +} + +/* + * t_fread: read from core/object file + */ +/*ARGSUSED*/ +static ssize_t +bhyve_fread(mdb_tgt_t *tgt, void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_aread(tgt, MDB_TGT_AS_FILE, buf, nbytes, addr)); +} + +/* + * t_fwrite: write to core/object file + */ +/*ARGSUSED*/ +static ssize_t +bhyve_fwrite(mdb_tgt_t *tgt, const void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_awrite(tgt, MDB_TGT_AS_FILE, buf, nbytes, addr)); +} + +/* + * t_ioread: read from I/O space + */ +/*ARGSUSED*/ +static ssize_t +bhyve_ioread(mdb_tgt_t *tgt, void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_aread(tgt, MDB_TGT_AS_IO, buf, nbytes, addr)); +} + +/* + * t_iowrite: write to I/O space + */ +/*ARGSUSED*/ +static ssize_t +bhyve_iowrite(mdb_tgt_t *tgt, const void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_awrite(tgt, MDB_TGT_AS_IO, buf, nbytes, addr)); +} + +/* + * t_vtop: translate virtual to physical address + */ +static int +bhyve_vtop(mdb_tgt_t *tgt, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pa) +{ + bhyve_data_t *bd = tgt->t_data; + int seg; + + switch ((uintptr_t)as) { + case (uintptr_t)MDB_TGT_AS_VIRT: + seg = bd->bd_defseg; + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_I: + seg = VMM_DESC_CS; + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_S: + seg = VMM_DESC_SS; + break; + + default: + return (set_errno(EINVAL)); + } + + if (vmm_vtop(bd->bd_vmm, bd->bd_curcpu, seg, va, pa) != 0) { + if (errno == EFAULT) + return (set_errno(EMDB_NOMAP)); + else + return (-1); + } + + return (0); +} + +/* + * t_status: get target status + */ +static int +bhyve_status(mdb_tgt_t *tgt, mdb_tgt_status_t *tsp) +{ + bhyve_data_t *bd = tgt->t_data; + mdb_tgt_reg_t rip; + vmm_desc_t cs; + int ret; + + bzero(tsp, sizeof (mdb_tgt_status_t)); + + ret = vmm_getreg(bd->bd_vmm, bd->bd_curcpu, KREG_RIP, &rip); + if (ret != 0) { + tsp->st_state = MDB_TGT_UNDEAD; + } else { + tsp->st_state = MDB_TGT_STOPPED; + tsp->st_pc = rip; + } + + switch (vmm_vcpu_isa(bd->bd_vmm, bd->bd_curcpu)) { + case VMM_ISA_16: + (void) mdb_dis_select("ia16"); + break; + case VMM_ISA_32: + (void) mdb_dis_select("ia32"); + break; + case VMM_ISA_64: + (void) mdb_dis_select("amd64"); + break; + default: + break; + } + + return (0); +} + +static void +bhyve_sighdl(int sig, siginfo_t *sip, ucontext_t *ucp, mdb_tgt_t *tgt) +{ + mdb_tgt_status_t *tsp = &tgt->t_status; + bhyve_data_t *bd = tgt->t_data; + + switch (sig) { + case SIGINT: + /* + * vmm_stop() may fail if the VM was destroyed while we were + * waiting. This will be handled by mdb_tgt_status(). + */ + (void) vmm_stop(bd->bd_vmm); + (void) mdb_tgt_status(tgt, tsp); + break; + } +} + +/* + * t_step: single-step target + */ +static int +bhyve_step(mdb_tgt_t *tgt, mdb_tgt_status_t *tsp) +{ + bhyve_data_t *bd = tgt->t_data; + int ret; + + ret = vmm_step(bd->bd_vmm, bd->bd_curcpu); + (void) mdb_tgt_status(tgt, tsp); + + return (ret); +} + +/* + * t_cont: continue target execution + * + * Catch SIGINT so that the target can be stopped with Ctrl-C. + */ +static int +bhyve_cont(mdb_tgt_t *tgt, mdb_tgt_status_t *tsp) +{ + bhyve_data_t *bd = tgt->t_data; + mdb_signal_f *intf; + void *intd; + int ret; + + intf = mdb_signal_gethandler(SIGINT, &intd); + (void) mdb_signal_sethandler(SIGINT, (mdb_signal_f *)bhyve_sighdl, tgt); + + if (ret = vmm_cont(bd->bd_vmm) != 0) { + mdb_warn("failed to continue target execution: %d", ret); + return (set_errno(EMDB_TGT)); + } + + tsp->st_state = MDB_TGT_RUNNING; + (void) pause(); + + (void) mdb_signal_sethandler(SIGINT, intf, intd); + (void) mdb_tgt_status(tgt, tsp); + + return (ret); +} + +static int +bhyve_lookup_reg(mdb_tgt_t *tgt, const char *rname) +{ + bhyve_data_t *bd = tgt->t_data; + const mdb_tgt_regdesc_t *rd; + + for (rd = bhyve_kregs; rd->rd_name != NULL; rd++) + if (strcmp(rd->rd_name, rname) == 0) + return (rd->rd_num); + + return (-1); +} + +/* + * t_getareg: get the value of a single register + */ +static int +bhyve_getareg(mdb_tgt_t *tgt, mdb_tgt_tid_t tid, const char *rname, + mdb_tgt_reg_t *rp) +{ + bhyve_data_t *bd = tgt->t_data; + int reg = bhyve_lookup_reg(tgt, rname); + int ret; + + if (reg == -1) + return (set_errno(EMDB_BADREG)); + + ret = vmm_getreg(bd->bd_vmm, bd->bd_curcpu, reg, rp); + if (ret == -1) + return (set_errno(EMDB_BADREG)); + + return (0); +} + +/* + * t_putareg: set the value of a single register + */ +static int +bhyve_putareg(mdb_tgt_t *tgt, mdb_tgt_tid_t tid, const char *rname, + mdb_tgt_reg_t r) +{ + bhyve_data_t *bd = tgt->t_data; + int reg = bhyve_lookup_reg(tgt, rname); + int ret; + + if ((tgt->t_flags & MDB_TGT_F_RDWR) == 0) + return (set_errno(EMDB_TGTRDONLY)); + + if (reg == -1) + return (set_errno(EMDB_BADREG)); + + ret = vmm_setreg(bd->bd_vmm, bd->bd_curcpu, reg, r); + if (ret == -1) + return (set_errno(EMDB_BADREG)); + + return (0); +} + +static const mdb_tgt_ops_t bhyve_ops = { + .t_setflags = bhyve_setflags, + .t_setcontext = (int (*)()) mdb_tgt_notsup, + .t_activate = bhyve_activate, + .t_deactivate = bhyve_deactivate, + .t_periodic = (void (*)()) mdb_tgt_nop, + .t_destroy = bhyve_destroy, + .t_name = bhyve_name, + .t_isa = bhyve_isa, + .t_platform = (const char *(*)()) mdb_conf_platform, + .t_uname = (int (*)()) mdb_tgt_notsup, + .t_dmodel = bhyve_dmodel, + .t_aread = bhyve_aread, + .t_awrite = bhyve_awrite, + .t_vread = bhyve_vread, + .t_vwrite = bhyve_vwrite, + .t_pread = bhyve_pread, + .t_pwrite = bhyve_pwrite, + .t_fread = bhyve_fread, + .t_fwrite = bhyve_fwrite, + .t_ioread = bhyve_ioread, + .t_iowrite = bhyve_iowrite, + .t_vtop = bhyve_vtop, + .t_lookup_by_name = (int (*)()) mdb_tgt_notsup, + .t_lookup_by_addr = (int (*)()) mdb_tgt_notsup, + .t_symbol_iter = (int (*)()) mdb_tgt_notsup, + .t_mapping_iter = (int (*)()) mdb_tgt_notsup, + .t_object_iter = (int (*)()) mdb_tgt_notsup, + .t_addr_to_map = (const mdb_map_t *(*)()) mdb_tgt_null, + .t_name_to_map = (const mdb_map_t *(*)()) mdb_tgt_null, + .t_addr_to_ctf = (struct ctf_file *(*)()) mdb_tgt_null, + .t_name_to_ctf = (struct ctf_file *(*)()) mdb_tgt_null, + .t_status = bhyve_status, + .t_run = (int (*)()) mdb_tgt_notsup, + .t_step = bhyve_step, + .t_step_out = (int (*)()) mdb_tgt_notsup, + .t_next = (int (*)()) mdb_tgt_notsup, + .t_cont = bhyve_cont, + .t_signal = (int (*)()) mdb_tgt_notsup, + .t_add_vbrkpt = (int (*)()) mdb_tgt_null, + .t_add_sbrkpt = (int (*)()) mdb_tgt_null, + .t_add_pwapt = (int (*)()) mdb_tgt_null, + .t_add_vwapt = (int (*)()) mdb_tgt_null, + .t_add_iowapt = (int (*)()) mdb_tgt_null, + .t_add_sysenter = (int (*)()) mdb_tgt_null, + .t_add_sysexit = (int (*)()) mdb_tgt_null, + .t_add_signal = (int (*)()) mdb_tgt_null, + .t_add_fault = (int (*)()) mdb_tgt_null, + .t_getareg = bhyve_getareg, + .t_putareg = bhyve_putareg, + .t_stack_iter = (int (*)()) mdb_tgt_notsup, + .t_auxv = (int (*)()) mdb_tgt_notsup +}; + +int +mdb_bhyve_tgt_create(mdb_tgt_t *tgt, int argc, const char *argv[]) +{ + bhyve_data_t *bd; + vmm_t *vmm = NULL; + boolean_t writable = (tgt->t_flags & MDB_TGT_F_RDWR) != 0; + + if (argc != 1) + return (set_errno(EINVAL)); + + vmm = vmm_open_vm(argv[0]); + if (vmm == NULL) { + mdb_warn("failed to open %s", argv[0]); + return (set_errno(EMDB_TGT)); + } + + if (vmm_map(vmm, writable) != 0) { + mdb_warn("failed to map %s", argv[0]); + vmm_close_vm(vmm); + return (set_errno(EMDB_TGT)); + } + + bd = mdb_zalloc(sizeof (bhyve_data_t) + strlen(argv[0]) + 1, UM_SLEEP); + (void) strcpy(bd->bd_name, argv[0]); + bd->bd_vmm = vmm; + bd->bd_curcpu = 0; + bd->bd_defseg = VMM_DESC_DS; + + tgt->t_ops = &bhyve_ops; + tgt->t_data = bd; + tgt->t_flags |= MDB_TGT_F_ASIO; + + (void) mdb_nv_insert(&mdb.m_nv, "cpuid", &bhyve_cpuid_disc, 0, + MDB_NV_PERSIST | MDB_NV_RDONLY); + + return (0); +} diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c b/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c index d6db4811b2..22e56a0eda 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c +++ b/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c @@ -23,16 +23,18 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2018, Joyent, Inc. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ #include +#include #include #include #include #include +#include #include #include #include @@ -41,10 +43,14 @@ #include #include +#ifndef __amd64 /* * We also define an array of register names and their corresponding * array indices. This is used by the getareg and putareg entry points, * and also by our register variable discipline. + * + * When built into an amd64 mdb this won't be used as it's only a subset of + * mdb_amd64_kregs, hence the #ifdef. */ const mdb_tgt_regdesc_t mdb_ia32_kregs[] = { { "savfp", KREG_SAVFP, MDB_TGT_R_EXPORT }, @@ -87,6 +93,7 @@ const mdb_tgt_regdesc_t mdb_ia32_kregs[] = { { "err", KREG_ERR, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV }, { NULL, 0, 0 } }; +#endif void mdb_ia32_printregs(const mdb_tgt_gregset_t *gregs) @@ -94,27 +101,27 @@ mdb_ia32_printregs(const mdb_tgt_gregset_t *gregs) const kreg_t *kregs = &gregs->kregs[0]; kreg_t eflags = kregs[KREG_EFLAGS]; - mdb_printf("%%cs = 0x%04x\t\t%%eax = 0x%0?p %A\n", + mdb_printf("%%cs = 0x%04x\t\t%%eax = 0x%08p %A\n", kregs[KREG_CS], kregs[KREG_EAX], kregs[KREG_EAX]); - mdb_printf("%%ds = 0x%04x\t\t%%ebx = 0x%0?p %A\n", + mdb_printf("%%ds = 0x%04x\t\t%%ebx = 0x%08p %A\n", kregs[KREG_DS], kregs[KREG_EBX], kregs[KREG_EBX]); - mdb_printf("%%ss = 0x%04x\t\t%%ecx = 0x%0?p %A\n", + mdb_printf("%%ss = 0x%04x\t\t%%ecx = 0x%08p %A\n", kregs[KREG_SS], kregs[KREG_ECX], kregs[KREG_ECX]); - mdb_printf("%%es = 0x%04x\t\t%%edx = 0x%0?p %A\n", + mdb_printf("%%es = 0x%04x\t\t%%edx = 0x%08p %A\n", kregs[KREG_ES], kregs[KREG_EDX], kregs[KREG_EDX]); - mdb_printf("%%fs = 0x%04x\t\t%%esi = 0x%0?p %A\n", + mdb_printf("%%fs = 0x%04x\t\t%%esi = 0x%08p %A\n", kregs[KREG_FS], kregs[KREG_ESI], kregs[KREG_ESI]); - mdb_printf("%%gs = 0x%04x\t\t%%edi = 0x%0?p %A\n\n", + mdb_printf("%%gs = 0x%04x\t\t%%edi = 0x%08p %A\n\n", kregs[KREG_GS], kregs[KREG_EDI], kregs[KREG_EDI]); - mdb_printf("%%eip = 0x%0?p %A\n", kregs[KREG_EIP], kregs[KREG_EIP]); - mdb_printf("%%ebp = 0x%0?p\n", kregs[KREG_EBP]); - mdb_printf("%%esp = 0x%0?p\n\n", kregs[KREG_ESP]); + mdb_printf("%%eip = 0x%08p %A\n", kregs[KREG_EIP], kregs[KREG_EIP]); + mdb_printf("%%ebp = 0x%08p\n", kregs[KREG_EBP]); + mdb_printf("%%esp = 0x%08p\n\n", kregs[KREG_ESP]); mdb_printf("%%eflags = 0x%08x\n", eflags); mdb_printf(" id=%u vip=%u vif=%u ac=%u vm=%u rf=%u nt=%u iopl=0x%x\n", @@ -138,8 +145,8 @@ mdb_ia32_printregs(const mdb_tgt_gregset_t *gregs) (eflags & KREG_EFLAGS_PF_MASK) ? "PF" : "pf", (eflags & KREG_EFLAGS_CF_MASK) ? "CF" : "cf"); -#ifndef _KMDB - mdb_printf(" %%uesp = 0x%0?x\n", kregs[KREG_UESP]); +#if !defined(__amd64) && !defined(_KMDB) + mdb_printf(" %%uesp = 0x%08x\n", kregs[KREG_UESP]); #endif mdb_printf("%%trapno = 0x%x\n", kregs[KREG_TRAPNO]); mdb_printf(" %%err = 0x%x\n", kregs[KREG_ERR]); @@ -166,7 +173,8 @@ kvm_argcount(mdb_tgt_t *t, uintptr_t eip, ssize_t size) M_ADD_IMM8 = 0x83 /* ADD imm8 to r/m32 */ }; - if (mdb_tgt_vread(t, ins, sizeof (ins), eip) != sizeof (ins)) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, ins, sizeof (ins), eip) != + sizeof (ins)) return (0); if (ins[1] != M_MODRM_ESP) @@ -185,7 +193,7 @@ kvm_argcount(mdb_tgt_t *t, uintptr_t eip, ssize_t size) n = 0; } - return (MIN((ssize_t)n, size) / sizeof (long)); + return (MIN((ssize_t)n, size) / sizeof (uint32_t)); } int @@ -198,9 +206,9 @@ mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, int err; struct fr { - uintptr_t fr_savfp; - uintptr_t fr_savpc; - long fr_argv[32]; + uintptr32_t fr_savfp; + uintptr32_t fr_savpc; + uint32_t fr_argv[32]; } fr; uintptr_t fp = gsp->kregs[KREG_EBP]; @@ -226,9 +234,9 @@ mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, err = EMDB_STKALIGN; goto badfp; } - if ((size = mdb_tgt_vread(t, &fr, sizeof (fr), fp)) >= - (ssize_t)(2 * sizeof (uintptr_t))) { - size -= (ssize_t)(2 * sizeof (uintptr_t)); + if ((size = mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &fr, + sizeof (fr), fp)) >= (ssize_t)(2 * sizeof (uintptr32_t))) { + size -= (ssize_t)(2 * sizeof (uintptr32_t)); argc = kvm_argcount(t, fr.fr_savpc, size); } else { err = EMDB_NOMAP; @@ -245,8 +253,9 @@ mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, if (advance_tortoise != 0) { struct fr tfr; - if (mdb_tgt_vread(t, &tfr, sizeof (tfr), - tortoise_fp) != sizeof (tfr)) { + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &tfr, + sizeof (tfr), tortoise_fp) != + sizeof (tfr)) { err = EMDB_NOMAP; goto badfp; } @@ -262,7 +271,8 @@ mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, advance_tortoise = !advance_tortoise; - if (got_pc && func(arg, pc, argc, fr.fr_argv, &gregs) != 0) + if (got_pc && + func(arg, pc, argc, (const long *)fr.fr_argv, &gregs) != 0) break; kregs[KREG_ESP] = kregs[KREG_EBP]; @@ -294,6 +304,12 @@ badfp: return (set_errno(err)); } +#ifndef __amd64 +/* + * The functions mdb_ia32_step_out and mdb_ia32_next haven't yet been adapted + * to work when built for an amd64 mdb. They are unused by the amd64-only bhyve + * target, hence the #ifdef. + */ /* * Determine the return address for the current frame. Typically this is the * fr_savpc value from the current frame, but we also perform some special @@ -321,7 +337,8 @@ mdb_ia32_step_out(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, kreg_t fp, kreg_t sp, fp = sp; } - if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) == sizeof (fr)) { + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &fr, sizeof (fr), fp) == + sizeof (fr)) { *p = fr.fr_savpc; return (0); } @@ -372,7 +389,8 @@ mdb_ia32_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr) * read the subsequent Mod/RM byte to perform additional decoding. */ if (curinstr == M_CALL_REG) { - if (mdb_tgt_vread(t, &m, sizeof (m), pc + 1) != sizeof (m)) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &m, sizeof (m), pc + 1) + != sizeof (m)) return (-1); /* errno is set for us */ /* @@ -404,13 +422,16 @@ mdb_ia32_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr) return (set_errno(EAGAIN)); } +#endif /*ARGSUSED*/ int -mdb_ia32_kvm_frame(void *arglim, uintptr_t pc, uint_t argc, const long *argv, +mdb_ia32_kvm_frame(void *arglim, uintptr_t pc, uint_t argc, const long *largv, const mdb_tgt_gregset_t *gregs) { - argc = MIN(argc, (uint_t)arglim); + const uint32_t *argv = (const uint32_t *)largv; + + argc = MIN(argc, (uintptr_t)arglim); mdb_printf("%a(", pc); if (argc != 0) { @@ -424,11 +445,13 @@ mdb_ia32_kvm_frame(void *arglim, uintptr_t pc, uint_t argc, const long *argv, } int -mdb_ia32_kvm_framev(void *arglim, uintptr_t pc, uint_t argc, const long *argv, +mdb_ia32_kvm_framev(void *arglim, uintptr_t pc, uint_t argc, const long *largv, const mdb_tgt_gregset_t *gregs) { - argc = MIN(argc, (uint_t)arglim); - mdb_printf("%0?lr %a(", gregs->kregs[KREG_EBP], pc); + const uint32_t *argv = (const uint32_t *)largv; + + argc = MIN(argc, (uintptr_t)arglim); + mdb_printf("%08lr %a(", gregs->kregs[KREG_EBP], pc); if (argc != 0) { mdb_printf("%lr", *argv++); diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.h b/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.h index 597b234b3e..1645b86d8d 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.h +++ b/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.h @@ -22,12 +22,13 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2018, Joyent, Inc. All rights reserved. + */ #ifndef _MDB_IA32UTIL_H #define _MDB_IA32UTIL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include @@ -35,8 +36,6 @@ extern "C" { #endif -typedef uchar_t mdb_instr_t; - extern const mdb_tgt_regdesc_t mdb_ia32_kregs[]; extern void mdb_ia32_printregs(const mdb_tgt_gregset_t *); diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_isautil.h b/usr/src/cmd/mdb/intel/mdb/mdb_isautil.h index b6d17e1045..237e6663ae 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_isautil.h +++ b/usr/src/cmd/mdb/intel/mdb/mdb_isautil.h @@ -23,16 +23,19 @@ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2018, Joyent, Inc. All rights reserved. + */ #ifndef _MDB_ISAUTIL_H #define _MDB_ISAUTIL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif +typedef uchar_t mdb_instr_t; + #ifdef __amd64 #include diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h b/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h index a3edf864d7..3db7d6a1d6 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h +++ b/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h @@ -75,6 +75,7 @@ typedef uint32_t kreg_t; #define KREG_ES KDIREG_ES #define KREG_FS KDIREG_FS #define KREG_GS KDIREG_GS +#define KREG_FSBASE KDIREG_FSBASE #define KREG_GSBASE KDIREG_GSBASE #define KREG_KGSBASE KDIREG_KGSBASE #define KREG_TRAPNO KDIREG_TRAPNO @@ -91,6 +92,17 @@ typedef uint32_t kreg_t; #define KREG_SP KREG_RSP #define KREG_FP KREG_RBP +#define KREG_EAX KREG_RAX +#define KREG_EBX KREG_RBX +#define KREG_ECX KREG_RCX +#define KREG_EDX KREG_RDX +#define KREG_ESI KREG_RSI +#define KREG_EDI KREG_RDI +#define KREG_EBP KREG_RBP +#define KREG_ESP KREG_RSP +#define KREG_EFLAGS KREG_RFLAGS +#define KREG_EIP KREG_RIP + #else /* __amd64 */ #define KREG_SAVFP KDIREG_SAVFP diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_x86util.c b/usr/src/cmd/mdb/intel/mdb/mdb_x86util.c new file mode 100644 index 0000000000..a01ee6cffb --- /dev/null +++ b/usr/src/cmd/mdb/intel/mdb/mdb_x86util.c @@ -0,0 +1,215 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +/* + * ISA-independent utility functions for the x86 architecture + */ + +#include +#include + +#include +#include + +#define MMU_PAGESHIFT 12 +#define MMU_PAGESIZE (1 << MMU_PAGESHIFT) +#define MMU_PAGEOFFSET (MMU_PAGESIZE - 1) +#define MMU_PAGEMASK (~MMU_PAGEOFFSET) + +#ifndef _KMDB +static void +mdb_x86_print_desc(const char *name, const mdb_x86_desc_t *desc, uint_t width) +{ + const char *type; + const mdb_bitmask_t *bits; + + static const mdb_bitmask_t mem_desc_flag_bits[] = { + { "P", 0x80, 0x80 }, + { "16b", 0x6000, 0x0 }, + { "32b", 0x6000, 0x4000 }, + { "64b", 0x6000, 0x2000 }, + { "G", 0x8000, 0x8000 }, + { "A", 0x1, 0x1 }, + { NULL, 0, 0 }, + }; + + static const char *mem_desc_types[] = { + "data, up, read-only", + "data, up, read-write", + "data, down, read-only", + "data, down, read-write", + "code, non-conforming, execute-only", + "code, non-conforming, execute-read", + "code, conforming, execute-only", + "code, conforming, execute-read" + }; + + static const mdb_bitmask_t sys_desc_flag_bits[] = { + { "P", 0x80, 0x80 }, + { "16b", 0x6000, 0x0 }, + { "32b", 0x6000, 0x4000 }, + { "64b", 0x6000, 0x2000 }, + { "G", 0x8000, 0x8000 }, + { NULL, 0, 0 }, + }; + + static const char *sys_desc_types[] = { + "reserved", + "16b TSS, available", + "LDT", + "16b TSS, busy", + "16b call gate", + "task gate", + "16b interrupt gate", + "16b trap gate", + "reserved", + "32b/64b TSS, available", + "reserved", + "32b/64b TSS, busy", + "32b/64b call gate", + "reserved", + "32b/64b interrupt gate" + "32b/64b trap gate", + }; + + if (desc->d_acc & 0x10) { + type = mem_desc_types[(desc->d_acc >> 1) & 7]; + bits = mem_desc_flag_bits; + } else { + type = sys_desc_types[desc->d_acc & 0xf]; + bits = sys_desc_flag_bits; + } + + mdb_printf("%%%s = 0x%0*lx/0x%0*x 0x%05x " + "<%susable, %s, dpl %d, flags: %b>\n", + name, width, desc->d_base, width / 2, desc->d_lim, desc->d_acc, + (desc->d_acc >> 16) & 1 ? "un" : "", type, + (desc->d_acc >> 5) & 3, desc->d_acc, bits); +} +#endif + +void +mdb_x86_print_sysregs(struct sysregs *sregs, boolean_t long_mode) +{ + const uint_t width = + 2 * (long_mode ? sizeof (uint64_t) : sizeof (uint32_t)); + + +#ifndef _KMDB + static const mdb_bitmask_t efer_flag_bits[] = { + { "SCE", AMD_EFER_SCE, AMD_EFER_SCE }, + { "LME", AMD_EFER_LME, AMD_EFER_LME }, + { "LMA", AMD_EFER_LMA, AMD_EFER_LMA }, + { "NXE", AMD_EFER_NXE, AMD_EFER_NXE }, + { "SVME", AMD_EFER_SVME, AMD_EFER_SVME }, + { "LMSLE", AMD_EFER_LMSLE, AMD_EFER_LMSLE }, + { "FFXSR", AMD_EFER_FFXSR, AMD_EFER_FFXSR }, + { "TCE", AMD_EFER_TCE, AMD_EFER_TCE }, + { NULL, 0, 0 } + }; +#endif + + static const mdb_bitmask_t cr0_flag_bits[] = { + { "PE", CR0_PE, CR0_PE }, + { "MP", CR0_MP, CR0_MP }, + { "EM", CR0_EM, CR0_EM }, + { "TS", CR0_TS, CR0_TS }, + { "ET", CR0_ET, CR0_ET }, + { "NE", CR0_NE, CR0_NE }, + { "WP", CR0_WP, CR0_WP }, + { "AM", CR0_AM, CR0_AM }, + { "NW", CR0_NW, CR0_NW }, + { "CD", CR0_CD, CR0_CD }, + { "PG", CR0_PG, CR0_PG }, + { NULL, 0, 0 } + }; + + static const mdb_bitmask_t cr3_flag_bits[] = { + { "PCD", CR3_PCD, CR3_PCD }, + { "PWT", CR3_PWT, CR3_PWT }, + { NULL, 0, 0, } + }; + + static const mdb_bitmask_t cr4_flag_bits[] = { + { "VME", CR4_VME, CR4_VME }, + { "PVI", CR4_PVI, CR4_PVI }, + { "TSD", CR4_TSD, CR4_TSD }, + { "DE", CR4_DE, CR4_DE }, + { "PSE", CR4_PSE, CR4_PSE }, + { "PAE", CR4_PAE, CR4_PAE }, + { "MCE", CR4_MCE, CR4_MCE }, + { "PGE", CR4_PGE, CR4_PGE }, + { "PCE", CR4_PCE, CR4_PCE }, + { "OSFXSR", CR4_OSFXSR, CR4_OSFXSR }, + { "OSXMMEXCPT", CR4_OSXMMEXCPT, CR4_OSXMMEXCPT }, + { "UMIP", CR4_UMIP, CR4_UMIP }, + { "VMXE", CR4_VMXE, CR4_VMXE }, + { "SMXE", CR4_SMXE, CR4_SMXE }, + { "FSGSBASE", CR4_FSGSBASE, CR4_FSGSBASE }, + { "PCIDE", CR4_PCIDE, CR4_PCIDE }, + { "OSXSAVE", CR4_OSXSAVE, CR4_OSXSAVE }, + { "SMEP", CR4_SMEP, CR4_SMEP }, + { "SMAP", CR4_SMAP, CR4_SMAP }, + { "PKE", CR4_PKE, CR4_PKE }, + { NULL, 0, 0 } + }; + +#ifndef _KMDB + mdb_printf("%%efer = 0x%0lx <%b>\n", + sregs->sr_efer, sregs->sr_efer, efer_flag_bits); +#endif + mdb_printf("%%cr0 = 0x%0lx <%b>\n", + sregs->sr_cr0, sregs->sr_cr0, cr0_flag_bits); + mdb_printf("%%cr2 = 0x%0*x <%a>\n", width, + sregs->sr_cr2, sregs->sr_cr2); + mdb_printf("%%cr3 = 0x%0lx sr_cr3, sregs->sr_cr3 >> MMU_PAGESHIFT); + if (sregs->sr_cr4 & CR4_PCIDE) + mdb_printf("pcid:%lu>\n", sregs->sr_cr3 & MMU_PAGEOFFSET); + else + mdb_printf("flags:%b>\n", sregs->sr_cr3, cr3_flag_bits); + mdb_printf("%%cr4 = 0x%0lx <%b>\n", + sregs->sr_cr4, sregs->sr_cr4, cr4_flag_bits); + +#ifndef _KMDB + mdb_printf("\n"); + mdb_printf("%%pdpte0 = 0x%0?lx\t%%pdpte2 = 0x%0?lx\n", + sregs->sr_pdpte0, sregs->sr_pdpte2); + mdb_printf("%%pdpte1 = 0x%0?lx\t%%pdpte3 = 0x%0?lx\n", + sregs->sr_pdpte1, sregs->sr_pdpte3); + mdb_printf("\n"); + + mdb_printf("%%gdtr = 0x%0*lx/0x%hx\n", + width, sregs->sr_gdtr.d_base, sregs->sr_gdtr.d_lim); +#else + mdb_printf("%%gdtr.base = 0x%0*lx, %%gdtr.limit = 0x%hx\n", + width, sregs->sr_gdtr.d_base, sregs->sr_gdtr.d_lim); +#endif +#ifndef _KMDB + mdb_printf("%%idtr = 0x%0*lx/0x%hx\n", + width, sregs->sr_idtr.d_base, sregs->sr_idtr.d_lim); + mdb_x86_print_desc("ldtr", &sregs->sr_ldtr, width); + mdb_x86_print_desc("tr ", &sregs->sr_tr, width); + mdb_x86_print_desc("cs ", &sregs->sr_cs, width); + mdb_x86_print_desc("ss ", &sregs->sr_ss, width); + mdb_x86_print_desc("ds ", &sregs->sr_ds, width); + mdb_x86_print_desc("es ", &sregs->sr_es, width); + mdb_x86_print_desc("fs ", &sregs->sr_fs, width); + mdb_x86_print_desc("gs ", &sregs->sr_gs, width); + + mdb_printf("%%intr_shadow = 0x%lx\n", + sregs->sr_intr_shadow); +#endif +} diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_x86util.h b/usr/src/cmd/mdb/intel/mdb/mdb_x86util.h new file mode 100644 index 0000000000..7641595d2a --- /dev/null +++ b/usr/src/cmd/mdb/intel/mdb/mdb_x86util.h @@ -0,0 +1,68 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +#ifndef _MDB_X86UTIL_H +#define _MDB_X86UTIL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mdb_x86_desc { + uint64_t d_base; + uint32_t d_lim; + uint32_t d_acc; +} mdb_x86_desc_t; + +struct sysregs { + uint64_t sr_cr0; + uint64_t sr_cr2; + uint64_t sr_cr3; + uint64_t sr_cr4; + uint64_t sr_dr0; + uint64_t sr_dr1; + uint64_t sr_dr2; + uint64_t sr_dr3; + uint64_t sr_dr6; + uint64_t sr_dr7; + uint64_t sr_efer; + uint64_t sr_pdpte0; + uint64_t sr_pdpte1; + uint64_t sr_pdpte2; + uint64_t sr_pdpte3; + uint64_t sr_intr_shadow; + mdb_x86_desc_t sr_gdtr; + mdb_x86_desc_t sr_idtr; + mdb_x86_desc_t sr_ldtr; + mdb_x86_desc_t sr_tr; + mdb_x86_desc_t sr_cs; + mdb_x86_desc_t sr_ss; + mdb_x86_desc_t sr_ds; + mdb_x86_desc_t sr_es; + mdb_x86_desc_t sr_fs; + mdb_x86_desc_t sr_gs; +}; + +extern void mdb_x86_print_sysregs(struct sysregs *, boolean_t); + + +#ifdef __cplusplus +} +#endif + +#endif /* _MDB_X86UTIL_H */ diff --git a/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c b/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c index cb613e2f0c..b19498b96e 100644 --- a/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c +++ b/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -144,7 +145,8 @@ pt_read_instr(mdb_tgt_t *t) const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp; uint8_t ret = 0; - (void) mdb_tgt_vread(t, &ret, sizeof (ret), psp->pr_reg[REG_RIP]); + (void) mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &ret, sizeof (ret), + psp->pr_reg[REG_RIP]); return (ret); } diff --git a/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c b/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c index 7f505b950f..c03a73f31e 100644 --- a/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c +++ b/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c @@ -24,8 +24,8 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2018, Joyent, Inc. * Copyright 2019 Doma Gergő Mihály + * Copyright 2018 Joyent, Inc. */ /* @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -99,7 +100,8 @@ pt_read_instr(mdb_tgt_t *t) const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp; uint8_t ret = 0; - (void) mdb_tgt_vread(t, &ret, sizeof (ret), psp->pr_reg[EIP]); + (void) mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &ret, sizeof (ret), + psp->pr_reg[EIP]); return (ret); } diff --git a/usr/src/compat/freebsd/amd64/machine/specialreg.h b/usr/src/compat/freebsd/amd64/machine/specialreg.h index 871573ea6b..ead63aaaab 100644 --- a/usr/src/compat/freebsd/amd64/machine/specialreg.h +++ b/usr/src/compat/freebsd/amd64/machine/specialreg.h @@ -38,6 +38,7 @@ #undef CR4_SMEP #undef CR4_SMAP #undef CR4_PKE +#undef CR4_FSGSBASE #undef CR4_PCIDE #endif /* _SYS_CONTROLREGS_H */ diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index c40721fd55..374c46d532 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -282,6 +282,7 @@ SUBDIRS += \ i386_SUBDIRS= \ libfdisk \ libsaveargs \ + libvmm \ libvmmapi sparc_SUBDIRS= \ @@ -508,6 +509,7 @@ HDRSUBDIRS= \ i386_HDRSUBDIRS= \ libfdisk \ libsaveargs \ + libvmm \ libvmmapi sparc_HDRSUBDIRS= \ @@ -694,6 +696,7 @@ libtsnet: libtsol libsecdb libtsol: libsecdb libuuid: libdlpi libv12n: libds libuuid +libvmm: libvmmapi libvolmgt: libadm libvrrpadm: libdladm libscf libvscan: libscf libsecdb diff --git a/usr/src/lib/libvmm/Makefile b/usr/src/lib/libvmm/Makefile new file mode 100644 index 0000000000..66bd60eb46 --- /dev/null +++ b/usr/src/lib/libvmm/Makefile @@ -0,0 +1,43 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018 Joyent, Inc. +# + +include ../Makefile.lib +include ../Makefile.rootfs + +$(BUILD64)SUBDIRS += $(MACH64) + +HDRS = libvmm.h +HDRDIR = . +CHECKHDRS = $(HDRS:%.h=%.check) + +all:= TARGET= all +install:= TARGET= install +clean:= TARGET= clean +clobber:= TARGET= clobber +lint:= TARGET= lint + +.KEEP_STATE: + +all install clean clobber lint: $(SUBDIRS) + +install_h: $(ROOTHDRS) +check: $(CHECKHDRS) + +$(SUBDIRS): FRC + cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include ../Makefile.targ diff --git a/usr/src/lib/libvmm/Makefile.com b/usr/src/lib/libvmm/Makefile.com new file mode 100644 index 0000000000..d85abae8ce --- /dev/null +++ b/usr/src/lib/libvmm/Makefile.com @@ -0,0 +1,51 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018 Joyent, Inc. +# + +LIBRARY = libvmm.a +VERS = .1 +OBJECTS = libvmm.o list.o + +SRCDIR = . + +include ../../Makefile.lib +include ../../Makefile.rootfs + +LIBS = $(DYNLIB) + +# The FreeBSD compat and contrib headers need to be first in the search +# path, hence we can't just append them to CPPFLAGS. So we assign CPPFLAGS +# directly and pull in CPPFLAGS.master at the appropriate place. +CPPFLAGS = -I$(COMPAT)/freebsd -I$(CONTRIB)/freebsd \ + -I$(COMPAT)/freebsd/amd64 -I$(CONTRIB)/freebsd/amd64 \ + $(CPPFLAGS.master) -I$(SRC)/uts/i86pc + +LDLIBS += -lc -lvmmapi + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +pics/%.o: $(SRC)/common/list/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +# include library targets +include ../../Makefile.targ diff --git a/usr/src/lib/libvmm/amd64/Makefile b/usr/src/lib/libvmm/amd64/Makefile new file mode 100644 index 0000000000..5ba4f14479 --- /dev/null +++ b/usr/src/lib/libvmm/amd64/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018 Joyent, Inc. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libvmm/libvmm.c b/usr/src/lib/libvmm/libvmm.c new file mode 100644 index 0000000000..dc552a8de0 --- /dev/null +++ b/usr/src/lib/libvmm/libvmm.c @@ -0,0 +1,860 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +/* + * Library for native code to access bhyve VMs, without the need to use + * FreeBSD compat headers + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +typedef struct vmm_memseg vmm_memseg_t; + +#define VMM_MEMSEG_DEVMEM 0x1 + +struct vmm_memseg { + list_node_t vms_list; + int vms_segid; + int vms_prot; + int vms_flags; + uintptr_t vms_gpa; + off_t vms_segoff; + size_t vms_seglen; + size_t vms_maplen; + char vms_name[64]; +}; + +struct vmm { + struct vmctx *vmm_ctx; + list_t vmm_memlist; + char *vmm_mem; + size_t vmm_memsize; + size_t vmm_ncpu; +}; + + +/* + * This code relies on two assumptions: + * - CPUs are never removed from the "active set", not even when suspended. + * A CPU being active just means that it has been used by the guest OS. + * - The CPU numbering is consecutive. + */ +static void +vmm_update_ncpu(vmm_t *vmm) +{ + cpuset_t cpuset; + + assert(vm_active_cpus(vmm->vmm_ctx, &cpuset) == 0); + + for (vmm->vmm_ncpu = 0; + CPU_ISSET(vmm->vmm_ncpu, &cpuset) == 1; + vmm->vmm_ncpu++) + ; +} + +vmm_t * +vmm_open_vm(const char *name) +{ + vmm_t *vmm = NULL; + + vmm = malloc(sizeof (vmm_t)); + if (vmm == NULL) + return (NULL); + + bzero(vmm, sizeof (vmm_t)); + vmm->vmm_mem = MAP_FAILED; + + list_create(&vmm->vmm_memlist, sizeof (vmm_memseg_t), + offsetof(vmm_memseg_t, vms_list)); + + vmm->vmm_ctx = vm_open(name); + if (vmm->vmm_ctx == NULL) { + free(vmm); + return (NULL); + } + + vmm_update_ncpu(vmm); + + /* + * If we open a VM that has just been created we may see a state + * where it has no CPUs configured yet. We'll just wait for 10ms + * and retry until we get a non-zero CPU count. + */ + if (vmm->vmm_ncpu == 0) { + do { + (void) usleep(10000); + vmm_update_ncpu(vmm); + } while (vmm->vmm_ncpu == 0); + } + + return (vmm); +} + +void +vmm_close_vm(vmm_t *vmm) +{ + vmm_unmap(vmm); + + list_destroy(&vmm->vmm_memlist); + + if (vmm->vmm_ctx != NULL) + vm_close(vmm->vmm_ctx); + + free(vmm); +} + +static vmm_memseg_t * +vmm_get_memseg(vmm_t *vmm, uintptr_t gpa) +{ + vmm_memseg_t ms, *ret; + int error, flags; + + bzero(&ms, sizeof (vmm_memseg_t)); + ms.vms_gpa = gpa; + error = vm_mmap_getnext(vmm->vmm_ctx, &ms.vms_gpa, &ms.vms_segid, + &ms.vms_segoff, &ms.vms_maplen, &ms.vms_prot, &flags); + if (error) + return (NULL); + + error = vm_get_memseg(vmm->vmm_ctx, ms.vms_segid, &ms.vms_seglen, + ms.vms_name, sizeof (ms.vms_name)); + if (error) + return (NULL); + + /* + * Regular memory segments don't have a name, but devmem segments do. + * We can use that information to set the DEVMEM flag if necessary. + */ + ms.vms_flags = ms.vms_name[0] != '\0' ? VMM_MEMSEG_DEVMEM : 0; + + ret = malloc(sizeof (vmm_memseg_t)); + if (ret == NULL) + return (NULL); + + *ret = ms; + + return (ret); +} + +int +vmm_map(vmm_t *vmm, boolean_t writable) +{ + uintptr_t last_gpa = 0; + vmm_memseg_t *ms; + int prot_write = writable ? PROT_WRITE : 0; + + if (vmm->vmm_mem != MAP_FAILED) { + errno = EINVAL; + return (-1); + } + + assert(list_is_empty(&vmm->vmm_memlist)); + + for (;;) { + ms = vmm_get_memseg(vmm, last_gpa); + + if (ms == NULL) + break; + + last_gpa = ms->vms_gpa + ms->vms_maplen; + list_insert_tail(&vmm->vmm_memlist, ms); + } + + vmm->vmm_mem = mmap(NULL, last_gpa, PROT_NONE, + MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0); + + if (vmm->vmm_mem == MAP_FAILED) + goto fail; + + for (ms = list_head(&vmm->vmm_memlist); + ms != NULL; + ms = list_next(&vmm->vmm_memlist, ms)) { + off_t mapoff = ms->vms_gpa; + + if ((ms->vms_flags & VMM_MEMSEG_DEVMEM) && + vm_get_devmem_offset(vmm->vmm_ctx, ms->vms_segid, &mapoff) + != 0) + goto fail; + + vmm->vmm_memsize += ms->vms_maplen; + + if (mmap(vmm->vmm_mem + ms->vms_gpa, ms->vms_maplen, + PROT_READ | prot_write, MAP_SHARED | MAP_FIXED, + vm_get_device_fd(vmm->vmm_ctx), mapoff) == MAP_FAILED) + goto fail; + } + + return (0); + +fail: + vmm_unmap(vmm); + + return (-1); +} + +void +vmm_unmap(vmm_t *vmm) +{ + while (!list_is_empty(&vmm->vmm_memlist)) { + vmm_memseg_t *ms = list_remove_head(&vmm->vmm_memlist); + + if (vmm->vmm_mem != MAP_FAILED) { + (void) munmap(vmm->vmm_mem + ms->vms_gpa, + ms->vms_maplen); + } + + free(ms); + } + + if (vmm->vmm_mem != MAP_FAILED) + (void) munmap(vmm->vmm_mem, vmm->vmm_memsize); + + vmm->vmm_mem = MAP_FAILED; + vmm->vmm_memsize = 0; +} + +ssize_t +vmm_pread(vmm_t *vmm, void *buf, size_t len, uintptr_t addr) +{ + ssize_t count = 0; + vmm_memseg_t *ms; + ssize_t res = len; + + for (ms = list_head(&vmm->vmm_memlist); + ms != NULL && len != 0; + ms = list_next(&vmm->vmm_memlist, ms)) { + + if (addr >= ms->vms_gpa && + addr < ms->vms_gpa + ms->vms_maplen) { + res = (addr + len) - (ms->vms_gpa + ms->vms_maplen); + + if (res < 0) + res = 0; + + bcopy(vmm->vmm_mem + addr, buf, len - res); + count += len - res; + addr += len - res; + len = res; + } + } + + if (res) + errno = EFAULT; + else + errno = 0; + + return (count); +} + +ssize_t +vmm_pwrite(vmm_t *vmm, const void *buf, size_t len, uintptr_t addr) +{ + ssize_t count = 0; + vmm_memseg_t *ms; + ssize_t res = len; + + for (ms = list_head(&vmm->vmm_memlist); + ms != NULL; + ms = list_next(&vmm->vmm_memlist, ms)) { + if (addr >= ms->vms_gpa && + addr < ms->vms_gpa + ms->vms_maplen) { + res = (addr + len) - (ms->vms_gpa + ms->vms_maplen); + + if (res < 0) + res = 0; + + bcopy(buf, vmm->vmm_mem + addr, len - res); + count += len - res; + addr += len - res; + len = res; + } + } + + if (res) + errno = EFAULT; + else + errno = 0; + + return (count); +} + +size_t +vmm_ncpu(vmm_t *vmm) +{ + return (vmm->vmm_ncpu); +} + +size_t +vmm_memsize(vmm_t *vmm) +{ + return (vmm->vmm_memsize); +} + +int +vmm_cont(vmm_t *vmm) +{ + return (vm_resume_cpu(vmm->vmm_ctx, -1)); +} + +int +vmm_step(vmm_t *vmm, int vcpu) +{ + cpuset_t cpuset; + int ret; + + if (vcpu >= vmm->vmm_ncpu) { + errno = EINVAL; + return (-1); + } + + ret = vm_set_capability(vmm->vmm_ctx, vcpu, VM_CAP_MTRAP_EXIT, 1); + if (ret != 0) + return (-1); + + assert(vm_resume_cpu(vmm->vmm_ctx, vcpu) == 0); + + do { + (void) vm_debug_cpus(vmm->vmm_ctx, &cpuset); + } while (!CPU_ISSET(vcpu, &cpuset)); + + (void) vm_set_capability(vmm->vmm_ctx, vcpu, VM_CAP_MTRAP_EXIT, 0); + + return (ret); +} + +int +vmm_stop(vmm_t *vmm) +{ + int ret = vm_suspend_cpu(vmm->vmm_ctx, -1); + + if (ret == 0) + vmm_update_ncpu(vmm); + + return (ret); +} + +/* + * Mapping of KDI-defined registers to vmmapi-defined registers. + * Registers not known to vmmapi use VM_REG_LAST, which is invalid and + * causes an error in vm_{get,set}_register_set(). + * + * This array must be kept in sync with the definitions in kdi_regs.h. + */ +static int vmm_kdi_regmap[] = { + VM_REG_LAST, /* KDIREG_SAVFP */ + VM_REG_LAST, /* KDIREG_SAVPC */ + VM_REG_GUEST_RDI, /* KDIREG_RDI */ + VM_REG_GUEST_RSI, /* KDIREG_RSI */ + VM_REG_GUEST_RDX, /* KDIREG_RDX */ + VM_REG_GUEST_RCX, /* KDIREG_RCX */ + VM_REG_GUEST_R8, /* KDIREG_R8 */ + VM_REG_GUEST_R9, /* KDIREG_R9 */ + VM_REG_GUEST_RAX, /* KDIREG_RAX */ + VM_REG_GUEST_RBX, /* KDIREG_RBX */ + VM_REG_GUEST_RBP, /* KDIREG_RBP */ + VM_REG_GUEST_R10, /* KDIREG_R10 */ + VM_REG_GUEST_R11, /* KDIREG_R11 */ + VM_REG_GUEST_R12, /* KDIREG_R12 */ + VM_REG_GUEST_R13, /* KDIREG_R13 */ + VM_REG_GUEST_R14, /* KDIREG_R14 */ + VM_REG_GUEST_R15, /* KDIREG_R15 */ + VM_REG_LAST, /* KDIREG_FSBASE */ + VM_REG_LAST, /* KDIREG_GSBASE */ + VM_REG_LAST, /* KDIREG_KGSBASE */ + VM_REG_GUEST_CR2, /* KDIREG_CR2 */ + VM_REG_GUEST_CR3, /* KDIREG_CR3 */ + VM_REG_GUEST_DS, /* KDIREG_DS */ + VM_REG_GUEST_ES, /* KDIREG_ES */ + VM_REG_GUEST_FS, /* KDIREG_FS */ + VM_REG_GUEST_GS, /* KDIREG_GS */ + VM_REG_LAST, /* KDIREG_TRAPNO */ + VM_REG_LAST, /* KDIREG_ERR */ + VM_REG_GUEST_RIP, /* KDIREG_RIP */ + VM_REG_GUEST_CS, /* KDIREG_CS */ + VM_REG_GUEST_RFLAGS, /* KDIREG_RFLAGS */ + VM_REG_GUEST_RSP, /* KDIREG_RSP */ + VM_REG_GUEST_SS /* KDIREG_SS */ +}; +CTASSERT(ARRAY_SIZE(vmm_kdi_regmap) == KDIREG_NGREG); + +/* + * Mapping of libvmm-defined registers to vmmapi-defined registers. + * + * This array must be kept in sync with the definitions in libvmm.h + */ +static int vmm_sys_regmap[] = { + VM_REG_GUEST_CR0, /* VMM_REG_CR0 */ + VM_REG_GUEST_CR2, /* VMM_REG_CR2 */ + VM_REG_GUEST_CR3, /* VMM_REG_CR3 */ + VM_REG_GUEST_CR4, /* VMM_REG_CR4 */ + VM_REG_GUEST_DR0, /* VMM_REG_DR0 */ + VM_REG_GUEST_DR1, /* VMM_REG_DR1 */ + VM_REG_GUEST_DR2, /* VMM_REG_DR2 */ + VM_REG_GUEST_DR3, /* VMM_REG_DR3 */ + VM_REG_GUEST_DR6, /* VMM_REG_DR6 */ + VM_REG_GUEST_DR7, /* VMM_REG_DR7 */ + VM_REG_GUEST_EFER, /* VMM_REG_EFER */ + VM_REG_GUEST_PDPTE0, /* VMM_REG_PDPTE0 */ + VM_REG_GUEST_PDPTE1, /* VMM_REG_PDPTE1 */ + VM_REG_GUEST_PDPTE2, /* VMM_REG_PDPTE2 */ + VM_REG_GUEST_PDPTE3, /* VMM_REG_PDPTE3 */ + VM_REG_GUEST_INTR_SHADOW, /* VMM_REG_INTR_SHADOW */ +}; + +/* + * Mapping of libvmm-defined descriptors to vmmapi-defined descriptors. + * + * This array must be kept in sync with the definitions in libvmm.h + */ +static int vmm_descmap[] = { + VM_REG_GUEST_GDTR, + VM_REG_GUEST_LDTR, + VM_REG_GUEST_IDTR, + VM_REG_GUEST_TR, + VM_REG_GUEST_CS, + VM_REG_GUEST_DS, + VM_REG_GUEST_ES, + VM_REG_GUEST_FS, + VM_REG_GUEST_GS, + VM_REG_GUEST_SS +}; + +static int +vmm_mapreg(int reg) +{ + errno = 0; + + if (reg < 0) + goto fail; + + if (reg < KDIREG_NGREG) + return (vmm_kdi_regmap[reg]); + + if (reg >= VMM_REG_OFFSET && + reg < VMM_REG_OFFSET + ARRAY_SIZE(vmm_sys_regmap)) + return (vmm_sys_regmap[reg - VMM_REG_OFFSET]); + +fail: + errno = EINVAL; + return (VM_REG_LAST); +} + +static int +vmm_mapdesc(int desc) +{ + errno = 0; + + if (desc >= VMM_DESC_OFFSET && + desc < VMM_DESC_OFFSET + ARRAY_SIZE(vmm_descmap)) + return (vmm_descmap[desc - VMM_DESC_OFFSET]); + + errno = EINVAL; + return (VM_REG_LAST); +} + +int +vmm_getreg(vmm_t *vmm, int vcpu, int reg, uint64_t *val) +{ + reg = vmm_mapreg(reg); + + if (reg == VM_REG_LAST) + return (-1); + + return (vm_get_register(vmm->vmm_ctx, vcpu, reg, val)); +} + +int +vmm_setreg(vmm_t *vmm, int vcpu, int reg, uint64_t val) +{ + reg = vmm_mapreg(reg); + + if (reg == VM_REG_LAST) + return (-1); + + return (vm_set_register(vmm->vmm_ctx, vcpu, reg, val)); +} + +int +vmm_get_regset(vmm_t *vmm, int vcpu, size_t nregs, const int *regnums, + uint64_t *regvals) +{ + int *vm_regnums; + int i; + int ret = -1; + + vm_regnums = malloc(sizeof (int) * nregs); + if (vm_regnums == NULL) + return (ret); + + for (i = 0; i != nregs; i++) { + vm_regnums[i] = vmm_mapreg(regnums[i]); + if (vm_regnums[i] == VM_REG_LAST) + goto fail; + } + + ret = vm_get_register_set(vmm->vmm_ctx, vcpu, nregs, vm_regnums, + regvals); + +fail: + free(vm_regnums); + return (ret); +} + +int +vmm_set_regset(vmm_t *vmm, int vcpu, size_t nregs, const int *regnums, + uint64_t *regvals) +{ + int *vm_regnums; + int i; + int ret = -1; + + vm_regnums = malloc(sizeof (int) * nregs); + if (vm_regnums == NULL) + return (ret); + + for (i = 0; i != nregs; i++) { + vm_regnums[i] = vmm_mapreg(regnums[i]); + if (vm_regnums[i] == VM_REG_LAST) + goto fail; + } + + ret = vm_set_register_set(vmm->vmm_ctx, vcpu, nregs, vm_regnums, + regvals); + +fail: + free(vm_regnums); + return (ret); +} + +int +vmm_get_desc(vmm_t *vmm, int vcpu, int desc, vmm_desc_t *vd) +{ + desc = vmm_mapdesc(desc); + if (desc == VM_REG_LAST) + return (-1); + + return (vm_get_desc(vmm->vmm_ctx, vcpu, desc, &vd->vd_base, &vd->vd_lim, + &vd->vd_acc)); +} + +int +vmm_set_desc(vmm_t *vmm, int vcpu, int desc, vmm_desc_t *vd) +{ + desc = vmm_mapdesc(desc); + if (desc == VM_REG_LAST) + return (-1); + + return (vm_set_desc(vmm->vmm_ctx, vcpu, desc, vd->vd_base, vd->vd_lim, + vd->vd_acc)); +} + +/* + * Structure to hold MMU state during address translation. + * The contents of vmm_mmu_regnum[] must be kept in sync with this. + */ +typedef struct vmm_mmu { + uint64_t vm_cr0; + uint64_t vm_cr3; + uint64_t vm_cr4; + uint64_t vm_efer; +} vmm_mmu_t; + +static const int vmm_mmu_regnum[] = { + VMM_REG_CR0, + VMM_REG_CR3, + VMM_REG_CR4, + VMM_REG_EFER +}; + +#define X86_PTE_P 0x001ULL +#define X86_PTE_PS 0x080ULL + +#define X86_PTE_PHYSMASK 0x000ffffffffff000ULL +#define X86_PAGE_SHIFT 12 +#define X86_PAGE_SIZE (1ULL << X86_PAGE_SHIFT) + +#define X86_SEG_CODE_DATA (1ULL << 4) +#define X86_SEG_PRESENT (1ULL << 7) +#define X86_SEG_LONG (1ULL << 13) +#define X86_SEG_BIG (1ULL << 14) +#define X86_SEG_GRANULARITY (1ULL << 15) +#define X86_SEG_UNUSABLE (1ULL << 16) + +#define X86_SEG_USABLE (X86_SEG_PRESENT | X86_SEG_CODE_DATA) +#define X86_SEG_USABLE_MASK (X86_SEG_UNUSABLE | X86_SEG_USABLE) + +/* + * vmm_pte2paddr: + * + * Recursively calculate the physical address from a virtual address, + * starting at the given PTE level using the given PTE. + */ +static int +vmm_pte2paddr(vmm_t *vmm, uint64_t pte, boolean_t ia32, int level, + uint64_t vaddr, uint64_t *paddr) +{ + int pte_size = ia32 ? sizeof (uint32_t) : sizeof (uint64_t); + int off_bits = ia32 ? 10 : 9; + boolean_t hugepage = B_FALSE; + uint64_t offset; + uint64_t off_mask, off_shift; + + if (level < 4 && (pte & X86_PTE_P) == 0) { + errno = EFAULT; + return (-1); + } + + off_shift = X86_PAGE_SHIFT + off_bits * level; + off_mask = (1ULL << off_shift) - 1; + + offset = vaddr & off_mask; + + if ((level == 1 || level == 2) && (pte & X86_PTE_PS) != 0) { + hugepage = B_TRUE; + } else { + if (level > 0) { + offset >>= off_shift - off_bits; + offset <<= X86_PAGE_SHIFT - off_bits; + } + off_mask = 0xfff; + } + + *paddr = (pte & X86_PTE_PHYSMASK & ~off_mask) + offset; + + if (level == 0 || hugepage) + return (0); + + pte = 0; + if (vmm_pread(vmm, &pte, pte_size, *paddr) != pte_size) + return (-1); + return (vmm_pte2paddr(vmm, pte, ia32, level - 1, vaddr, paddr)); +} + +static vmm_mode_t +vmm_vcpu_mmu_mode(vmm_t *vmm, int vcpu, vmm_mmu_t *mmu) +{ + if ((mmu->vm_cr0 & CR0_PE) == 0) + return (VMM_MODE_REAL); + else if ((mmu->vm_cr4 & CR4_PAE) == 0) + return (VMM_MODE_PROT); + else if ((mmu->vm_efer & AMD_EFER_LME) == 0) + return (VMM_MODE_PAE); + else + return (VMM_MODE_LONG); +} + +vmm_mode_t +vmm_vcpu_mode(vmm_t *vmm, int vcpu) +{ + vmm_mmu_t mmu = { 0 }; + + if (vmm_get_regset(vmm, vcpu, ARRAY_SIZE(vmm_mmu_regnum), + vmm_mmu_regnum, (uint64_t *)&mmu) != 0) + return (VMM_MODE_UNKNOWN); + + return (vmm_vcpu_mmu_mode(vmm, vcpu, &mmu)); +} + +vmm_isa_t +vmm_vcpu_isa(vmm_t *vmm, int vcpu) +{ + vmm_desc_t cs; + + if (vmm_get_desc(vmm, vcpu, VMM_DESC_CS, &cs) != 0) + return (VMM_ISA_UNKNOWN); + + switch (cs.vd_acc & (X86_SEG_BIG | X86_SEG_LONG)) { + case 0x0: /* 16b code segment */ + return (VMM_ISA_16); + case X86_SEG_LONG: /* 64b code segment */ + return (VMM_ISA_64); + case X86_SEG_BIG: /* 32b code segment */ + return (VMM_ISA_32); + } + + return (VMM_ISA_UNKNOWN); +} + +/* + * vmm_vtol: + * + * Translate a virtual address to a physical address on a certain vCPU, + * using the specified segment register or descriptor according to the mode. + * + */ +int +vmm_vtol(vmm_t *vmm, int vcpu, int seg, uint64_t vaddr, uint64_t *laddr) +{ + vmm_desc_t desc; + uint64_t limit; + + if (vmm_get_desc(vmm, vcpu, seg, &desc) != 0) + return (-1); + + switch (vmm_vcpu_mode(vmm, vcpu)) { + case VMM_MODE_REAL: + if (seg == VMM_DESC_FS || seg == VMM_DESC_GS) + goto fault; + /* FALLTHRU */ + case VMM_MODE_PROT: + case VMM_MODE_PAE: + if ((desc.vd_acc & X86_SEG_USABLE_MASK) != X86_SEG_USABLE) + /* unusable, system segment, or not present */ + goto fault; + + limit = desc.vd_lim; + if (desc.vd_acc & X86_SEG_GRANULARITY) + limit *= 4096; + + if (vaddr > limit) + goto fault; + /* FALLTHRU */ + case VMM_MODE_LONG: + *laddr = desc.vd_base + vaddr; + return (0); + + default: + fault: + errno = EFAULT; + return (-1); + } + +} + +/* + * vmm_vtop: + * + * Translate a virtual address to a guest physical address on a certain vCPU, + * according to the mode the vCPU is in. + */ +int +vmm_vtop(vmm_t *vmm, int vcpu, int seg, uint64_t vaddr, uint64_t *paddr) +{ + vmm_mmu_t mmu = { 0 }; + int ret = 0; + + if (vmm_vtol(vmm, vcpu, seg, vaddr, &vaddr) != 0) + return (-1); + + if (vmm_get_regset(vmm, vcpu, ARRAY_SIZE(vmm_mmu_regnum), + vmm_mmu_regnum, (uint64_t *)&mmu) != 0) + return (-1); + + if ((mmu.vm_cr0 & CR0_PG) == 0) { + /* no paging, physical equals virtual */ + *paddr = vaddr; + return (0); + } + + switch (vmm_vcpu_mmu_mode(vmm, vcpu, &mmu)) { + case VMM_MODE_PROT: + /* protected mode, no PAE: 2-level paging, 32bit PTEs */ + ret = vmm_pte2paddr(vmm, mmu.vm_cr3, B_TRUE, 2, vaddr, paddr); + break; + case VMM_MODE_PAE: + /* protected mode with PAE: 3-level paging, 64bit PTEs */ + ret = vmm_pte2paddr(vmm, mmu.vm_cr3, B_FALSE, 3, vaddr, paddr); + break; + case VMM_MODE_LONG: + /* long mode: 4-level paging, 64bit PTEs */ + ret = vmm_pte2paddr(vmm, mmu.vm_cr3, B_FALSE, 4, vaddr, paddr); + break; + default: + ret = -1; + } + + return (ret); +} + +ssize_t +vmm_vread(vmm_t *vmm, int vcpu, int seg, void *buf, size_t len, uintptr_t addr) +{ + ssize_t res = 0; + uint64_t paddr; + size_t plen; + uint64_t boundary; + + while (len != 0) { + if (vmm_vtop(vmm, vcpu, seg, addr, &paddr) != 0) { + errno = EFAULT; + return (0); + } + + boundary = (addr + X86_PAGE_SIZE) & ~(X86_PAGE_SIZE - 1); + if (addr + len > boundary) + plen = boundary - addr; + else + plen = len; + + if (vmm_pread(vmm, buf, plen, paddr) != plen) + return (0); + len -= plen; + addr += plen; + buf += plen; + res += plen; + } + + return (res); +} + +ssize_t +vmm_vwrite(vmm_t *vmm, int vcpu, int seg, const void *buf, size_t len, + uintptr_t addr) +{ + ssize_t res = 0; + uint64_t paddr; + size_t plen; + uint64_t boundary; + + while (len != 0) { + if (vmm_vtop(vmm, vcpu, seg, addr, &paddr) != 0) { + errno = EFAULT; + return (0); + } + + boundary = (addr + X86_PAGE_SIZE) & ~(X86_PAGE_SIZE - 1); + if (addr + len > boundary) + plen = boundary - addr; + else + plen = len; + + if (vmm_pwrite(vmm, buf, plen, paddr) != plen) + return (0); + len -= plen; + addr += plen; + buf += plen; + res += plen; + } + + return (res); +} diff --git a/usr/src/lib/libvmm/libvmm.h b/usr/src/lib/libvmm/libvmm.h new file mode 100644 index 0000000000..352b09e970 --- /dev/null +++ b/usr/src/lib/libvmm/libvmm.h @@ -0,0 +1,122 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +#ifndef _LIBVMM_H +#define _LIBVMM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct vmm vmm_t; + +typedef struct vmm_desc { + uint64_t vd_base; + uint32_t vd_lim; + uint32_t vd_acc; +} vmm_desc_t; + + +/* + * This enum must be kept in sync with vmm_sys_regmap[] in libvmm.c. + */ +#define VMM_REG_OFFSET 0x100 +enum vmm_regs { + VMM_REG_CR0 = VMM_REG_OFFSET, + VMM_REG_CR2, + VMM_REG_CR3, + VMM_REG_CR4, + VMM_REG_DR0, + VMM_REG_DR1, + VMM_REG_DR2, + VMM_REG_DR3, + VMM_REG_DR6, + VMM_REG_DR7, + VMM_REG_EFER, + VMM_REG_PDPTE0, + VMM_REG_PDPTE1, + VMM_REG_PDPTE2, + VMM_REG_PDPTE3, + VMM_REG_INTR_SHADOW +}; + +/* + * This enum must be kept in sync with vmm_descmap[] in libvmm.c. + */ +#define VMM_DESC_OFFSET 0x200 +enum vmm_descs { + VMM_DESC_GDTR = VMM_DESC_OFFSET, + VMM_DESC_LDTR, + VMM_DESC_IDTR, + VMM_DESC_TR, + VMM_DESC_CS, + VMM_DESC_DS, + VMM_DESC_ES, + VMM_DESC_FS, + VMM_DESC_GS, + VMM_DESC_SS +}; + +typedef enum { + VMM_MODE_UNKNOWN = 0, + VMM_MODE_REAL, + VMM_MODE_PROT, + VMM_MODE_PAE, + VMM_MODE_LONG +} vmm_mode_t; + +typedef enum { + VMM_ISA_UNKNOWN = 0, + VMM_ISA_16, + VMM_ISA_32, + VMM_ISA_64 +} vmm_isa_t; + +vmm_t *vmm_open_vm(const char *); +void vmm_close_vm(vmm_t *); + +int vmm_map(vmm_t *, boolean_t); +void vmm_unmap(vmm_t *); + +ssize_t vmm_pread(vmm_t *, void *, size_t, uintptr_t); +ssize_t vmm_pwrite(vmm_t *, const void *, size_t, uintptr_t); +ssize_t vmm_vread(vmm_t *, int, int, void *, size_t, uintptr_t); +ssize_t vmm_vwrite(vmm_t *, int, int, const void *, size_t, uintptr_t); + +size_t vmm_ncpu(vmm_t *); +size_t vmm_memsize(vmm_t *); + +int vmm_cont(vmm_t *); +int vmm_step(vmm_t *, int); +int vmm_stop(vmm_t *); + +int vmm_getreg(vmm_t *, int, int, uint64_t *); +int vmm_setreg(vmm_t *, int, int, uint64_t); +int vmm_get_regset(vmm_t *, int, size_t, const int *, uint64_t *); +int vmm_set_regset(vmm_t *, int, size_t, const int *, uint64_t *); + +int vmm_get_desc(vmm_t *, int, int, vmm_desc_t *); +int vmm_set_desc(vmm_t *, int, int, vmm_desc_t *); + +vmm_mode_t vmm_vcpu_mode(vmm_t *, int); +vmm_isa_t vmm_vcpu_isa(vmm_t *, int); +int vmm_vtol(vmm_t *, int, int, uint64_t, uint64_t *); +int vmm_vtop(vmm_t *, int, int, uint64_t, uint64_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBVMM_H */ diff --git a/usr/src/lib/libvmm/mapfile-vers b/usr/src/lib/libvmm/mapfile-vers new file mode 100644 index 0000000000..19a15802ac --- /dev/null +++ b/usr/src/lib/libvmm/mapfile-vers @@ -0,0 +1,60 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018 Joyent, Inc. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# + +$mapfile_version 2 + +SYMBOL_VERSION ILLUMOSprivate { + global: + vmm_open_vm; + vmm_close_vm; + vmm_map; + vmm_unmap; + vmm_pread; + vmm_pwrite; + vmm_ncpu; + vmm_memsize; + vmm_cont; + vmm_step; + vmm_stop; + vmm_setreg; + vmm_getreg; + vmm_set_regset; + vmm_get_regset; + vmm_set_desc; + vmm_get_desc; + vmm_vcpu_isa; + vmm_vcpu_mode; + vmm_vtol; + vmm_vtop; + vmm_vread; + vmm_vwrite; + + local: + *; +}; diff --git a/usr/src/lib/libvmmapi/common/mapfile-vers b/usr/src/lib/libvmmapi/common/mapfile-vers index 397ebd7d59..f8fe636386 100644 --- a/usr/src/lib/libvmmapi/common/mapfile-vers +++ b/usr/src/lib/libvmmapi/common/mapfile-vers @@ -40,6 +40,7 @@ SYMBOL_VERSION ILLUMOSprivate { vm_assign_pptdev; vm_capability_name2type; vm_capability_type2name; + vm_close; vm_copy_setup; vm_copy_teardown; vm_copyin; @@ -53,6 +54,7 @@ SYMBOL_VERSION ILLUMOSprivate { vm_get_capability; vm_get_desc; vm_get_device_fd; + vm_get_devmem_offset; vm_get_gpa_pmap; vm_get_hpet_capabilities; vm_get_highmem_size; diff --git a/usr/src/lib/libvmmapi/common/vmmapi.c b/usr/src/lib/libvmmapi/common/vmmapi.c index ceac495746..bae214aba0 100644 --- a/usr/src/lib/libvmmapi/common/vmmapi.c +++ b/usr/src/lib/libvmmapi/common/vmmapi.c @@ -179,10 +179,32 @@ vm_open(const char *name) return (vm); err: +#ifdef __FreeBSD__ vm_destroy(vm); +#else + /* + * As libvmmapi is used by other programs to query and control bhyve + * VMs, destroying a VM just because the open failed isn't useful. We + * have to free what we have allocated, though. + */ + free(vm); +#endif return (NULL); } +#ifndef __FreeBSD__ +void +vm_close(struct vmctx *vm) +{ + assert(vm != NULL); + assert(vm->fd >= 0); + + (void) close(vm->fd); + + free(vm); +} +#endif + void vm_destroy(struct vmctx *vm) { @@ -551,6 +573,22 @@ vm_get_highmem_size(struct vmctx *ctx) return (ctx->highmem); } +#ifndef __FreeBSD__ +int +vm_get_devmem_offset(struct vmctx *ctx, int segid, off_t *mapoff) +{ + struct vm_devmem_offset vdo; + int error; + + vdo.segid = segid; + error = ioctl(ctx->fd, VM_DEVMEM_GETOFFSET, &vdo); + if (error == 0) + *mapoff = vdo.offset; + + return (error); +} +#endif + void * vm_create_devmem(struct vmctx *ctx, int segid, const char *name, size_t len) { @@ -583,17 +621,8 @@ vm_create_devmem(struct vmctx *ctx, int segid, const char *name, size_t len) if (fd < 0) goto done; #else - { - struct vm_devmem_offset vdo; - - vdo.segid = segid; - error = ioctl(ctx->fd, VM_DEVMEM_GETOFFSET, &vdo); - if (error == 0) { - mapoff = vdo.offset; - } else { - goto done; - } - } + if (vm_get_devmem_offset(ctx, segid, &mapoff) != 0) + goto done; #endif /* diff --git a/usr/src/lib/libvmmapi/common/vmmapi.h b/usr/src/lib/libvmmapi/common/vmmapi.h index 1b08a9cae5..6cb7a1186d 100644 --- a/usr/src/lib/libvmmapi/common/vmmapi.h +++ b/usr/src/lib/libvmmapi/common/vmmapi.h @@ -114,6 +114,13 @@ int vm_mmap_getnext(struct vmctx *ctx, vm_paddr_t *gpa, int *segid, void *vm_create_devmem(struct vmctx *ctx, int segid, const char *name, size_t len); +#ifndef __FreeBSD__ +/* + * Return the map offset for the device memory segment 'segid'. + */ +int vm_get_devmem_offset(struct vmctx *ctx, int segid, off_t *mapoff); +#endif + /* * Map the memory segment identified by 'segid' into the guest address space * at [gpa,gpa+len) with protection 'prot'. @@ -124,6 +131,9 @@ int vm_mmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, int segid, int vm_create(const char *name); int vm_get_device_fd(struct vmctx *ctx); struct vmctx *vm_open(const char *name); +#ifndef __FreeBSD__ +void vm_close(struct vmctx *ctx); +#endif void vm_destroy(struct vmctx *ctx); int vm_parse_memsize(const char *optarg, size_t *memsize); int vm_setup_memory(struct vmctx *ctx, size_t len, enum vm_mmap_style s); diff --git a/usr/src/man/man1/mdb.1 b/usr/src/man/man1/mdb.1 index 8fdd91e661..54f00f4b61 100644 --- a/usr/src/man/man1/mdb.1 +++ b/usr/src/man/man1/mdb.1 @@ -5,13 +5,13 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH MDB 1 "Feb 21, 2019" +.TH MDB 1 "May 20, 2020" .SH NAME mdb \- modular debugger .SH SYNOPSIS .LP .nf -\fBmdb\fR [\fB-fkmuwyAFKMSUW\fR] [\(+-o \fIoption\fR] [\fB-p\fR \fIpid\fR] [\fB-s\fR \fIdistance\fR] +\fBmdb\fR [\fB-fkmuwyAFKMSUW\fR] [\(+-o \fIoption\fR] [\fB-b\fR \fIVM\fR] [\fB-p\fR \fIpid\fR] [\fB-s\fR \fIdistance\fR] [\fB-I\fR \fIpath\fR] [\fB-L\fR \fIpath\fR] [\fB-P\fR \fIprompt\fR] [\fB-R\fR \fIroot\fR] [\fB-V\fR \fIdis-version\fR] [\fB-e\fR \fIexpr\fR] [object [core] | core | suffix] .fi @@ -50,12 +50,13 @@ different contexts, including live and post-mortem. .LP The \fItarget\fR is the program being inspected by the debugger. \fBmdb\fR currently provides support for the following types of targets: user processes, -user process core files, the live operating system (via \fB/dev/kmem\fR and -\fB/dev/ksyms\fR), operating system crash dumps, user process images recorded -inside an operating system crash dump, \fBELF\fR object files, and raw binary -files. Each target exports a standard set of properties, including one or more -address spaces, one or more symbol tables, a set of load objects, and a set of -threads that can be examined using the debugger commands described below. +user process core files, live bhyve VMs, the live operating system (via +\fB/dev/kmem\fR and \fB/dev/ksyms\fR), operating system crash dumps, user +process images recorded inside an operating system crash dump, \fBELF\fR object +files, and raw binary files. Each target exports a standard set of properties, +including one or more address spaces, one or more symbol tables, a set of load +objects, and a set of threads that can be examined using the debugger commands +described below. .sp .LP A debugger command, or \fIdcmd\fR (pronounced dee-command) in \fBmdb\fR @@ -3695,6 +3696,15 @@ process or core file, or to the loaded kernel modules in the live operating system or an operating system crash dump. .RE +.sp +.ne 2 +.na +\fB\fB-b\fR \fIVM\fR\fR +.ad +.RS 15n +Attaches to and stops the specified bhyve VM. +.RE + .sp .ne 2 .na diff --git a/usr/src/pkg/manifests/system-library-bhyve.mf b/usr/src/pkg/manifests/system-library-bhyve.mf index 3c7e52c938..5408778c90 100644 --- a/usr/src/pkg/manifests/system-library-bhyve.mf +++ b/usr/src/pkg/manifests/system-library-bhyve.mf @@ -28,6 +28,7 @@ dir path=lib/$(ARCH64) group=bin dir path=usr group=sys dir path=usr/lib group=bin dir path=usr/lib/$(ARCH64) group=bin +file path=lib/$(ARCH64)/libvmm.so.1 file path=lib/$(ARCH64)/libvmmapi.so.1 file path=usr/lib/$(ARCH64)/libppt.so.1 file path=usr/lib/libppt.so.1 diff --git a/usr/src/uts/i86pc/io/vmm/vmm.c b/usr/src/uts/i86pc/io/vmm/vmm.c index dd24a18f6a..47a5f26cb7 100644 --- a/usr/src/uts/i86pc/io/vmm/vmm.c +++ b/usr/src/uts/i86pc/io/vmm/vmm.c @@ -2116,6 +2116,10 @@ restart: break; } + case VM_EXITCODE_MTRAP: + vm_suspend_cpu(vm, vcpuid); + retu = true; + break; #endif default: retu = true; /* handled in userland */ diff --git a/usr/src/uts/intel/sys/controlregs.h b/usr/src/uts/intel/sys/controlregs.h index 43b5247274..0be7b3b650 100644 --- a/usr/src/uts/intel/sys/controlregs.h +++ b/usr/src/uts/intel/sys/controlregs.h @@ -86,8 +86,8 @@ extern "C" { /* CR3 Register */ -#define CR3_PCD 0x00000010 /* cache disable */ -#define CR3_PWT 0x00000008 /* write through */ +#define CR3_PCD 0x00000010 /* cache disable */ +#define CR3_PWT 0x00000008 /* write through */ #if defined(_ASM) #define CR3_NOINVL_BIT 0x8000000000000000 #else @@ -110,18 +110,22 @@ extern "C" { #define CR4_PCE 0x0100 /* perf-monitoring counter enable */ #define CR4_OSFXSR 0x0200 /* OS fxsave/fxrstor support */ #define CR4_OSXMMEXCPT 0x0400 /* OS unmasked exception support */ - /* 0x0800 reserved */ +#define CR4_UMIP 0x0800 /* user-mode instruction prevention */ /* 0x1000 reserved */ -#define CR4_VMXE 0x2000 -#define CR4_SMXE 0x4000 +#define CR4_VMXE 0x2000 /* VMX enable */ +#define CR4_SMXE 0x4000 /* SMX enable */ + /* 0x8000 reserved */ +#define CR4_FSGSBASE 0x10000 /* FSGSBASE enable */ #define CR4_PCIDE 0x20000 /* PCID enable */ #define CR4_OSXSAVE 0x40000 /* OS xsave/xrestore support */ #define CR4_SMEP 0x100000 /* NX for user pages in kernel */ #define CR4_SMAP 0x200000 /* kernel can't access user pages */ +#define CR4_PKE 0x400000 /* protection key enable */ #define FMT_CR4 \ - "\20\26smap\25smep\23osxsav\22pcide" \ - "\17smxe\16vmxe\13xmme\12fxsr\11pce\10pge" \ + "\20\27pke\26smap\25smep\23osxsav" \ + "\22pcide\20fsgsbase\17smxe\16vmxe" \ + "\14umip\13xmme\12fxsr\11pce\10pge" \ "\7mce\6pae\5pse\4de\3tsd\2pvi\1vme" /* @@ -158,7 +162,9 @@ extern "C" { #define MSR_AMD_EFER 0xc0000080 /* extended feature enable MSR */ +#define AMD_EFER_TCE 0x8000 /* translation cache extension */ #define AMD_EFER_FFXSR 0x4000 /* fast fxsave/fxrstor */ +#define AMD_EFER_LMSLE 0x2000 /* long mode segment limit enable */ #define AMD_EFER_SVME 0x1000 /* svm enable */ #define AMD_EFER_NXE 0x0800 /* no-execute enable */ #define AMD_EFER_LMA 0x0400 /* long mode active (read-only) */ @@ -166,7 +172,7 @@ extern "C" { #define AMD_EFER_SCE 0x0001 /* system call extensions */ #define FMT_AMD_EFER \ - "\20\17ffxsr\15svme\14nxe\13lma\11lme\1sce" + "\20\20tce\17ffxsr\16lmsle\15svme\14nxe\13lma\11lme\1sce" /* AMD's SYSCFG register */ diff --git a/usr/src/uts/intel/sys/debugreg.h b/usr/src/uts/intel/sys/debugreg.h index b537076d26..8528a293ab 100644 --- a/usr/src/uts/intel/sys/debugreg.h +++ b/usr/src/uts/intel/sys/debugreg.h @@ -26,6 +26,9 @@ /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ /* All Rights Reserved */ +/* + * Copyright (c) 2018, Joyent, Inc. All rights reserved. + */ #ifndef _SYS_DEBUGREG_H #define _SYS_DEBUGREG_H @@ -57,6 +60,7 @@ extern "C" { #define DR_ICEALSO 0x2000 /* Flag bit reserved for in-circuit-emulator */ #define DR_SINGLESTEP 0x4000 /* Trap resulting from the single-step flag */ #define DR_TASKSWITCH 0x8000 /* Trap resulting from a task-switch */ +#define DR_IN_RTM 0x10000 /* Trap inside an RTM region */ /* * dr7 controls the rest of the debug registers. @@ -73,6 +77,8 @@ extern "C" { #define DR_CONTROL_RESERVED 0xFC00 /* Bits reserved by Intel */ #define DR_LOCAL_SLOWDOWN 0x100 /* Slow the pipeline for ldt addrs */ #define DR_GLOBAL_SLOWDOWN 0x200 /* Slow the pipeline for gdt addrs */ +#define DR_RTM 0x800 /* Restricted Transactional Memory */ +#define DR_GENERAL_DETECT 0x2000 /* General Detect Enable */ #define DR_LOCAL_ENABLE_SHIFT 0 /* Additional shift: local enable */ #define DR_GLOBAL_ENABLE_SHIFT 1 /* Additional shift: global enable */ @@ -95,6 +101,7 @@ extern "C" { #define DR_LEN_1 0x0 /* Settings for data length */ #define DR_LEN_2 0x4 #define DR_LEN_4 0xC +#define DR_LEN_8 0x8 #ifdef __cplusplus } -- cgit v1.2.3 From c376fe93141769de29a07813de2dfb2c8c4b8481 Mon Sep 17 00:00:00 2001 From: Peter Tribble Date: Sun, 17 May 2020 10:28:10 +0100 Subject: 12745 man page typos Reviewed by: Toomas Soome Approved by: Dan McDonald --- usr/src/man/man1/cp.1 | 34 ++-------------------------------- usr/src/man/man1/elfedit.1 | 33 ++------------------------------- usr/src/man/man1/mail.1 | 30 ++---------------------------- usr/src/man/man1/wait.1 | 32 ++------------------------------ usr/src/man/man1m/ipf.1m | 12 ++---------- usr/src/man/man1m/luxadm.1m | 21 ++++----------------- usr/src/man/man4/proc.4 | 4 ++-- usr/src/man/man5/lf64.5 | 38 +++++++++++++++++--------------------- usr/src/man/man7d/ecpp.7d | 10 ++++------ usr/src/man/man7d/usbprn.7d | 17 ++--------------- 10 files changed, 39 insertions(+), 192 deletions(-) (limited to 'usr/src/man/man1') diff --git a/usr/src/man/man1/cp.1 b/usr/src/man/man1/cp.1 index a4b71a5976..97b64289ad 100644 --- a/usr/src/man/man1/cp.1 +++ b/usr/src/man/man1/cp.1 @@ -45,11 +45,10 @@ .\" Portions Copyright (c) 2007, Sun Microsystems, Inc. All Rights Reserved .\" Copyright 2013 Nexenta Systems, Inc. All rights reserved. .\" -.TH CP 1 "Apr 15, 2013" +.TH CP 1 "May 17, 2020" .SH NAME cp \- copy files .SH SYNOPSIS -.LP .nf \fB/usr/bin/cp\fR [\fB-afip@/\fR] \fIsource_file\fR \fItarget_file\fR .fi @@ -90,8 +89,6 @@ cp \- copy files .fi .SH DESCRIPTION -.sp -.LP In the first synopsis form, neither \fIsource_file\fR nor \fItarget_file\fR are directory files, nor can they have the same name. The \fBcp\fR utility copies the contents of \fIsource_file\fR to the destination path named by @@ -121,8 +118,6 @@ In the third or fourth synopsis forms, one or more directories specified by the \fB-r\fR or \fB-R\fR must be specified. For each \fIsource_dir\fR, \fBcp\fR copies all files and subdirectories. .SH OPTIONS -.sp -.LP The following options are supported for both \fB/usr/bin/cp\fR and \fB/usr/xpg4/bin/cp\fR: .sp @@ -272,8 +267,6 @@ Specifying more than one of the mutually-exclusive options \fB-H\fR, \fB-L\fR, and \fB-P\fR is not considered an error. The last option specified determines the behavior of the utility. .SS "/usr/bin/cp" -.sp -.LP If the \fB-p\fR option is specified with either the \fB-@\fR option or the \fB-/\fR option, \fB/usr/bin/cp\fR behaves as follows .RS +4 @@ -291,10 +284,8 @@ When both \fB-p\fR and \fB-/\fR are specified in any order, the copy fails if extended system attributes cannot be copied. .RE .SS "/usr/xpg4/bin/cp" -.sp -.LP If the \fB-p\fR option is specified with either the \fB-@\fR option or the -\fB-/\fR option, /\fBusr/xpg4/bin/cp\fR behaves as follows: +\fB-/\fR option, \fB/usr/xpg4/bin/cp\fR behaves as follows: .RS +4 .TP .ie t \(bu @@ -311,8 +302,6 @@ determines whether the copy fails if extended system attributes cannot be preserved. .RE .SH OPERANDS -.sp -.LP The following operands are supported: .sp .ne 2 @@ -352,12 +341,9 @@ A pathname of a directory to contain the copied files. .RE .SH USAGE -.sp -.LP See \fBlargefile\fR(5) for the description of the behavior of \fBcp\fR when encountering files greater than or equal to 2 Gbyte ( 2^31 bytes). .SH EXAMPLES -.LP \fBExample 1 \fRCopying a File .sp .LP @@ -462,8 +448,6 @@ $ ls -/c /tmp/file1 .sp .SH ENVIRONMENT VARIABLES -.sp -.LP See \fBenviron\fR(5) for descriptions of the following environment variables that affect the execution of \fBcp\fR: \fBLANG\fR, \fBLC_ALL\fR, \fBLC_COLLATE\fR, \fBLC_CTYPE\fR, \fBLC_MESSAGES\fR, and \fBNLSPATH\fR. @@ -478,8 +462,6 @@ in \fBLC_CTYPE\fR determines the locale for interpretation of sequences of bytes of text data a characters, the behavior of character classes used in the expression defined for the \fByesexpr\fR. See \fBlocale\fR(5). .SH EXIT STATUS -.sp -.LP The following exit values are returned: .sp .ne 2 @@ -500,13 +482,8 @@ An error occurred. .RE .SH ATTRIBUTES -.sp -.LP See \fBattributes\fR(5) for descriptions of the following attributes: .SS "/usr/bin/cp" -.sp - -.sp .TS box; c | c @@ -519,9 +496,6 @@ Interface Stability Committed .TE .SS "/usr/xpg4/bin/cp" -.sp - -.sp .TS box; c | c @@ -534,14 +508,10 @@ Interface Stability Committed .TE .SH SEE ALSO -.sp -.LP \fBchmod\fR(1), \fBchown\fR(1), \fBsetfacl\fR(1), \fButime\fR(2), \fBfgetattr\fR(3C), \fBattributes\fR(5), \fBenviron\fR(5), \fBfsattr\fR(5), \fBlargefile\fR(5), \fBlocale\fR(5), \fBstandards\fR(5) .SH NOTES -.sp -.LP The permission modes of the source file are preserved in the copy. .sp .LP diff --git a/usr/src/man/man1/elfedit.1 b/usr/src/man/man1/elfedit.1 index 7230d8ab13..b8f27fa3a9 100644 --- a/usr/src/man/man1/elfedit.1 +++ b/usr/src/man/man1/elfedit.1 @@ -4,19 +4,16 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH ELFEDIT 1 "Jan 28, 2008" +.TH ELFEDIT 1 "May 17, 2020" .SH NAME elfedit \- examine or edit ELF files .SH SYNOPSIS -.LP .nf \fBelfedit\fR [\fB-adr\fR] [\fB-e\fR \fIcmd\fR] [\fB-L\fR \fIpath\fR] [\fB-o\fR \fBdefault\fR | \fBsimple\fR | \fBnum\fR] [\fIinfile\fR] [\fIoutfile\fR] .fi .SH DESCRIPTION -.sp -.LP \fBelfedit\fR is a tool for examining or modifying the contents of an existing ELF object. Specifically, \fBelfedit\fR is used to modify the ELF metadata contained in the object. Access is provided to most of the ELF data contained @@ -24,8 +21,6 @@ in an object, including the ELF header, section header table, program header table, dynamic section, hardware and software capabilities, string tables, and symbol tables. .SS "Syntax" -.sp -.LP \fBelfedit\fR processes commands from the command line (\fB-e\fR option) or from standard input. If standard input is a terminal, \fBelfedit\fR provides terminal editing capabilities, as well as extensive command completion. ELF @@ -302,8 +297,6 @@ Core built in \fBelfedit\fR commands .RE .SS "Status And Command Documentation" -.sp -.LP Status And Command Documentation .sp .LP @@ -399,8 +392,6 @@ help (\fBsys:help\fR) can be used to obtain help on itself: .sp .SS "Module Search Path" -.sp -.LP \fBelfedit\fR modules are implemented as sharable objects which are loaded on demand. When a module is required, \fBelfedit\fR searches a module path in order to locate the sharable object that implements the module. The path is a @@ -444,7 +435,7 @@ appending or prepending directories to the default path. .ad .RS 6n Root of file system tree holding the \fBelfedit\fR program, assuming that -\fBelfedit\fR is installed as \fBusr/bin/elfedi\fRt within the tree. On a +\fBelfedit\fR is installed as \fBusr/bin/elfedit\fR within the tree. On a standard system, this is simply the standard system root directory (\fB/\fR). On a development system, where the copy of \fBelfedit\fR can be installed elsewhere, the use of \fB%r\fR can be used to ensure that the matching set of @@ -507,8 +498,6 @@ The default search path can be changed by setting the \fBELFEDIT_PATH\fR environment variable, or by using the \fB-L\fR command line option. If you specify both, the \fB-L\fR option supersedes the environment variable. .SH OPTIONS -.sp -.LP The following options are supported: .sp .ne 2 @@ -628,8 +617,6 @@ examination of files for which the user does not have write permission. .RE .SH OPERANDS -.sp -.LP The following operands are supported: .sp .ne 2 @@ -672,8 +659,6 @@ is opened for read-only access, and the modified object contents are written to .RE .SH USAGE -.sp -.LP When supported by the system, \fBelfedit\fR runs as a 64-bit application, capable of processing files greater than or equal to 2 Gbytes (2^31 bytes). .sp @@ -702,8 +687,6 @@ If no \fB-e\fR options are specified, \fBelfedit\fR reads commands from issue the write (\fBsys:write\fR) and quit (\fBsys:quit\fR) commands to save their work and exit when running in this mode. .SH EXIT STATUS -.sp -.LP The following exit values are returned: .sp .ne 2 @@ -733,8 +716,6 @@ Invalid command line options were specified. .RE .SH EXAMPLES -.sp -.LP In the following examples, interactive use of \fBelfedit\fR is shown with the shell prompt (\fB%\fR) and the \fBelfedit\fR prompt (\fB>\fR). Neither of these characters should be entered by the user. @@ -866,7 +847,6 @@ STT_FUNC .sp .SH ENVIRONMENT VARIABLES -.sp .ne 2 .na \fB\fBELFEDIT_PATH\fR\fR @@ -897,7 +877,6 @@ Interactively delivers output from \fBelfedit\fR to the screen. If not set, .RE .SH FILES -.sp .ne 2 .na \fB\fB/usr/lib/elfedit\fR\fR @@ -918,8 +897,6 @@ Personal \fBtecla\fR customization file for command line editing. See .RE .SH ATTRIBUTES -.sp -.LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -934,8 +911,6 @@ Interface Stability Committed .TE .SH SEE ALSO -.sp -.LP \fBdump\fR(1), \fBelfdump\fR(1), \fBld.so.1\fR(1), \fBmore\fR(1), \fBnm\fR(1), \fBpvs\fR(1), \fBelf\fR(3ELF), \fBlibelf\fR(3LIB), \fBtecla\fR(5), \fBattributes\fR(5) @@ -943,8 +918,6 @@ Interface Stability Committed .LP \fILinker and Libraries Guide\fR .SH WARNINGS -.sp -.LP \fBelfedit\fR is designed to be a tool for testing and development of the ELF system. It offers the ability to examine and change nearly every piece of ELF metadata in the object. It quietly allows edits that can produce an invalid or @@ -965,8 +938,6 @@ Higher level operations, such as the use of the \fBdyn:runpath\fR command to change the \fBrunpath\fR of an object, are safe, and can be carried out without the sort of risk detailed in this section. .SH NOTES -.sp -.LP Not every ELF operation supported by \fBelfedit\fR can be successfully carried out on every ELF object. \fBelfedit\fR is constrained by the existing sections found in the file. diff --git a/usr/src/man/man1/mail.1 b/usr/src/man/man1/mail.1 index 8aad4de37e..5d8bc7b84c 100644 --- a/usr/src/man/man1/mail.1 +++ b/usr/src/man/man1/mail.1 @@ -44,12 +44,11 @@ .\" Portions Copyright (c) 1992, X/Open Company Limited All Rights Reserved .\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved .\" -.TH MAIL 1 "Jul 24, 2008" +.TH MAIL 1 "May 17, 2020" .SH NAME mail, rmail \- read mail or send mail to users .SH SYNOPSIS .SS "Sending Mail" -.LP .nf \fBmail\fR [\fB-tw\fR] [\fB-m\fR \fImessage_type\fR] \fIrecipient\fR... .fi @@ -60,20 +59,16 @@ mail, rmail \- read mail or send mail to users .fi .SS "Reading Mail" -.LP .nf \fBmail\fR [\fB-ehpPqr\fR] [\fB-f\fR \fIfile\fR] .fi .SS "Debugging" -.LP .nf \fBmail\fR [\fB-x\fR \fIdebug_level\fR] [\fIother_mail_options\fR] \fIrecipient\fR... .fi .SH DESCRIPTION -.sp -.LP A \fIrecipient\fR is usually a domain style address ("\fIuser\fR@\fImachine\fR") or a user name recognized by \fBlogin\fR(1). When \fIrecipient\fRs are named, \fBmail\fR assumes a message is being sent. It @@ -119,8 +114,6 @@ consists of only header lines with no message content. Header lines may be continued on the following line if that line starts with white space. .SH OPTIONS .SS "Sending Mail" -.sp -.LP The following command-line arguments affect sending mail: .sp .ne 2 @@ -202,8 +195,6 @@ extended network (such as \fBsysa!sysb!sysc!user\fR or .RE .SS "Reading Mail" -.sp -.LP The following command-line arguments affect reading mail: .sp .ne 2 @@ -545,8 +536,6 @@ preservation using the \fBDEL_EMPTY_MAILFILE\fR option of \fBmailcnfg\fR.) The group \fBID\fR of the mailfile must be \fBmail\fR to allow new messages to be delivered, and the mailfile must be writable by group \fBmail\fR. .SS "Debugging" -.sp -.LP The following command-line arguments cause \fBmail\fR to provide debugging information: .sp @@ -572,8 +561,6 @@ overrides any specification of \fBDEBUG\fR in \fB/etc/mail/mailcnfg\fR. The information provided by the \fB-x\fR option is esoteric and is probably only useful to system administrators. .SS "Delivery Notification" -.sp -.LP Several forms of notification are available for mail by including one of the following lines in the message header. .sp @@ -640,8 +627,6 @@ Same as \fB/return\fR except that the original message is not returned. The default is \fB/nodelivery/return\fR. If contradictory options are used, the first is recognized and later, conflicting, terms are ignored. .SH OPERANDS -.sp -.LP The following operand is supported for sending mail: .sp .ne 2 @@ -654,14 +639,10 @@ recognized by \fBlogin\fR(1). .RE .SH USAGE -.sp -.LP See \fBlargefile\fR(5) for the description of the behavior of \fBmail\fR and \fBrmail\fR when encountering files greater than or equal to 2 Gbyte ( 2^31 bytes). .SH ENVIRONMENT VARIABLES -.sp -.LP See \fBenviron\fR(5) for descriptions of the following environment variables that affect the execution of \fBmail\fR: \fBLC_CTYPE\fR, \fBLC_MESSAGES\fR, and \fBNLSPATH\fR. @@ -675,8 +656,6 @@ Determine the timezone used with date and time strings. .RE .SH EXIT STATUS -.sp -.LP The following exit values are returned: .sp .ne 2 @@ -706,7 +685,6 @@ An error occurred after initialization. .RE .SH FILES -.sp .ne 2 .na \fB\fBdead.letter\fR\fR @@ -782,15 +760,13 @@ incoming mail for \fIuser\fR; that is, the \fImailfile\fR .sp .ne 2 .na -\fB\fBvar/tmp/ma\fR*\fR +\fB\fB/var/tmp/ma\fR*\fR .ad .RS 20n temporary file .RE .SH SEE ALSO -.sp -.LP \fBchmod\fR(1), \fBcsh\fR(1), \fBlogin\fR(1), \fBmailx\fR(1), \fBuucp\fR(1C), \fBuuencode\fR(1C), \fBvacation\fR(1), \fBwrite\fR(1), \fBattributes\fR(5), \fBenviron\fR(5), \fBlargefile\fR(5) @@ -798,8 +774,6 @@ temporary file .LP \fISolaris Advanced User\&'s Guide\fR .SH NOTES -.sp -.LP The interpretation and resulting action taken because of the header lines described in the Delivery Notifications section only occur if this version of \fBmail\fR is installed on the system where the delivery (or failure) happens. diff --git a/usr/src/man/man1/wait.1 b/usr/src/man/man1/wait.1 index 6708415364..67e87e8a95 100644 --- a/usr/src/man/man1/wait.1 +++ b/usr/src/man/man1/wait.1 @@ -45,23 +45,20 @@ .\" Portions Copyright (c) 1982-2007 AT&T Knowledge Ventures .\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved .\" -.TH WAIT 1 "Mar 13, 2008" +.TH WAIT 1 "May 17, 2020" .SH NAME wait \- await process completion .SH SYNOPSIS -.LP .nf .fi .SS "/bin/sh" -.LP .nf \fBwait\fR [\fIpid\fR]... .fi .SS "/bin/jsh /bin/ksh /usr/xpg4/bin/sh" -.LP .nf \fBwait\fR [\fIpid\fR]... .fi @@ -72,20 +69,16 @@ wait \- await process completion .fi .SS "/bin/csh" -.LP .nf \fBwait\fR .fi .SS "ksh93" -.LP .nf \fBwait\fR [\fIjob...\fR] .fi .SH DESCRIPTION -.sp -.LP The shell itself executes \fBwait\fR, without creating a new process. If you get the error message \fBcannot fork,too many processes\fR, try using the \fBwait\fR command to clean up your background processes. If this doesn't help, @@ -97,8 +90,6 @@ associated with your login, and to the number the system can keep track of. Not all the processes of a pipeline with three or more stages are children of the shell, and thus cannot be waited for. .SS "/bin/sh, /bin/jsh" -.sp -.LP Wait for your background process whose process \fBID\fR is \fIpid\fR and report its termination status. If \fIpid\fR is omitted, all your shell's currently active background processes are waited for and the return code is \fB0\fR. The @@ -109,12 +100,8 @@ and the argument, \fIjobid\fR, is preceded by a percent sign (\fB%\fR). If \fIpid\fR is not an active process \fBID,\fR the \fBwait\fR utility returns immediately and the return code is \fB0\fR. .SS "csh" -.sp -.LP Wait for your background processes. .SS "ksh" -.sp -.LP When an asynchronous list is started by the shell, the process \fBID\fR of the last command in each element of the asynchronous list becomes known in the current shell execution environment. @@ -138,8 +125,6 @@ is the exit status of the process requested by the last \fIpid\fR or The known process \fBID\fRs are applicable only for invocations of \fBwait\fR in the current shell execution environment. .SS "ksh93" -.sp -.LP wait with no operands, waits until all jobs known to the invoking shell have terminated. If one or more job operands are specified, wait waits until all of them have completed. Each job can be specified as one of the following: @@ -212,12 +197,10 @@ Refers to the previous job .sp .LP -If one ore more job operands is a process id or process group id not known by +If one or more job operands is a process id or process group id not known by the current shell environment, \fBwait\fR treats each of them as if it were a process that exited with status 127. .SH OPERANDS -.sp -.LP The following operands are supported: .sp .ne 2 @@ -242,8 +225,6 @@ on systems supporting the job control option. .RE .SH USAGE -.sp -.LP On most implementations, \fBwait\fR is a shell built-in. If it is called in a subshell or separate utility execution environment, such as one of the following, @@ -262,7 +243,6 @@ find . -exec wait ... \e; it returns immediately because there is no known process \fBID\fRs to wait for in those environments. .SH EXAMPLES -.LP \fBExample 1 \fRUsing A Script To Identify The Termination Signal .sp .LP @@ -315,15 +295,11 @@ wait %% .sp .SH ENVIRONMENT VARIABLES -.sp -.LP See \fBenviron\fR(5) for descriptions of the following environment variables that affect the execution of \fBwait\fR: \fBLANG\fR, \fBLC_ALL\fR, \fBLC_CTYPE\fR, \fBLC_MESSAGES\fR, and \fBNLSPATH\fR. .SH EXIT STATUS .SS "ksh93" -.sp -.LP The following exit values are returned by the \fBwait\fR built-in in \fBksh93\fR: .sp @@ -347,8 +323,6 @@ shell environment. .RE .SH ATTRIBUTES -.sp -.LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -365,7 +339,5 @@ Standard See \fBstandards\fR(5). .TE .SH SEE ALSO -.sp -.LP \fBcsh\fR(1), \fBjobs\fR(1), \fBksh\fR(1), \fBksh93\fR(1), \fBsh\fR(1), \fBattributes\fR(5), \fBenviron\fR(5), \fBstandards\fR(5) diff --git a/usr/src/man/man1m/ipf.1m b/usr/src/man/man1m/ipf.1m index 5797e8c28e..121556e83c 100644 --- a/usr/src/man/man1m/ipf.1m +++ b/usr/src/man/man1m/ipf.1m @@ -3,11 +3,10 @@ .\" location. .\" Portions Copyright (c) 2009, Sun Microsystems Inc. All Rights Reserved. .\" Portions Copyright (c) 2015, Joyent, Inc. -.TH IPF 1M "April 9, 2016" +.TH IPF 1M "May 17, 2020" .SH NAME ipf \- alter packet filtering lists for IP packet input and output .SH SYNOPSIS -.LP .nf \fBipf\fR [\fB-6AdDEGInoPRrsvVyzZ\fR] [\fB-l\fR block | pass | nomatch] [\fB-T\fR \fIoptionlist\fR] [\fB-F\fR i | o | a | s | S] \fB-f\fR \fIfilename\fR @@ -15,7 +14,6 @@ ipf \- alter packet filtering lists for IP packet input and output .fi .SH DESCRIPTION -.LP The \fBipf\fR utility is part of a suite of commands associated with the Solaris IP Filter feature. See \fBipfilter\fR(5). .sp @@ -34,7 +32,6 @@ matching the order in which they appear when given to \fBipf\fR. \fB/dev/ipl\fR, and \fB/dev/ipstate\fR. The default permissions of these files require \fBipf\fR to be run as root for all operations. .SS "Enabling Solaris IP Filter Feature" -.LP Solaris IP Filter is installed with the Solaris operating system. However, packet filtering is not enabled by default. Use the following procedure to activate the Solaris IP Filter feature. @@ -61,7 +58,7 @@ See \fBipnat\fR(4). 4. (Optional) Create an address pool configuration file. See \fBippool\fR(4). .sp -Create an \fBipool.conf\fR file if you want to refer to a group of addresses as +Create an \fBippool.conf\fR file if you want to refer to a group of addresses as a single address pool. If you want the address pool configuration file to be loaded at boot time, create a file called \fB/etc/ipf/ippool.conf\fR in which to put the address pool. If you do not want the address pool configuration file @@ -158,7 +155,6 @@ If you reboot your system, the IPfilter configuration is automatically activated. .RE .SH OPTIONS -.LP The following options are supported: .sp .ne 2 @@ -469,7 +465,6 @@ affect fragment or state statistics. .RE .SH ZONES -.LP Each non-global zone has two ipfilter instances: the in-zone ipfilter, which can be controlled from both the zone itself and the global zone, and the Global Zone-controlled (GZ-controlled) instance, which can only be controlled @@ -525,7 +520,6 @@ Contains numerous IP Filter examples. .RE .SH ATTRIBUTES -.LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -540,7 +534,6 @@ Interface Stability Committed .TE .SH SEE ALSO -.LP \fBipfstat\fR(1M), \fBipmon\fR(1M), \fBipnat\fR(1M), \fBippool\fR(1M), \fBsvcadm\fR(1M), \fBsvc.ipfd\fR(1M), \fBipf\fR(4), \fBipnat\fR(4), \fBippool\fR(4), \fBattributes\fR(5), \fBipfilter\fR(5), \fBzones(5)\fR @@ -548,6 +541,5 @@ Interface Stability Committed .LP \fI\fR .SH DIAGNOSTICS -.LP Needs to be run as root for the packet filtering lists to actually be affected inside the kernel. diff --git a/usr/src/man/man1m/luxadm.1m b/usr/src/man/man1m/luxadm.1m index 71fc381a8c..4bd782458b 100644 --- a/usr/src/man/man1m/luxadm.1m +++ b/usr/src/man/man1m/luxadm.1m @@ -3,18 +3,16 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH LUXADM 1M "May 13, 2017" +.TH LUXADM 1M "May 17, 2020" .SH NAME luxadm \- administer Sun Fire 880 storage subsystem and FC_AL devices .SH SYNOPSIS -.LP .nf \fBluxadm\fR [\fIoptions\fR]... \fIsubcommand\fR [\fIoptions\fR]... \fIenclosure\fR [,\fIdev\fR] | \fIpathname\fR... .fi .SH DESCRIPTION -.LP The \fBluxadm\fR program is an administrative command that manages the \fBSENA\fR, Sun Fire 880 internal storage subsystem, and individual Fiber Channel Arbitrated Loop (\fBFC_AL\fR) devices. \fBluxadm\fR performs a variety @@ -36,7 +34,6 @@ of the \fBSENA\fR enclosure, and an optional identifier for the particular device in the enclosure. The individual \fBFC_AL\fR devices may be specified by entering the \fBWWN\fR for the device or a port to the device. .SS "Pathname" -.LP Specify the device or controller by either a complete physical pathname or a complete logical pathname. .sp @@ -120,7 +117,6 @@ and a typical logical pathname is: .sp .SS "Enclosure" -.LP For \fBSENA,\fR a device may be identified by its enclosure name and slotname: .br .in +2 @@ -169,7 +165,6 @@ the disk slot number in the Sun Fire 880 internal storage subsystem, \fB0\fR - See \fBdisks\fR(1M) and \fBdevlinks\fR(1M) for additional information on logical names for disks and subsystems. .SH OPTIONS -.LP The following options are supported by all subcommands: .sp .ne 2 @@ -194,7 +189,6 @@ Verbose mode. Options that are specific to particular subcommands are described with the subcommand in the \fBUSAGE\fR section. .SH OPERANDS -.LP The following operands are supported: .sp .ne 2 @@ -315,7 +309,7 @@ pathname. When the \fBSENA's\fR download is complete, the \fBSENA\fR will be reset and the downloaded code executed. If no filename is specified, the default prom image will be used. The default prom image for the \fBSENA\fR is in the -directory \fBusr/lib/locale/C/LC_MESSAGES\fR and is named \fBibfirmware\fR +directory \fB/usr/lib/locale/C/LC_MESSAGES\fR and is named \fBibfirmware\fR .sp When the Sun Fire 880 internal storage subsystem's download is complete, the subsystem resets and the downloaded code begins execution. The default firmware @@ -746,7 +740,6 @@ Spin down the specified disks in a SENA. .RE .SS "SENA, Sun Fire 880 Internal Storage Subsystem, and Individual FC_AL Drive Expert Mode Subcommands" -.LP The following subcommands are for expert use only, and are applicable only to the \fBSENA\fR, Sun Fire 880 internal storage subsystem, and fiber channel loops. They should only be used by users that are knowledgeable about the @@ -867,7 +860,6 @@ the loop that contains the device specified by the enclosure or pathname. .RE .SS "Other Expert Mode Subcommands" -.LP See \fBNOTES\fR for limitations of these subcommands. They should only be used by users that are knowledgeable about the systems they are managing. .sp @@ -955,7 +947,6 @@ Put the specified device online. .RE .SH EXAMPLES -.LP \fBExample 1 \fRDisplaying the \fBSENA\fRs and Individual FC_AL Devices on a System .sp @@ -1207,11 +1198,9 @@ example# \fBluxadm release /dev/rdsk/c1t8d0s2\fR .sp .SH ENVIRONMENT VARIABLES -.LP See \fBenviron\fR(5) for a description of the \fBLANG\fR environment variable that affects the execution of \fBluxadm\fR. .SH EXIT STATUS -.LP The following exit values are returned: .sp .ne 2 @@ -1234,7 +1223,7 @@ An error occurred. .SH FILES .ne 2 .na -\fB\fBusr/lib/firmware/fc_s/fc_s_fcode\fR\fR +\fB\fB/usr/lib/firmware/fc_s/fc_s_fcode\fR\fR .ad .sp .6 .RS 4n @@ -1244,7 +1233,7 @@ An error occurred. .sp .ne 2 .na -\fB\fBusr/lib/locale/C/LC_MESSAGES/ibfirmware\fR\fR +\fB\fB/usr/lib/locale/C/LC_MESSAGES/ibfirmware\fR\fR .ad .sp .6 .RS 4n @@ -1252,11 +1241,9 @@ An error occurred. .RE .SH SEE ALSO -.LP \fBdevlinks\fR(1M), \fBdisks\fR(1M), \fBattributes\fR(5), \fBenviron\fR(5), \fBses\fR(7D) .SH NOTES -.LP Currently, only some device drivers support hot plugging. If hot plugging is attempted on a disk or bus where it is not supported, an error message of the form: diff --git a/usr/src/man/man4/proc.4 b/usr/src/man/man4/proc.4 index b53db24537..53714657e5 100644 --- a/usr/src/man/man4/proc.4 +++ b/usr/src/man/man4/proc.4 @@ -18,7 +18,7 @@ .\" fields enclosed by brackets "[]" replaced with your own identifying .\" information: Portions Copyright [yyyy] [name of copyright owner] .\" -.Dd January 6, 2020 +.Dd May 17, 2020 .Dt PROC 4 .Os .Sh NAME @@ -483,7 +483,7 @@ is the total number of active lwps in the process. is the total number of zombie lwps in the process. A zombie lwp is a non-detached lwp that has terminated but has not been reaped with -.Xr thr_join 3 +.Xr thr_join 3C or .Xr pthread_join 3C . .Pp diff --git a/usr/src/man/man5/lf64.5 b/usr/src/man/man5/lf64.5 index f1be4e3d83..f2c59d78a6 100644 --- a/usr/src/man/man5/lf64.5 +++ b/usr/src/man/man5/lf64.5 @@ -4,11 +4,10 @@ .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] .\" Copyright (c) 2015, Joyent, Inc. All rights reserved. -.TH LF64 5 "Jan 14, 2015" +.TH LF64 5 "May 17, 2020" .SH NAME lf64 \- transitional interfaces for 64-bit file offsets .SH DESCRIPTION -.LP The data types, interfaces, and macros described on this page provide explicit access to 64-bit file offsets. They are accessible through the transitional compilation environment described on the \fBlfcompile64\fR(5) manual page. The @@ -16,7 +15,6 @@ function prototype and semantics of a transitional interface are equivalent to those of the standard version of the call, except that relevant data types are 64-bit entities. .SS "Data Types" -.LP The following tables list the standard data or struct types in the left-hand column and their corresponding explicit 64-bit file offset types in the right-hand column, grouped by header. The absence of an entry in the left-hand @@ -99,7 +97,7 @@ l l . struct \fBstatvfs\fR struct \fBstatvfs64\fR \fBfsblkcnt_t\fR f_blocks; \fBfsblkcnt64_t\fR f_blocks; \fBfsblkcnt_t\fR f_bfree; \fBfsblkcnt64_t\fR f_bfree; - \fBfsblkcnt_t\fR f_bavial; \fBfsblkcnt64_t\fR f_bavial; + \fBfsblkcnt_t\fR f_bavail; \fBfsblkcnt64_t\fR f_bavail; \fBfsfilcnt_t\fR f_files; \fBfsfilcnt64_t\fR f_files; \fBfsfilcnt_t\fR f_ffree; \fBfsfilcnt64_t\fR f_ffree; \fBfsfilcnt_t\fR f_favail; \fBfsfilcnt64_t\fR f_favail; @@ -138,7 +136,6 @@ l l . .TE .SS "System Interfaces" -.LP The following tables display the standard API and the corresponding transitional interfaces for 64-bit file offsets. The interfaces are grouped by header. The interface name and the affected data types are displayed in courier @@ -148,11 +145,11 @@ font. .TS l l l l . -int \fBaio_cancel\fR(..., int \fBaio_cancel64\fR(..., +int \fBaio_cancel\fR(..., int \fBaio_cancel64\fR(..., struct \fBaiocb\fR *); struct \fBaiocb64\fR *); int \fBaio_error\fR( int \fBaio_error64\fR( const struct \fBaiocb\fR *); const struct \fBaiocb64\fR *); -int \fBaio_fsync\fR(..., int \fBaio_fsync64\fR(..., +int \fBaio_fsync\fR(..., int \fBaio_fsync64\fR(..., struct \fBaiocb\fR *); struct \fBaiocb64\fR *); int \fBaio_read\fR(struct \fBaiocb\fR *); int \fBaio_read64\fR(struct \fBaiocb64\fR *); int \fBaio_return\fR(struct \fBaiocb\fR *); int \fBaio_return64\fR(struct \fBaiocb64\fR *); @@ -161,7 +158,7 @@ int \fBaio_suspend\fR( int \fBaio_suspend64\fR( int \fBaio_waitn\fR(aiocb_t *[], int \fBaio_waitn64\fR(aiocb64_t *[], ...); ...); int \fBaio_write\fR(struct \fBaiocb\fR *); int \fBaio_write64\fR(struct \fBaiocb64\fR *); -int \fBlio_listio\fR(..., int \fBlio_listio64\fR(..., +int \fBlio_listio\fR(..., int \fBlio_listio64\fR(..., const struct \fBaiocb\fR *, ...); const struct \fBaiocb64\fR *, ...); .TE @@ -171,12 +168,12 @@ int \fBlio_listio\fR(..., int \fBlio_listio64\fR(..., l l l l . int \fBalphasort\fR( int \fBalphasort64\fR( - const struct dirent **, const struct dirent64 **, + const struct dirent **, const struct dirent64 **, const struct dirent **) const struct dirent64 **) struct \fBdirent *\fR\fBreaddir()\fR; struct \fBdirent64 *\fR\fBreaddir64()\fR; struct \fBdirent *\fR\fBreaddir_r()\fR; struct \fBdirent64 *\fR\fBreaddir64_r()\fR; -int \fBscandir\fR(..., int \fBscandir64\fR(..., - struct dirent *(*[]), struct dirent64 *(*[]), +int \fBscandir\fR(..., int \fBscandir64\fR(..., + struct dirent *(*[]), struct dirent64 *(*[]), int (*)(const struct dirent *), int (*)(const struct dirent64 *), int (*)(const struct dirent **, int (*)(const struct dirent64 **, const struct dirent **)) const struct dirent64 **)) @@ -202,10 +199,10 @@ l l l l . int \fBftw\fR(..., int \fBftw64\fR(..., const struct \fBstat\fR *, ...); const struct \fBstat64\fR *, ...); - + int \fBnftw\fR(.. int \fBnftw64\fR(..., const struct \fBstat\fR *, ...); const struct \fBstat64\fR *, ...); - + .TE .SS "<\fBlibgen.h\fR>" @@ -252,7 +249,7 @@ int \fBaiowrite\fR(..., \fBoff_t\fR, ...); int \fBaiowrite64\fR(..., \fBoff64_t\ l l l l . int \fBgetdents\fR(..., \fBdirent\fR); int \fBgetdents64\fR(..., \fBdirent64\fR); - + .TE .SS "<\fBsys/mman.h\fR>" @@ -278,11 +275,11 @@ int \fBsetrlimit\fR(..., int \fBsetrlimit64\fR(..., .TS l l l l . -ssize_t \fBsendfile\fR(..., ssize_t \fBsendfile64\fR(..., +ssize_t \fBsendfile\fR(..., ssize_t \fBsendfile64\fR(..., \fBoff_t\fR *, ...); \fBoff64_t\fR *, ...); -ssize_t \fBsendfilev\fR(..., const ssize_t \fBsendfilev64\fR(..., const +ssize_t \fBsendfilev\fR(..., const ssize_t \fBsendfilev64\fR(..., const struct \fBsendfilevec\fR *, ...); struct \fBsendfilevec64\fR *, ...); - + .TE .SS "<\fBsys/stat.h\fR>" @@ -291,7 +288,7 @@ ssize_t \fBsendfilev\fR(..., const ssize_t \fBsendfilev64\fR(..., const l l l l . int \fBfstat\fR(..., struct \fBstat\fR *); int \fBfstat64\fR(..., struct \fBstat64\fR *); -int \fBfstatat\fR(..., int \fBfstatat64\fR(..., +int \fBfstatat\fR(..., int \fBfstatat64\fR(..., struct \fBstat\fR *, int); struct \fBstat64\fR *, int); int \fBlstat\fR(..., struct \fBstat\fR *); int \fBlstat64\fR(..., struct \fBstat64\fR *); int \fBstat\fR(..., struct \fBstat\fR *); int \fBstat64\fR(..., struct \fBstat64\fR *); @@ -304,7 +301,7 @@ l l l l . int \fBstatvfs\fR(..., int \fBstatvfs64\fR(..., struct \fBstatvfs\fR *); struct \fBstatvfs64\fR *); -int \fBfstatvfs\fR(..., int \fBfstatvfs64\fR(..., +int \fBfstatvfs\fR(..., int \fBfstatvfs64\fR(..., struct \fBstatvfs\fR *); struct \fBstatvfs64\fR *); .TE @@ -328,7 +325,7 @@ int \fBalphasort\fR( int \fBalphasort64\fR( struct \fBdirect *\fR\fBreaddir()\fR; struct \fBdirect64 *\fR\fBreaddir64()\fR; int \fBscandir\fR(..., int \fBscandir64\fR(..., struct \fBdirect\fR *(*[]);, ...); struct \fBdirect64\fR *(*[]);, ...); - + .TE .SS "<\fBunistd.h\fR>" @@ -347,5 +344,4 @@ int \fBtruncate\fR(..., \fBoff_t\fR); int \fBtruncate64\fR(..., \fBoff64_t\fR); .TE .SH SEE ALSO -.LP \fBlfcompile\fR(5), \fBlfcompile64\fR(5) diff --git a/usr/src/man/man7d/ecpp.7d b/usr/src/man/man7d/ecpp.7d index 7d10e4ee9c..dc5259dbdf 100644 --- a/usr/src/man/man7d/ecpp.7d +++ b/usr/src/man/man7d/ecpp.7d @@ -3,7 +3,7 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH ECPP 7D "Jan 10, 2020" +.TH ECPP 7D "May 17, 2020" .SH NAME ecpp \- IEEE 1284 compliant parallel port driver .SH SYNOPSIS @@ -25,7 +25,7 @@ ecpp@unit-address The \fBecpp\fR driver provides a bi-directional interface to \fIIEEE 1284\fR compliant devices as well as a forward single-directional interface to Centronics devices. In addition to the Centronics protocol, the \fBecpp\fR -driver supports the \fIIEEE 1284\fRCompatibility, Nibble, and ECP protocols. +driver supports the \fIIEEE 1284\fR Compatibility, Nibble, and ECP protocols. \fBECPP_COMPAT_MODE\fR and \fBECPP_CENTRONICS\fR modes of operation have logically identical handshaking protocols, however devices that support \fBECPP_COMPAT_MODE\fR are \fIIEEE 1284\fR compliant devices. \fIIEEE 1284\fR @@ -231,8 +231,7 @@ conditions are ok, \fB0\fR is returned. Otherwise, \fB-1\fR is returned, errno is set to \fBEIO\fR and the state of the status pins is captured. The captured status can be retrieved using the \fBBPPIOC_GETERR\fR \fBioctl\fR(2) call. The \fBtimeout_occurred\fR and \fBbus_error\fR fields will never be set by this -\fBioctl\fR(2). \fBBPPIOC_TESTIO\fR and \fBBPPIOC_GETERR\fR are compatible to -the ioctls specified in \fBbpp\fR(7D). +\fBioctl\fR(2). .RE .sp @@ -450,7 +449,7 @@ Interface stability Evolving .SH SEE ALSO \fBmodload\fR(1M), \fBmodunload\fR(1M), \fBupdate_drv\fR(1M), \fBioctl\fR(2), \fBopen\fR(2), \fBread\fR(2), \fBwrite\fR(2), \fBattributes\fR(5), -\fBbpp\fR(7D), \fBusbprn\fR(7D), \fBprnio\fR(7I), \fBstreamio\fR(7I) +\fBusbprn\fR(7D), \fBprnio\fR(7I), \fBstreamio\fR(7I) .sp .LP \fIIEEE Std 1284-1994\fR @@ -464,4 +463,3 @@ Interface stability Evolving Driver does not support parallel port controller on the given host. Attach failed. .RE - diff --git a/usr/src/man/man7d/usbprn.7d b/usr/src/man/man7d/usbprn.7d index b28b0a7626..9f5d326917 100644 --- a/usr/src/man/man7d/usbprn.7d +++ b/usr/src/man/man7d/usbprn.7d @@ -3,11 +3,10 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH USBPRN 7D "May 13, 2017" +.TH USBPRN 7D "May 17, 2020" .SH NAME usbprn \- USB printer class driver .SH SYNOPSIS -.LP .nf #include .fi @@ -23,7 +22,6 @@ usbprn@unit-address .fi .SH DESCRIPTION -.LP The \fBusbprn\fR driver is a USBA (Solaris USB Architecture) compliant client driver that supports the \fIUSB Printer Class 1.0\fR specification. The \fBusbprn\fR driver supports a subset of the \fBecpp\fR(7D) parallel port @@ -44,14 +42,12 @@ queue. For USB connected printers, it attempts to pre-select the manufacturer and model information based on the 1284 device id supplied by the printer. .SS "UGEN (Generic USB)" -.LP The \fBusbprn\fR driver also supports a \fBugen\fR(7D) interface allowing raw access to the device, for example by libusb applications, by passing the drivers bound to each interface. Because a libusb application might change the state of the device, you should not access the device through the child interface drivers. .SH DEFAULT OPERATION -.LP With certain minor exceptions (outlined in the Notes sections below), the \fBusbprn\fR driver supports a subset of the \fBecpp\fR(7D) ioctl interfaces: .sp @@ -73,7 +69,6 @@ to their default values with each \fBattach\fR(9E). (The \fBecpp\fR(7D) driver resets configuration variables with each \fBopen\fR(2).) .RE .SH WRITE OPERATION -.LP A \fBwrite\fR(2) operation returns the number of bytes successfully written to the device. If a failure occurs while a driver is transferring data to printer, the contents of the status bits are captured at the time of the error and can @@ -81,7 +76,6 @@ be retrieved by the application program using the ECPPIOC_GETERR \fBioctl\fR(2) call. The captured status information is overwritten each time an ECPPIOC_TESTIO \fBioctl\fR(2) occurs. .SH IOCTLS -.LP The \fBusbprn\fR driver supports \fBprnio\fR(7I) interfaces. Note that the \fBPRNIOC_RESET\fR command has no effect on USB printers. .sp @@ -154,8 +148,6 @@ determine if a \fBwrite\fR(2) will succeed. If status bits are set, a transfer will fail. If a transfer will succeed, zero is returned. If a transfer fails, the driver returns \fBEIO\fR and the state of the status bits are captured. The captured status can be retrieved using the BPPIOC_GETERR \fBioctl\fR(2) call. -BPPIOC_TESTIO and BPPIOC_GETERR are compatible to the ioctls specified in -\fBbpp\fR(7D). .LP Note - .sp @@ -243,7 +235,6 @@ Unlike \fBecpp\fR(7D), only the ECPP_CENTRONICS mode is currently supported in .RE .SH READ OPERATION -.LP The \fBread\fR operation is not supported and returns \fBEIO\fR. .SH ERRORS .ne 2 @@ -354,7 +345,6 @@ Character special files .RE .SH ATTRIBUTES -.LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -369,10 +359,9 @@ Architecture SPARC, x86, PCI-based systems .TE .SH SEE ALSO -.LP \fBcfgadm_usb\fR(1M), \fBprintmgr\fR(1M), \fBioctl\fR(2), \fBopen\fR(2), \fBread\fR(2), \fBwrite\fR(2), \fBattributes\fR(5), -\fBbpp\fR(7D), \fBecpp\fR(7D), \fBugen\fR(7D), \fBusba\fR(7D), \fBprnio\fR(7I), +\fBecpp\fR(7D), \fBugen\fR(7D), \fBusba\fR(7D), \fBprnio\fR(7I), \fBattach\fR(9E) .sp .LP @@ -387,7 +376,6 @@ Architecture SPARC, x86, PCI-based systems .LP \fISystem Administration Guide: Basic Administration\fR .SH DIAGNOSTICS -.LP In addition to being logged, the following messages may appear on the system console. All messages are formatted in the following manner: .sp @@ -446,7 +434,6 @@ to the hot-removal may be lost. .RE .SH NOTES -.LP The USB printer will be power managed if the device is closed. .sp .LP -- cgit v1.2.3