summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2018-05-14 22:28:18 +0000
committerJohn Levon <john.levon@joyent.com>2018-05-14 22:28:18 +0000
commite847b91c79ac0a60cba1e1852929eb37e96cf21c (patch)
tree331d6f9d009301d0ad3f313ec629727f7959c86c
parent5f7e4160c0e83ee07bed904fb119988351eac739 (diff)
downloadillumos-joyent-e847b91c79ac0a60cba1e1852929eb37e96cf21c.tar.gz
OS-6760 bhyve passthru devices should use physical path
Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Approved by: Patrick Mooney <patrick.mooney@joyent.com>
-rw-r--r--manifest4
-rw-r--r--usr/src/Makefile.lint3
-rw-r--r--usr/src/cmd/Makefile1
-rw-r--r--usr/src/cmd/pptadm/Makefile43
-rw-r--r--usr/src/cmd/pptadm/pptadm.c205
-rw-r--r--usr/src/cmd/zoneadmd/Makefile.com2
-rw-r--r--usr/src/cmd/zoneadmd/vplat.c12
-rw-r--r--usr/src/cmd/zoneadmd/zoneadmd.c59
-rw-r--r--usr/src/cmd/zoneadmd/zoneadmd.h6
-rw-r--r--usr/src/lib/Makefile3
-rw-r--r--usr/src/lib/libppt/Makefile44
-rw-r--r--usr/src/lib/libppt/Makefile.com46
-rw-r--r--usr/src/lib/libppt/amd64/Makefile19
-rw-r--r--usr/src/lib/libppt/common/libppt.c506
-rw-r--r--usr/src/lib/libppt/common/libppt.h36
-rw-r--r--usr/src/lib/libppt/common/llib-lppt19
-rw-r--r--usr/src/lib/libppt/common/mapfile-vers40
-rw-r--r--usr/src/lib/libppt/i386/Makefile18
-rw-r--r--usr/src/lib/libppt/sparc/Makefile18
-rw-r--r--usr/src/lib/libppt/sparcv9/Makefile19
-rw-r--r--usr/src/man/man1m/Makefile3
-rw-r--r--usr/src/man/man1m/pptadm.1m74
-rw-r--r--usr/src/pkg/manifests/system-bhyve.mf9
-rw-r--r--usr/src/uts/common/os/modsysfile.c27
24 files changed, 1195 insertions, 21 deletions
diff --git a/manifest b/manifest
index b323eb88b9..bcfb8827e5 100644
--- a/manifest
+++ b/manifest
@@ -4928,6 +4928,7 @@ f usr/lib/amd64/libpool.so.1 0755 root bin
s usr/lib/amd64/libpool.so=libpool.so.1
s usr/lib/amd64/libposix4.so.1=../../../lib/amd64/librt.so.1
s usr/lib/amd64/libposix4.so=../../../lib/amd64/librt.so.1
+f usr/lib/amd64/libppt.so.1 0755 root bin
s usr/lib/amd64/libproc.so.1=../../../lib/amd64/libproc.so.1
s usr/lib/amd64/libproc.so=../../../lib/amd64/libproc.so.1
f usr/lib/amd64/libproject.so.1 0755 root bin
@@ -6379,6 +6380,7 @@ s usr/lib/libposix4.so.1=../../lib/librt.so.1
s usr/lib/libposix4.so=../../lib/librt.so.1
f usr/lib/libpp.so.1 0755 root bin
s usr/lib/libpp.so=libpp.so.1
+f usr/lib/libppt.so.1 0755 root bin
s usr/lib/libproc.so.1=../../lib/libproc.so.1
s usr/lib/libproc.so=../../lib/libproc.so.1
f usr/lib/libproject.so.1 0755 root bin
@@ -10450,6 +10452,7 @@ f usr/sbin/poolbind 0555 root bin
f usr/sbin/poolcfg 0555 root bin
h usr/sbin/ports=usr/sbin/devfsadm
h usr/sbin/poweroff=usr/sbin/halt
+f usr/sbin/pptadm 0555 root bin
f usr/sbin/praudit 0555 root bin
f usr/sbin/projadd 0555 root sys
f usr/sbin/projdel 0555 root sys
@@ -12093,6 +12096,7 @@ f usr/share/man/man1m/poold.1m 0444 root bin
f usr/share/man/man1m/poolstat.1m 0444 root bin
f usr/share/man/man1m/ports.1m 0444 root bin
s usr/share/man/man1m/poweroff.1m=halt.1m
+f usr/share/man/man1m/pptadm.1m 0444 root bin
f usr/share/man/man1m/praudit.1m 0444 root bin
f usr/share/man/man1m/projadd.1m 0444 root bin
f usr/share/man/man1m/projdel.1m 0444 root bin
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint
index b8c25c83da..b5f18f9ca1 100644
--- a/usr/src/Makefile.lint
+++ b/usr/src/Makefile.lint
@@ -24,6 +24,7 @@
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright 2015 Garrett D'Amore <garrett@damore.org>
# Copyright 2016 Nexenta Systems, Inc.
+# Copyright 2018 Joyent, Inc.
#
# include global definitions
@@ -235,6 +236,7 @@ COMMON_SUBDIRS = \
cmd/printf \
cmd/latencytop \
cmd/ppgsz \
+ cmd/pptadm \
cmd/praudit \
cmd/prctl \
cmd/priocntl \
@@ -409,6 +411,7 @@ COMMON_SUBDIRS = \
lib/libpicltree \
lib/libpkg \
lib/libpool \
+ lib/libppt \
lib/libproc \
lib/libpthread \
lib/libraidcfg \
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index 9d42f388cd..d86e9ae3a4 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -317,6 +317,7 @@ COMMON_SUBDIRS= \
ppgsz \
pg \
plockstat \
+ pptadm \
pr \
prctl \
printf \
diff --git a/usr/src/cmd/pptadm/Makefile b/usr/src/cmd/pptadm/Makefile
new file mode 100644
index 0000000000..3be558a7a0
--- /dev/null
+++ b/usr/src/cmd/pptadm/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.
+#
+
+PROG = pptadm
+OBJS = pptadm.o
+SRCS = $(OBJS:%.o=%.c)
+
+include ../Makefile.cmd
+include ../Makefile.ctf
+
+LDLIBS += -lofmt -lppt -lnvpair
+
+CSTD = $(CSTD_GNU99)
+C99LMODE = -Xc99=%all
+
+CLEANFILES += $(OBJS)
+
+.KEEP_STATE:
+
+all: $(OBJS) $(PROG)
+
+install: all $(ROOTUSRSBINPROG)
+
+clean:
+ -$(RM) $(CLEANFILES)
+
+lint: lint_SRCS
+
+%.o: ../%.c
+ $(COMPILE.c) $<
+ $(POST_PROCESS_O)
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/pptadm/pptadm.c b/usr/src/cmd/pptadm/pptadm.c
new file mode 100644
index 0000000000..c6b9094408
--- /dev/null
+++ b/usr/src/cmd/pptadm/pptadm.c
@@ -0,0 +1,205 @@
+/*
+ * 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 <stdlib.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <string.h>
+#include <ofmt.h>
+#include <err.h>
+
+#include <libppt.h>
+
+typedef enum field {
+ PPT_DEV,
+ PPT_VENDOR,
+ PPT_DEVICE,
+ PPT_SUBVENDOR,
+ PPT_SUBDEVICE,
+ PPT_REV,
+ PPT_PATH,
+ PPT_LABEL
+} field_t;
+
+const char *valname[] = {
+ "dev",
+ "vendor-id",
+ "device-id",
+ "subsystem-vendor-id",
+ "subsystem-id",
+ "revision-id",
+ "path",
+ "label"
+};
+
+static ofmt_cb_t print_field;
+
+static ofmt_field_t fields[] = {
+/* name, field width, index, callback */
+{ "DEV", sizeof ("/dev/pptXX"), PPT_DEV, print_field },
+{ "VENDOR", sizeof ("VENDOR"), PPT_VENDOR, print_field },
+{ "DEVICE", sizeof ("DEVICE"), PPT_DEVICE, print_field },
+{ "SUBVENDOR", sizeof ("SUBVENDOR"), PPT_SUBVENDOR, print_field },
+{ "SUBDEVICE", sizeof ("SUBDEVICE"), PPT_SUBDEVICE, print_field },
+{ "REV", sizeof ("REV"), PPT_REV, print_field },
+{ "PATH", 50, PPT_PATH, print_field },
+{ "LABEL", 60, PPT_LABEL, print_field },
+{ NULL, 0, 0, NULL },
+};
+
+static void
+usage(const char *errmsg)
+{
+ if (errmsg != NULL)
+ (void) fprintf(stderr, "pptadm: %s\n", errmsg);
+ (void) fprintf(errmsg != NULL ? stderr : stdout,
+ "Usage:\n"
+ "pptadm list [ -j ]\n"
+ "pptadm list [-ap] [-o fields]\n");
+ exit(errmsg != NULL ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+/* PRINTFLIKE1 */
+static void
+die(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrx(EXIT_FAILURE, fmt, ap);
+ va_end(ap);
+}
+
+static boolean_t
+print_field(ofmt_arg_t *arg, char *buf, uint_t bufsize)
+{
+ nvlist_t *nvl = arg->ofmt_cbarg;
+ nvpair_t *nvp = NULL;
+
+ while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
+ const char *name = nvpair_name(nvp);
+ char *val = NULL;
+
+ (void) nvpair_value_string(nvp, &val);
+
+ if (strcmp(name, valname[arg->ofmt_id]) != 0)
+ continue;
+
+ (void) snprintf(buf, bufsize, "%s", val);
+ return (B_TRUE);
+ }
+
+ (void) snprintf(buf, bufsize, "--");
+ return (B_TRUE);
+}
+
+static int
+list(int argc, char *argv[])
+{
+ const char *fields_str = NULL;
+ boolean_t parsable = B_FALSE;
+ boolean_t json = B_FALSE;
+ boolean_t all = B_FALSE;
+ uint_t ofmtflags = 0;
+ ofmt_status_t oferr;
+ ofmt_handle_t ofmt;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "ahjo:p")) != -1) {
+ switch (opt) {
+ case 'a':
+ all = B_TRUE;
+ break;
+ case 'h':
+ usage(NULL);
+ break;
+ case 'j':
+ json = B_TRUE;
+ break;
+ case 'o':
+ fields_str = optarg;
+ break;
+ case 'p':
+ ofmtflags |= OFMT_PARSABLE;
+ parsable = B_TRUE;
+ break;
+ default:
+ usage("unrecognized option");
+ break;
+ }
+ }
+
+ if (optind == (argc - 1))
+ usage("unused arguments");
+
+ if (json && (parsable || fields_str != NULL))
+ usage("-j option cannot be used with -p or -o options");
+
+ if (fields_str == NULL) {
+ if (parsable)
+ usage("-o must be provided when using -p option");
+ fields_str = "dev,vendor,device,path";
+ }
+
+ oferr = ofmt_open(fields_str, fields, ofmtflags, 0, &ofmt);
+
+ ofmt_check(oferr, parsable, ofmt, die, warn);
+
+ nvlist_t *nvl = all ? ppt_list() : ppt_list_assigned();
+ nvpair_t *nvp = NULL;
+
+ if (json) {
+ if (printf("{\n\t\"devices\": [\n") < 0)
+ err(EXIT_FAILURE, "failed to write JSON");
+ }
+
+ while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
+ nvlist_t *props;
+
+ (void) nvpair_value_nvlist(nvp, &props);
+
+ if (json) {
+ if (printf("\t\t") < 0)
+ err(EXIT_FAILURE, "failed to write JSON");
+ if (nvlist_print_json(stdout, props) < 0)
+ err(EXIT_FAILURE, "failed to write JSON");
+ if (nvlist_next_nvpair(nvl, nvp) != NULL)
+ (void) printf(",\n");
+ } else {
+ ofmt_print(ofmt, props);
+ }
+ }
+
+ if (json) {
+ if (printf("\n\t]\n}\n") < 0)
+ err(EXIT_FAILURE, "failed to write JSON");
+ }
+
+ nvlist_free(nvl);
+ ofmt_close(ofmt);
+ return (EXIT_SUCCESS);
+}
+
+int
+main(int argc, char *argv[])
+{
+ if (argc == 1)
+ return (list(argc - 1, argv));
+
+ if (strcmp(argv[1], "list") == 0) {
+ return (list(argc - 1, &argv[1]));
+ } else {
+ usage("unknown sub-command");
+ }
+
+ return (EXIT_SUCCESS);
+}
diff --git a/usr/src/cmd/zoneadmd/Makefile.com b/usr/src/cmd/zoneadmd/Makefile.com
index 7f78fb2e05..6312c00ad5 100644
--- a/usr/src/cmd/zoneadmd/Makefile.com
+++ b/usr/src/cmd/zoneadmd/Makefile.com
@@ -35,7 +35,7 @@ OBJS= zoneadmd.o zcons.o zfd.o vplat.o log.o
CFLAGS += $(CCVERBOSE)
LDLIBS += -lsocket -lzonecfg -lnsl -ldevinfo -ldevice -lnvpair \
-lgen -lbsm -lcontract -lzfs -luuid -lbrand -ldladm -ltsnet -ltsol \
- -linetutil -lproc -lscf
+ -linetutil -lproc -lscf -lppt
CSTD= $(CSTD_GNU99)
diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c
index d67e8d824f..f466836b96 100644
--- a/usr/src/cmd/zoneadmd/vplat.c
+++ b/usr/src/cmd/zoneadmd/vplat.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2017, Joyent Inc.
+ * Copyright 2018, Joyent Inc.
* Copyright (c) 2015, 2016 by Delphix. All rights reserved.
*/
@@ -1198,9 +1198,15 @@ mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd)
goto cleanup;
}
while (zonecfg_getdevent(snap_hndl, &ztab) == Z_OK) {
- if (di_prof_add_dev(prof, ztab.zone_dev_match)) {
+ char path[MAXPATHLEN];
+
+ if ((err = resolve_device_match(zlogp, &ztab,
+ path, sizeof (path))) != Z_OK)
+ goto cleanup;
+
+ if (di_prof_add_dev(prof, path)) {
zerror(zlogp, B_TRUE, "failed to add "
- "user-specified device");
+ "user-specified device '%s'", path);
goto cleanup;
}
}
diff --git a/usr/src/cmd/zoneadmd/zoneadmd.c b/usr/src/cmd/zoneadmd/zoneadmd.c
index 21c6460eeb..51954a9f3e 100644
--- a/usr/src/cmd/zoneadmd/zoneadmd.c
+++ b/usr/src/cmd/zoneadmd/zoneadmd.c
@@ -105,6 +105,7 @@
#include <sys/dls_mgmt.h>
#include <libscf.h>
#include <uuid/uuid.h>
+#include <libppt.h>
#include <libzonecfg.h>
#include <zonestat_impl.h>
@@ -830,6 +831,46 @@ set_zonecfg_env(char *rsrc, char *attr, char *name, char *val)
}
/*
+ * Resolve a device:match value to a path. This is only different for PPT
+ * devices, where we expect the match property to be a /devices/... path, and
+ * configured for PPT already.
+ */
+int
+resolve_device_match(zlog_t *zlogp, struct zone_devtab *dtab,
+ char *path, size_t len)
+{
+ struct zone_res_attrtab *rap;
+
+ for (rap = dtab->zone_dev_attrp; rap != NULL;
+ rap = rap->zone_res_attr_next) {
+ if (strcmp(rap->zone_res_attr_name, "model") == 0 &&
+ strcmp(rap->zone_res_attr_value, "passthru") == 0)
+ break;
+ }
+
+ if (rap == NULL) {
+ if (strlcpy(path, dtab->zone_dev_match, len) >= len)
+ return (Z_INVAL);
+ return (Z_OK);
+ }
+
+ if (strncmp(dtab->zone_dev_match, "/devices",
+ strlen("/devices")) != 0) {
+ zerror(zlogp, B_FALSE, "invalid passthru match value '%s'",
+ dtab->zone_dev_match);
+ return (Z_INVAL);
+ }
+
+ if (ppt_devpath_to_dev(dtab->zone_dev_match, path, len) != 0) {
+ zerror(zlogp, B_TRUE, "failed to resolve passthru device %s",
+ dtab->zone_dev_match);
+ return (Z_INVAL);
+ }
+
+ return (Z_OK);
+}
+
+/*
* Export various zonecfg properties into environment for the boot and state
* change hooks.
*
@@ -846,7 +887,7 @@ set_zonecfg_env(char *rsrc, char *attr, char *name, char *val)
* SmartOS.
*/
static int
-setup_subproc_env(boolean_t debug)
+setup_subproc_env(zlog_t *zlogp, boolean_t debug)
{
int res;
struct zone_nwiftab ntab;
@@ -931,17 +972,19 @@ setup_subproc_env(boolean_t debug)
dev_resources[0] = '\0';
while (zonecfg_getdevent(snap_hndl, &dtab) == Z_OK) {
+ char *match = dtab.zone_dev_match;
struct zone_res_attrtab *rap;
- char *match;
+ char path[MAXPATHLEN];
- match = dtab.zone_dev_match;
+ res = resolve_device_match(zlogp, &dtab, path, sizeof (path));
+ if (res != Z_OK)
+ goto done;
/*
- * In the environment variable name, the value of match will be
- * mangled. Thus, we store the value of match in a "path"
- * environment variable.
+ * Even if not modified, the match path will be mangled in the
+ * environment variable name, so we always store the value here.
*/
- set_zonecfg_env(RSRC_DEV, match, "path", match);
+ set_zonecfg_env(RSRC_DEV, match, "path", path);
for (rap = dtab.zone_dev_attrp; rap != NULL;
rap = rap->zone_res_attr_next) {
@@ -1078,7 +1121,7 @@ do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr, boolean_t debug)
}
closefrom(STDERR_FILENO + 1);
- if (setup_subproc_env(debug) != Z_OK) {
+ if (setup_subproc_env(zlogp, debug) != Z_OK) {
(void) fprintf(stderr, "failed to setup environment");
_exit(127);
}
diff --git a/usr/src/cmd/zoneadmd/zoneadmd.h b/usr/src/cmd/zoneadmd/zoneadmd.h
index a170759e50..4953479e64 100644
--- a/usr/src/cmd/zoneadmd/zoneadmd.h
+++ b/usr/src/cmd/zoneadmd/zoneadmd.h
@@ -187,6 +187,12 @@ extern int init_template(void);
*/
extern int do_subproc(zlog_t *, char *, char **, boolean_t);
+/*
+ * Resource handling.
+ */
+extern int resolve_device_match(zlog_t *, struct zone_devtab *,
+ char *, size_t);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index 9efd87bc10..ee1855d850 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -183,6 +183,7 @@ SUBDIRS += \
libpkg \
libpool \
libpp \
+ libppt \
libproc \
libproject \
libpthread \
@@ -448,6 +449,7 @@ HDRSUBDIRS= \
libpicltree \
libpool \
libpp \
+ libppt \
libproc \
libraidcfg \
librcm \
@@ -655,6 +657,7 @@ libpctx: libproc
libpkg: libscf libadm
libpool: libscf libexacct
libpp: libast
+libppt: libpcidb libdevinfo libcmdutils
libproc: ../cmd/sgs/librtld_db ../cmd/sgs/libelf libctf
$(INTEL_BLD)libproc: libsaveargs
libproject: libpool libproc libsecdb
diff --git a/usr/src/lib/libppt/Makefile b/usr/src/lib/libppt/Makefile
new file mode 100644
index 0000000000..21c26d447e
--- /dev/null
+++ b/usr/src/lib/libppt/Makefile
@@ -0,0 +1,44 @@
+#
+# 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 $(SRC)/lib/Makefile.lib
+
+SUBDIRS = $(MACH) $(BUILD64) $(MACH64)
+
+HDRS = libppt.h
+HDRDIR = common
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRS)
+
+all install: install_h
+
+check: $(CHECKHDRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/lib/libppt/Makefile.com b/usr/src/lib/libppt/Makefile.com
new file mode 100644
index 0000000000..7b2ff4885f
--- /dev/null
+++ b/usr/src/lib/libppt/Makefile.com
@@ -0,0 +1,46 @@
+#
+# 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 = libppt.a
+VERS = .1
+
+OBJECTS = libppt.o
+
+include $(SRC)/lib/Makefile.lib
+
+SRCDIR = ../common
+
+LIBS = $(DYNLIB) $(LINTLIB)
+SRCS = $(SRCDIR)/libppt.c
+
+CSTD= $(CSTD_GNU99)
+C99LMODE= -Xc99=%all
+
+#
+# lint doesn't like %4s in sscanf().
+#
+LINTFLAGS += -erroff=E_BAD_FORMAT_ARG_TYPE2
+LINTFLAGS64 += -erroff=E_BAD_FORMAT_ARG_TYPE2
+
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
+LDLIBS += -lpcidb -ldevinfo -lcmdutils -lnvpair -lc
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/lib/libppt/amd64/Makefile b/usr/src/lib/libppt/amd64/Makefile
new file mode 100644
index 0000000000..5a304d7fe7
--- /dev/null
+++ b/usr/src/lib/libppt/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 $(SRC)/lib/Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libppt/common/libppt.c b/usr/src/lib/libppt/common/libppt.c
new file mode 100644
index 0000000000..7e8385da06
--- /dev/null
+++ b/usr/src/lib/libppt/common/libppt.c
@@ -0,0 +1,506 @@
+/*
+ * 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.
+ *
+ * Convenience routines for identifying current or available devices that are
+ * suitable for PCI passthrough to a bhyve guest.
+ */
+
+#include <libdevinfo.h>
+#include <libppt.h>
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/list.h>
+#include <strings.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <pcidb.h>
+#include <glob.h>
+
+typedef struct node_data {
+ pcidb_hdl_t *nd_db;
+ list_t nd_matches;
+ nvlist_t *nd_nvl;
+ int nd_err;
+} node_data_t;
+
+typedef struct ppt_match {
+ list_node_t pm_list;
+ char pm_path[MAXPATHLEN];
+ char pm_vendor[5];
+ char pm_device[5];
+} ppt_match_t;
+
+static boolean_t
+is_pci(di_node_t di_node)
+{
+ char *svals;
+
+ if (di_prop_lookup_strings(DDI_DEV_T_ANY, di_parent_node(di_node),
+ "device_type", &svals) != 1)
+ return (B_FALSE);
+
+ return (strcmp(svals, "pci") == 0 || strcmp(svals, "pciex") == 0);
+}
+
+static int
+populate_int_prop(di_node_t di_node, nvlist_t *nvl, const char *name, int *ival)
+{
+ char val[20];
+ int *ivals;
+ int err;
+
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, di_node, name, &ivals) != 1)
+ return (errno);
+
+ (void) snprintf(val, sizeof (val), "%x", ivals[0]);
+
+ err = nvlist_add_string(nvl, name, val);
+
+ if (err == 0 && ival != NULL)
+ *ival = ivals[0];
+
+ return (err);
+}
+
+static int
+dev_getlabel(pcidb_hdl_t *db, int vid, int did, char *buf, size_t buflen)
+{
+ pcidb_vendor_t *vend = NULL;
+ pcidb_device_t *dev = NULL;
+
+ if ((vend = pcidb_lookup_vendor(db, vid)) == NULL)
+ return (ENOENT);
+
+ if ((dev = pcidb_lookup_device_by_vendor(vend, did)) == NULL)
+ return (ENOENT);
+
+ (void) snprintf(buf, buflen, "%s %s", pcidb_vendor_name(vend),
+ pcidb_device_name(dev));
+
+ return (0);
+}
+
+static nvlist_t *
+dev_getinfo(di_node_t di_node, pcidb_hdl_t *db,
+ const char *dev, const char *path)
+{
+ char label[MAXPATHLEN];
+ nvlist_t *nvl = NULL;
+ int vid, did;
+ int err;
+
+ if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
+ goto out;
+
+ if (dev != NULL && (err = nvlist_add_string(nvl, "dev", dev)) != 0)
+ goto out;
+ if ((err = nvlist_add_string(nvl, "path", path)) != 0)
+ goto out;
+ if ((err = populate_int_prop(di_node, nvl, "vendor-id", &vid)) != 0)
+ goto out;
+ if ((err = populate_int_prop(di_node, nvl, "device-id", &did)) != 0)
+ goto out;
+ if ((err = populate_int_prop(di_node, nvl,
+ "subsystem-vendor-id", NULL)) != 0)
+ goto out;
+ if ((err = populate_int_prop(di_node, nvl, "subsystem-id", NULL)) != 0)
+ goto out;
+ if ((err = populate_int_prop(di_node, nvl, "revision-id", NULL)) != 0)
+ goto out;
+
+ err = dev_getlabel(db, vid, did, label, sizeof (label));
+
+ if (err == 0) {
+ err = nvlist_add_string(nvl, "label", label);
+ } else if (err == ENOENT) {
+ err = 0;
+ }
+
+out:
+ if (err) {
+ nvlist_free(nvl);
+ errno = err;
+ return (NULL);
+ }
+
+ return (nvl);
+}
+
+/*
+ * /devices/pci0@0/....@0,1:ppt -> /pci0@0/...@0,1
+ */
+static const char *
+fs_to_phys_path(char *fspath)
+{
+ const char prefix[] = "/devices";
+ char *c;
+
+ if ((c = strrchr(fspath, ':')) != NULL && strcmp(c, ":ppt") == 0)
+ *c = '\0';
+
+ c = fspath;
+
+ if (strncmp(c, prefix, sizeof (prefix) - 1) == 0)
+ c += sizeof (prefix) - 1;
+
+ return (c);
+}
+
+/*
+ * Return an nvlist representing the mappings of /dev/ppt* devices to physical
+ * devices. Of the form:
+ *
+ * /pci@0,0/... {
+ * dev: "/dev/ppt0"
+ * path: "/pci@0,0/..."
+ * vendor-id: "8086"
+ * device-id: "1528"
+ * subsystem-vendor-id: "8086"
+ * subsystem-id: "1528"
+ * revision-id: "1"
+ * label: "Intel Corporation ..."
+ * },
+ * /pci@0,0/...
+ *
+ * The nvlist should be freed by the caller.
+ */
+nvlist_t *
+ppt_list_assigned(void)
+{
+ di_node_t di_root = DI_NODE_NIL;
+ pcidb_hdl_t *db = NULL;
+ nvlist_t *nvl = NULL;
+ glob_t gl;
+ int err;
+
+ bzero(&gl, sizeof (gl));
+
+ if ((di_root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
+ return (NULL);
+
+ if ((db = pcidb_open(PCIDB_VERSION)) == NULL) {
+ err = errno;
+ goto out;
+ }
+
+ if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
+ goto out;
+
+ if ((err = glob("/dev/ppt*", GLOB_KEEPSTAT | GLOB_ERR,
+ NULL, &gl)) != 0) {
+ err = (err == GLOB_NOMATCH) ? 0 : errno;
+ goto out;
+ }
+
+ for (size_t i = 0; i < gl.gl_pathc; i++) {
+ char fspath[MAXPATHLEN];
+ nvlist_t *info_nvl;
+ di_node_t di_node;
+ const char *path;
+
+ if (!S_ISLNK(gl.gl_statv[i]->st_mode))
+ continue;
+
+ if (realpath(gl.gl_pathv[i], fspath) == NULL) {
+ err = errno;
+ goto out;
+ }
+
+ path = fs_to_phys_path(fspath);
+
+ /*
+ * path argument is treated as const.
+ */
+ if ((di_node = di_lookup_node(di_root, (char *)path)) == NULL) {
+ err = errno;
+ goto out;
+ }
+
+ if (!is_pci(di_node))
+ continue;
+
+ info_nvl = dev_getinfo(di_node, db, gl.gl_pathv[i], path);
+
+ if (info_nvl == NULL) {
+ err = errno;
+ goto out;
+ }
+
+ err = nvlist_add_nvlist(nvl, path, info_nvl);
+ nvlist_free(info_nvl);
+
+ if (err)
+ goto out;
+ }
+
+out:
+ if (di_root != DI_NODE_NIL)
+ di_fini(di_root);
+
+ pcidb_close(db);
+ globfree(&gl);
+
+ if (err) {
+ nvlist_free(nvl);
+ errno = err;
+ return (NULL);
+ }
+
+ return (nvl);
+}
+
+/*
+ * Read in our list of potential PPT devices. A boot-module provided file
+ * explicitly over-rides anything delivered.
+ */
+static int
+get_matches(list_t *listp)
+{
+ int err = 0;
+ FILE *fp;
+
+ list_create(listp, sizeof (ppt_match_t),
+ offsetof(ppt_match_t, pm_list));
+
+ if ((fp = fopen("/system/boot/etc/ppt_matches", "r")) == NULL) {
+ if (errno != ENOENT)
+ return (errno);
+
+ if ((fp = fopen("/etc/ppt_matches", "r")) == NULL) {
+ if (errno == ENOENT)
+ return (0);
+ return (errno);
+ }
+ }
+
+ for (;;) {
+ char *line = NULL;
+ ppt_match_t *pm;
+ size_t cap = 0;
+ ssize_t read;
+
+ if ((read = getline(&line, &cap, fp)) <= 0) {
+ free(line);
+ break;
+ }
+
+ if (line[read - 1] == '\n')
+ line[read - 1] = '\0';
+
+ if ((pm = malloc(sizeof (*pm))) == NULL) {
+ err = errno;
+ free(line);
+ goto out;
+ }
+
+ bzero(pm, sizeof (*pm));
+
+ if (sscanf(line, "pciex%4s,%4s", &pm->pm_vendor,
+ &pm->pm_device) == 2 ||
+ sscanf(line, "pci%4s,%4s", &pm->pm_vendor,
+ &pm->pm_device) == 2 ||
+ sscanf(line, "pciex%4s", &pm->pm_vendor) == 1 ||
+ sscanf(line, "pci%4s", &pm->pm_vendor) == 1) {
+ list_insert_tail(listp, pm);
+ } else if (line[0] == '/') {
+ (void) strlcpy(pm->pm_path, line, sizeof (pm->pm_path));
+ list_insert_tail(listp, pm);
+ } else {
+ /*
+ * Ignore any line we don't understand.
+ */
+ free(pm);
+ }
+
+ free(line);
+ }
+
+out:
+ (void) fclose(fp);
+ return (err);
+}
+
+static boolean_t
+match_ppt(list_t *matches, nvlist_t *nvl)
+{
+ char *vendor;
+ char *device;
+ char *path;
+
+ if (nvlist_lookup_string(nvl, "path", &path) != 0 ||
+ nvlist_lookup_string(nvl, "vendor-id", &vendor) != 0 ||
+ nvlist_lookup_string(nvl, "device-id", &device) != 0)
+ return (B_FALSE);
+
+ for (ppt_match_t *pm = list_head(matches); pm != NULL;
+ pm = list_next(matches, pm)) {
+ if (pm->pm_path[0] != '\0' && strcmp(pm->pm_path, path) == 0)
+ return (B_TRUE);
+
+ if (pm->pm_vendor[0] != '\0' &&
+ strcmp(pm->pm_vendor, vendor) == 0) {
+ if (pm->pm_device[0] == '\0')
+ return (B_TRUE);
+ if (strcmp(pm->pm_device, device) == 0)
+ return (B_TRUE);
+ }
+ }
+
+ return (B_FALSE);
+}
+
+static int
+inspect_node(di_node_t di_node, void *arg)
+{
+ node_data_t *data = arg;
+ nvlist_t *info_nvl = NULL;
+ char *devname = NULL;
+ const char *driver;
+ char *path = NULL;
+
+ if (!is_pci(di_node))
+ return (DI_WALK_CONTINUE);
+
+ driver = di_driver_name(di_node);
+
+ if (driver != NULL && strcmp(driver, "ppt") == 0) {
+ if (asprintf(&devname, "/dev/ppt%d",
+ di_instance(di_node)) < 0) {
+ data->nd_err = errno;
+ goto out;
+ }
+ }
+
+ if ((path = di_devfs_path(di_node)) == NULL) {
+ data->nd_err = ENOENT;
+ goto out;
+ }
+
+ info_nvl = dev_getinfo(di_node, data->nd_db, devname, path);
+
+ if (info_nvl == NULL)
+ goto out;
+
+ if (devname == NULL && !match_ppt(&data->nd_matches, info_nvl))
+ goto out;
+
+ data->nd_err = nvlist_add_nvlist(data->nd_nvl, path, info_nvl);
+
+out:
+ free(path);
+ free(devname);
+ nvlist_free(info_nvl);
+ return (data->nd_err ? DI_WALK_TERMINATE : DI_WALK_CONTINUE);
+}
+
+/*
+ * Like ppt_list_assigned() output, but includes all devices that could be used
+ * for passthrough, whether assigned or not.
+ */
+nvlist_t *
+ppt_list(void)
+{
+ node_data_t nd = { NULL, };
+ di_node_t di_root;
+ int err;
+
+ if ((di_root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
+ return (NULL);
+
+ if ((err = get_matches(&nd.nd_matches)) != 0)
+ goto out;
+
+ if ((nd.nd_db = pcidb_open(PCIDB_VERSION)) == NULL) {
+ err = errno;
+ goto out;
+ }
+
+ if ((err = nvlist_alloc(&nd.nd_nvl, NV_UNIQUE_NAME, 0)) != 0)
+ goto out;
+
+ if ((err = di_walk_node(di_root, DI_WALK_CLDFIRST,
+ &nd, inspect_node)) != 0)
+ goto out;
+
+ err = nd.nd_err;
+
+out:
+ pcidb_close(nd.nd_db);
+
+ for (ppt_match_t *pm = list_head(&nd.nd_matches); pm != NULL; ) {
+ ppt_match_t *next = list_next(&nd.nd_matches, pm);
+ free(pm);
+ pm = next;
+ }
+
+ if (di_root != DI_NODE_NIL)
+ di_fini(di_root);
+
+ if (err) {
+ nvlist_free(nd.nd_nvl);
+ errno = err;
+ return (NULL);
+ }
+
+ return (nd.nd_nvl);
+}
+
+/*
+ * Given a physical path such as "/devices/pci0@0...", return the "/dev/pptX"
+ * that is bound to it, if any. The "/devices/" prefix is optional. The
+ * physical path may have the ":ppt" minor name suffix.
+ *
+ * Returns ENOENT if no such PPT device exists.
+ */
+int
+ppt_devpath_to_dev(const char *inpath, char *buf, size_t buflen)
+{
+ char fspath[MAXPATHLEN] = "";
+ nvpair_t *nvp = NULL;
+ const char *devpath;
+ int err = ENOENT;
+ nvlist_t *nvl;
+
+ if (strlcat(fspath, inpath, sizeof (fspath)) >= sizeof (fspath))
+ return (ENAMETOOLONG);
+
+ devpath = fs_to_phys_path(fspath);
+
+ if ((nvl = ppt_list_assigned()) == NULL)
+ return (errno);
+
+ while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
+ const char *name = nvpair_name(nvp);
+ char *ppt = NULL;
+ nvlist_t *props;
+
+ (void) nvpair_value_nvlist(nvp, &props);
+
+ if (strcmp(name, devpath) == 0) {
+ (void) nvlist_lookup_string(props, "dev", &ppt);
+
+ err = 0;
+
+ if (strlcpy(buf, ppt, buflen) >= buflen)
+ err = ENAMETOOLONG;
+ break;
+ }
+ }
+
+ nvlist_free(nvl);
+ return (err);
+}
diff --git a/usr/src/lib/libppt/common/libppt.h b/usr/src/lib/libppt/common/libppt.h
new file mode 100644
index 0000000000..efbf2c7b8b
--- /dev/null
+++ b/usr/src/lib/libppt/common/libppt.h
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBPPT_H
+#define _LIBPPT_H
+
+#include <sys/types.h>
+
+#include <libnvpair.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ppt_devpath_to_dev(const char *, char *, size_t);
+
+extern nvlist_t *ppt_list_assigned(void);
+
+extern nvlist_t *ppt_list(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBPPT_H */
diff --git a/usr/src/lib/libppt/common/llib-lppt b/usr/src/lib/libppt/common/llib-lppt
new file mode 100644
index 0000000000..dadd992a31
--- /dev/null
+++ b/usr/src/lib/libppt/common/llib-lppt
@@ -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.
+ */
+
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+#include <libppt.h>
diff --git a/usr/src/lib/libppt/common/mapfile-vers b/usr/src/lib/libppt/common/mapfile-vers
new file mode 100644
index 0000000000..d9d882874b
--- /dev/null
+++ b/usr/src/lib/libppt/common/mapfile-vers
@@ -0,0 +1,40 @@
+#
+# 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:
+ ppt_devpath_to_dev;
+ ppt_list_assigned;
+ ppt_list;
+
+ local:
+ *;
+};
diff --git a/usr/src/lib/libppt/i386/Makefile b/usr/src/lib/libppt/i386/Makefile
new file mode 100644
index 0000000000..3f11e556d4
--- /dev/null
+++ b/usr/src/lib/libppt/i386/Makefile
@@ -0,0 +1,18 @@
+#
+# 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
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libppt/sparc/Makefile b/usr/src/lib/libppt/sparc/Makefile
new file mode 100644
index 0000000000..3f11e556d4
--- /dev/null
+++ b/usr/src/lib/libppt/sparc/Makefile
@@ -0,0 +1,18 @@
+#
+# 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
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libppt/sparcv9/Makefile b/usr/src/lib/libppt/sparcv9/Makefile
new file mode 100644
index 0000000000..5a304d7fe7
--- /dev/null
+++ b/usr/src/lib/libppt/sparcv9/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 $(SRC)/lib/Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/man/man1m/Makefile b/usr/src/man/man1m/Makefile
index e242b24eee..94d5d9bd4d 100644
--- a/usr/src/man/man1m/Makefile
+++ b/usr/src/man/man1m/Makefile
@@ -557,7 +557,8 @@ _MANFILES= 6to4relay.1m \
i386_MANFILES= \
acpidump.1m \
acpixtract.1m \
- nvmeadm.1m
+ nvmeadm.1m \
+ pptadm.1m
sparc_MANFILES= cvcd.1m \
dcs.1m \
diff --git a/usr/src/man/man1m/pptadm.1m b/usr/src/man/man1m/pptadm.1m
new file mode 100644
index 0000000000..f13a5e32a4
--- /dev/null
+++ b/usr/src/man/man1m/pptadm.1m
@@ -0,0 +1,74 @@
+.\"
+.\" 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.
+.\"
+.Dd April 10, 2018
+.Dt PPTADM 1M
+.Os
+.Sh NAME
+.Nm pptadm
+.Nd PPT administration utility
+.Sh SYNOPSIS
+.Nm
+.Cm list -j
+.Op Fl a
+.Nm
+.Cm list
+.Op Fl ap Op Fl o Ar fields
+.Sh DESCRIPTION
+The
+.Nm
+utility can enumerate passthrough devices for use by a virtualized guest.
+.Sh OPTIONS
+The following options to the
+.Cm list
+command are supported:
+.Bl -tag -width Ds
+.It Fl a
+Show all PPT devices, both available and assigned.
+.It Fl j
+Output JSON.
+.It Fl o
+Specify fields to output, or "all". Available fields are
+dev,path,vendor,device,subvendor,subdevice,rev,label
+.It Fl p
+Output in a parsable format; this requires the -o option to be specified.
+.El
+.Sh JSON OUTPUT
+The JSON output consists of an array under the key "devices" with the fields:
+.Bl -tag -width Ds
+.It dev
+The PPT /dev path, if assigned and bound.
+.It path
+The physical /devices path.
+.It vendor-id
+The PCI vendor ID.
+.It device-id
+The PCI device ID.
+.It subsystem-vendor-id
+The PCI subsystem vendor ID.
+.It subsystem-id
+The PCI subsystem ID.
+.It revision-id
+The PCI device revision.
+.It label
+Human-readable description from the PCI database.
+.El
+.Sh FILES
+.Bl -tag -width Ds
+.It /etc/ppt_aliases
+Containts the bindings of PPT devices in the same format as /etc/driver_aliases
+.It /etc/ppt_matches
+Identifies devices that PPT could be bound to, either by physical path, or by
+PCI ID.
+.El
+.Sh EXIT STATUS
+.Ex -std
diff --git a/usr/src/pkg/manifests/system-bhyve.mf b/usr/src/pkg/manifests/system-bhyve.mf
index 4b95d3986a..fe19fb21b4 100644
--- a/usr/src/pkg/manifests/system-bhyve.mf
+++ b/usr/src/pkg/manifests/system-bhyve.mf
@@ -36,18 +36,25 @@ dir path=usr group=sys
dir path=usr/kernel/drv group=sys
dir path=usr/kernel/drv/$(ARCH64) group=sys
dir path=usr/lib group=bin
+dir path=usr/share
+dir path=usr/share/man
+dir path=usr/share/man/man1m
dir path=usr/sbin
driver name=ppt
driver name=viona
driver name=vmm
file path=lib/$(ARCH64)/libvmmapi.so.1
+link path=lib/$(ARCH64)/libvmmapi.so target=./libvmmapi.so.1
file path=usr/kernel/drv/$(ARCH64)/ppt
file path=usr/kernel/drv/$(ARCH64)/viona
file path=usr/kernel/drv/$(ARCH64)/vmm
file path=usr/kernel/drv/ppt.conf
file path=usr/kernel/drv/viona.conf
file path=usr/kernel/drv/vmm.conf
+file path=usr/lib/libppt.so.1
+file path=usr/lib/$(ARCH64)/libppt.so.1
file path=usr/sbin/bhyve mode=0555
file path=usr/sbin/bhyvectl mode=0555
+file path=usr/sbin/pptadm mode=0555
+file path=usr/share/man/man1m/pptadm.1m
license lic_CDDL license=lic_CDDL
-link path=lib/$(ARCH64)/libvmmapi.so target=./libvmmapi.so.1
diff --git a/usr/src/uts/common/os/modsysfile.c b/usr/src/uts/common/os/modsysfile.c
index 8dca86880f..37ac089edf 100644
--- a/usr/src/uts/common/os/modsysfile.c
+++ b/usr/src/uts/common/os/modsysfile.c
@@ -23,6 +23,7 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2016 Nexenta Systems, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#include <sys/types.h>
@@ -57,10 +58,12 @@ struct hwc_class *hcl_head; /* head of list of classes */
static kmutex_t hcl_lock; /* for accessing list of classes */
#define DAFILE "/etc/driver_aliases"
+#define PPTFILE "/etc/ppt_aliases"
#define CLASSFILE "/etc/driver_classes"
#define DACFFILE "/etc/dacf.conf"
static char class_file[] = CLASSFILE;
+static char pptfile[] = PPTFILE;
static char dafile[] = DAFILE;
static char dacffile[] = DACFFILE;
@@ -2136,14 +2139,13 @@ hwc_parse_now(char *fname, struct par_list **pl, ddi_prop_t **props)
return (0); /* always return success */
}
-void
-make_aliases(struct bind **bhash)
+static void
+parse_aliases(struct bind **bhash, struct _buf *file)
{
enum {
AL_NEW, AL_DRVNAME, AL_DRVNAME_COMMA, AL_ALIAS, AL_ALIAS_COMMA
} state;
- struct _buf *file;
char tokbuf[MAXPATHLEN];
char drvbuf[MAXPATHLEN];
token_t token;
@@ -2152,9 +2154,6 @@ make_aliases(struct bind **bhash)
static char dupwarn[] = "!Driver alias \"%s\" conflicts with "
"an existing driver name or alias.";
- if ((file = kobj_open_file(dafile)) == (struct _buf *)-1)
- return;
-
state = AL_NEW;
major = DDI_MAJOR_T_NONE;
while (!done) {
@@ -2239,8 +2238,22 @@ make_aliases(struct bind **bhash)
kobj_file_err(CE_WARN, file, tok_err, tokbuf);
}
}
+}
- kobj_close_file(file);
+void
+make_aliases(struct bind **bhash)
+{
+ struct _buf *file;
+
+ if ((file = kobj_open_file(pptfile)) != (struct _buf *)-1) {
+ parse_aliases(bhash, file);
+ kobj_close_file(file);
+ }
+
+ if ((file = kobj_open_file(dafile)) != (struct _buf *)-1) {
+ parse_aliases(bhash, file);
+ kobj_close_file(file);
+ }
}