summaryrefslogtreecommitdiff
path: root/usr/src/lib/libds
diff options
context:
space:
mode:
authorMike Christensen <Michael.Christensen@Sun.COM>2008-09-25 17:36:37 -0700
committerMike Christensen <Michael.Christensen@Sun.COM>2008-09-25 17:36:37 -0700
commit30588217a56ff2c9137248fb2e5065c4f0101459 (patch)
tree08b89b75fb363ad2fb24e241c8c3c64fdce586e1 /usr/src/lib/libds
parent88294e09b5c27cbb12b6735e2fb247a86b76666d (diff)
downloadillumos-joyent-30588217a56ff2c9137248fb2e5065c4f0101459.tar.gz
PSARC 2008/568 Logical Domain's Domain Services
6689118 LDoms Domain Services (DS) extensions for user program API
Diffstat (limited to 'usr/src/lib/libds')
-rw-r--r--usr/src/lib/libds/Makefile58
-rw-r--r--usr/src/lib/libds/Makefile.com64
-rw-r--r--usr/src/lib/libds/common/libds.c710
-rw-r--r--usr/src/lib/libds/common/libds.h95
-rw-r--r--usr/src/lib/libds/common/llib-lds29
-rw-r--r--usr/src/lib/libds/common/mapfile-vers44
-rw-r--r--usr/src/lib/libds/sparc/Makefile29
-rw-r--r--usr/src/lib/libds/sparcv9/Makefile30
8 files changed, 1059 insertions, 0 deletions
diff --git a/usr/src/lib/libds/Makefile b/usr/src/lib/libds/Makefile
new file mode 100644
index 0000000000..059b9076c4
--- /dev/null
+++ b/usr/src/lib/libds/Makefile
@@ -0,0 +1,58 @@
+#
+# CDDL HEADER START
+#
+# 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]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include ../Makefile.lib
+
+HDRS = libds.h
+HDRDIR = common
+
+ROOTHDRDIR = $(ROOT)/usr/platform/sun4v/include/sys
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+install := TARGET = install
+lint := TARGET = lint
+
+.KEEP_STATE:
+
+all clean clobber lint: $(SUBDIRS)
+
+check: $(CHECKHDRS)
+
+install: all .WAIT $(SUBDIRS)
+
+install_h: $(ROOTHDRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/lib/libds/Makefile.com b/usr/src/lib/libds/Makefile.com
new file mode 100644
index 0000000000..9168e65ed2
--- /dev/null
+++ b/usr/src/lib/libds/Makefile.com
@@ -0,0 +1,64 @@
+#
+# CDDL HEADER START
+#
+# 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]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+LIBRARY = libds.a
+VERS = .1
+
+LIBSRCS = libds.c
+OBJECTS = $(LIBSRCS:%.c=%.o)
+
+include ../../Makefile.lib
+
+LIBS = $(DYNLIB) $(LINTLIB)
+
+SRCDIR = ../common
+SRCS = $(LIBSRCS:%.c=$(SRCDIR)/%.c)
+
+CPPFLAGS += -I. -I$(SRC)/uts/sun4v
+CFLAGS += $(CCVERBOSE) $(C_BIGPICFLAGS)
+CFLAGS64 += $(CCVERBOSE) $(C_BIGPICFLAGS)
+
+LDLIBS += -lsysevent -lnvpair -lc
+
+LINTFLAGS = -msux
+LINTFLAGS64 = -msux -Xarch=$(MACH64:sparcv9=v9)
+
+$(LINTLIB) := SRCS = $(LINTSRC:%=$(SRCDIR)/%)
+$(LINTLIB) := LINTFLAGS = -nsvx -I$(ROOT)/usr/platform/sun4v/include
+$(LINTLIB) := LINTFLAGS64 = -nsvx -Xarch=$(MACH64:sparcv9=v9) \
+ -I$(ROOT)/usr/platform/sun4v/include
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: $(LINTLIB) lintcheck
+
+pics/%.o: $(SRCDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/libds/common/libds.c b/usr/src/lib/libds/common/libds.c
new file mode 100644
index 0000000000..bacdd14f5a
--- /dev/null
+++ b/usr/src/lib/libds/common/libds.c
@@ -0,0 +1,710 @@
+/*
+ * CDDL HEADER START
+ *
+ * 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]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/sysevent.h>
+#include <libsysevent.h>
+#include <sys/vlds.h>
+#include "libds.h"
+
+#define PTRTOUINT64(ptr) ((uint64_t)((uintptr_t)(ptr)))
+static char vlds_device[] =
+ "/devices/virtual-devices@100/channel-devices@200/"
+ "virtual-domain-service@0:vlds";
+
+typedef struct dslibentry {
+ ds_hdl_t dsl_hdl;
+ uint32_t dsl_flags;
+ char *dsl_service;
+ ds_ops_t dsl_ops;
+} dslibentry_t;
+
+#define MIN_DSLIB_ENTRIES 64
+static dslibentry_t *dslibtab;
+static int ndslib;
+
+/*
+ * Lock to protect the dslibtab table. We only need to protect this
+ * table for those functions which actually look at or modify the table:
+ * service registration (ds_svc_reg/ds_clnt_reg), service unregistration
+ * (ds_hdl_unreg) or during callbacks (ds_recv)
+ */
+static mutex_t dslib_lock;
+
+static int ds_fd = -1;
+
+static char *ds_sid_name = "vlds";
+
+static evchan_t *ds_evchan;
+
+/*
+ * Static functions internal to dslib.
+ */
+static dslibentry_t *ds_hdl_to_dslibentry(ds_hdl_t hdl);
+static dslibentry_t *ds_lookup_dslibentry(char *service, boolean_t is_client);
+static dslibentry_t *ds_register_dslibentry(ds_hdl_t hdl, char *service,
+ boolean_t is_client);
+static void ds_free_dslibentry(dslibentry_t *dsp, int force_unreg);
+static int ds_recv(sysevent_t *sep, void *arg);
+static void ds_string_arg(vlds_string_t *dsp, char *str);
+static int ds_register(ds_capability_t *cap, ds_ops_t *ops, uint_t flags);
+
+static dslibentry_t *
+ds_hdl_to_dslibentry(ds_hdl_t hdl)
+{
+ int i;
+ dslibentry_t *dsp;
+
+ for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) {
+ if (hdl == dsp->dsl_hdl)
+ return (dsp);
+ }
+ return (NULL);
+}
+
+static dslibentry_t *
+ds_new_dslibentry(void)
+{
+ int newndslib;
+ dslibentry_t *dsp;
+
+ if ((dsp = ds_hdl_to_dslibentry(NULL)) != NULL)
+ return (dsp);
+
+ /* double the size */
+ newndslib = ndslib << 1;
+ if ((dslibtab = realloc(dslibtab, newndslib * sizeof (dslibentry_t)))
+ == NULL)
+ return (NULL);
+ dsp = &dslibtab[ndslib];
+ (void) memset(dsp, 0, (newndslib - ndslib) * sizeof (dslibentry_t));
+ ndslib = newndslib;
+ return (dsp);
+}
+
+static dslibentry_t *
+ds_lookup_dslibentry(char *service, boolean_t is_client)
+{
+ int i;
+ dslibentry_t *dsp;
+ uint_t is_client_flag = is_client ? VLDS_REG_CLIENT : 0;
+
+ for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) {
+ if (dsp->dsl_hdl != NULL &&
+ strcmp(dsp->dsl_service, service) == 0 &&
+ (dsp->dsl_flags & VLDS_REG_CLIENT) == is_client_flag) {
+ return (dsp);
+ }
+ }
+ return (NULL);
+}
+
+static dslibentry_t *
+ds_register_dslibentry(ds_hdl_t hdl, char *service, boolean_t is_client)
+{
+ dslibentry_t *dsp, *orig_dsp;
+ uint_t nhdls;
+
+ if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL)
+ return (dsp);
+
+ if ((orig_dsp = ds_lookup_dslibentry(service, is_client)) == NULL) {
+ return (NULL);
+ }
+
+ /*
+ * Find out if we have 1 or 2 or more handles. Having one implies
+ * that we can reuse the current one handle for this service.
+ * Having two or more implies we need to allocate a new handle.
+ */
+ if (ds_hdl_lookup(service, is_client, NULL, 2, &nhdls) != 0)
+ return (NULL);
+
+ if (nhdls == 1) {
+ /* reuse the original structure entry */
+ dsp = orig_dsp;
+ } else if (nhdls == 2) {
+ /* allocate a new structure entry */
+ if ((dsp = ds_new_dslibentry()) == NULL)
+ return (NULL);
+ *dsp = *orig_dsp;
+ dsp->dsl_service = strdup(orig_dsp->dsl_service);
+ } else {
+ /* can't happen... */
+ return (NULL);
+ }
+ dsp->dsl_hdl = hdl;
+ return (dsp);
+}
+
+/*
+ * Want to leave an entry in the dslib table even though all the
+ * handles may have been unregistered for it.
+ */
+static void
+ds_free_dslibentry(dslibentry_t *dsp, int force_unreg)
+{
+ uint_t nhdls;
+
+ /*
+ * Find out if we have 1 or 2 or more handles. Having one implies
+ * that we want to leave the entry alone unless this is a ds_unreg_hdl
+ * (force_unreg is true).
+ */
+ if (ds_hdl_lookup(dsp->dsl_service,
+ (dsp->dsl_flags & VLDS_REG_CLIENT) != 0, NULL, 2, &nhdls) != 0) {
+ /* should never happen */
+ return;
+ }
+
+ if ((nhdls == 1 && force_unreg) || nhdls == 2) {
+ dsp->dsl_hdl = NULL;
+ if (dsp->dsl_service) {
+ free(dsp->dsl_service);
+ }
+ (void) memset(dsp, 0, sizeof (dslibentry_t));
+ }
+}
+
+/*ARGSUSED*/
+static int
+ds_recv(sysevent_t *sep, void *arg)
+{
+ nvlist_t *nvl;
+ uint64_t hdl;
+ ds_ver_t ver;
+ ds_domain_hdl_t dhdl;
+ uchar_t *bufp;
+ boolean_t is_client;
+ uint_t buflen;
+ char *subclass;
+ char *servicep;
+ dslibentry_t *dsp;
+ ds_cb_arg_t cb_arg;
+
+ subclass = sysevent_get_subclass_name(sep);
+ if (sysevent_get_attr_list(sep, &nvl) != 0) {
+ return (0);
+ }
+
+ if (nvlist_lookup_uint64(nvl, VLDS_HDL, &hdl) == 0) {
+ if (strcmp(subclass, ESC_VLDS_REGISTER) == 0) {
+ void (*reg_cb)(ds_hdl_t, ds_cb_arg_t, ds_ver_t *,
+ ds_domain_hdl_t) = NULL;
+
+ if (nvlist_lookup_string(nvl, VLDS_SERVICE_ID,
+ &servicep) == 0 &&
+ nvlist_lookup_boolean_value(nvl, VLDS_ISCLIENT,
+ &is_client) == 0) {
+ (void) mutex_lock(&dslib_lock);
+ if ((dsp = ds_register_dslibentry(hdl,
+ servicep, is_client)) != NULL) {
+ reg_cb = dsp->dsl_ops.ds_reg_cb;
+ cb_arg = dsp->dsl_ops.cb_arg;
+ }
+ (void) mutex_unlock(&dslib_lock);
+ if (reg_cb != NULL &&
+ nvlist_lookup_uint64(nvl, VLDS_DOMAIN_HDL,
+ &dhdl) == 0 &&
+ nvlist_lookup_uint16(nvl, VLDS_VER_MAJOR,
+ &ver.major) == 0 &&
+ nvlist_lookup_uint16(nvl, VLDS_VER_MINOR,
+ &ver.minor) == 0) {
+ (reg_cb)((ds_hdl_t)hdl, cb_arg, &ver,
+ dhdl);
+ }
+ }
+ } else if (strcmp(subclass, ESC_VLDS_UNREGISTER) == 0) {
+ void (*unreg_cb)(ds_hdl_t, ds_cb_arg_t) = NULL;
+
+ (void) mutex_lock(&dslib_lock);
+ if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) {
+ unreg_cb = dsp->dsl_ops.ds_unreg_cb;
+ cb_arg = dsp->dsl_ops.cb_arg;
+ ds_free_dslibentry(dsp, 0);
+ }
+ (void) mutex_unlock(&dslib_lock);
+ if (unreg_cb != NULL) {
+ (unreg_cb)((ds_hdl_t)hdl, cb_arg);
+ }
+ } else if (strcmp(subclass, ESC_VLDS_DATA) == 0) {
+ void (*data_cb)(ds_hdl_t, ds_cb_arg_t, void *,
+ size_t) = NULL;
+
+ (void) mutex_lock(&dslib_lock);
+ if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) {
+ data_cb = dsp->dsl_ops.ds_data_cb;
+ cb_arg = dsp->dsl_ops.cb_arg;
+ }
+ (void) mutex_unlock(&dslib_lock);
+ if (data_cb != NULL &&
+ nvlist_lookup_byte_array(nvl, VLDS_DATA, &bufp,
+ &buflen) == 0) {
+ (data_cb)((ds_hdl_t)hdl, cb_arg, bufp, buflen);
+ }
+ }
+ }
+ nvlist_free(nvl);
+ return (0);
+}
+
+static void
+ds_string_arg(vlds_string_t *dsp, char *str)
+{
+ if (str == NULL) {
+ dsp->vlds_strp = NULL;
+ dsp->vlds_strlen = 0;
+ } else {
+ dsp->vlds_strp = PTRTOUINT64(str);
+ dsp->vlds_strlen = strlen(str) + 1;
+ }
+}
+
+static int
+ds_init_sysev(void)
+{
+ char evchan_name[MAX_CHNAME_LEN];
+
+ (void) sprintf(evchan_name, VLDS_SYSEV_CHAN_FMT, (int)getpid());
+ if (sysevent_evc_bind(evchan_name, &ds_evchan, 0) != 0) {
+ return (errno);
+ }
+ if (sysevent_evc_subscribe(ds_evchan, ds_sid_name, EC_VLDS,
+ ds_recv, NULL, 0) != 0) {
+ sysevent_evc_unbind(ds_evchan);
+ ds_evchan = NULL;
+ return (errno);
+ }
+ return (0);
+}
+
+int
+ds_init(void)
+{
+ if (ds_fd >= 0)
+ return (0);
+
+ if ((ds_fd = open(vlds_device, 0)) < 0)
+ return (errno);
+
+ if (dslibtab == NULL) {
+ if ((dslibtab = malloc(sizeof (dslibentry_t) * ndslib)) == NULL)
+ return (errno = ENOMEM);
+ ndslib = MIN_DSLIB_ENTRIES;
+ (void) memset(dslibtab, 0, sizeof (dslibentry_t) * ndslib);
+ }
+
+ (void) mutex_init(&dslib_lock, USYNC_THREAD, NULL);
+ return (0);
+}
+
+static int
+ds_register(ds_capability_t *cap, ds_ops_t *ops, uint_t flags)
+{
+ dslibentry_t *dsp;
+ vlds_svc_reg_arg_t vlds_arg;
+ vlds_cap_t vlds_cap;
+ vlds_ver_t vlds_vers[VLDS_MAX_VERS];
+ uint64_t hdl_arg;
+ ds_hdl_t hdl;
+ uint_t nhdls;
+ int i;
+
+ if (cap == NULL || ops == NULL || cap->svc_id == NULL ||
+ cap->vers == NULL || (flags & (~VLDS_REG_CLIENT)) != 0) {
+ return (errno = EINVAL);
+ }
+
+ if (cap->nvers > VLDS_MAX_VERS) {
+ return (errno = EINVAL);
+ }
+
+ if (ds_fd < 0 && (errno = ds_init()) != 0) {
+ return (errno);
+ }
+
+ if (ds_hdl_lookup(cap->svc_id, (flags & VLDS_REG_CLIENT), NULL, 1,
+ &nhdls) == 0 && nhdls == 1) {
+ return (errno = EALREADY);
+ }
+
+ (void) mutex_lock(&dslib_lock);
+ if ((dsp = ds_new_dslibentry()) == NULL) {
+ (void) mutex_unlock(&dslib_lock);
+ return (errno = ENOMEM);
+ }
+
+ /* Setup device driver capability structure. */
+
+ /* service string */
+ ds_string_arg(&vlds_cap.vlds_service, cap->svc_id);
+
+ /* version array */
+ for (i = 0; i < cap->nvers; i++) {
+ vlds_vers[i].vlds_major = cap->vers[i].major;
+ vlds_vers[i].vlds_minor = cap->vers[i].minor;
+ }
+ vlds_cap.vlds_versp = PTRTOUINT64(vlds_vers);
+ vlds_cap.vlds_nver = cap->nvers;
+
+ /*
+ * Format args for VLDS_SVC_REG ioctl.
+ */
+
+ vlds_arg.vlds_capp = PTRTOUINT64(&vlds_cap);
+
+ /* op flags */
+ if (ops->ds_reg_cb != NULL)
+ flags |= VLDS_REGCB_VALID;
+ if (ops->ds_unreg_cb != NULL)
+ flags |= VLDS_UNREGCB_VALID;
+ if (ops->ds_data_cb != NULL)
+ flags |= VLDS_DATACB_VALID;
+ vlds_arg.vlds_reg_flags = flags;
+
+ /* returned handle */
+ vlds_arg.vlds_hdlp = PTRTOUINT64(&hdl_arg);
+
+ if (ioctl(ds_fd, VLDS_SVC_REG, &vlds_arg) < 0) {
+ (void) mutex_unlock(&dslib_lock);
+ return (errno);
+ }
+
+ /*
+ * Setup user callback sysevent channel.
+ */
+ if ((flags & VLDS_ANYCB_VALID) != 0 && ds_evchan == NULL &&
+ ds_init_sysev() != 0) {
+ (void) mutex_unlock(&dslib_lock);
+ (void) ioctl(ds_fd, VLDS_UNREG_HDL, &vlds_arg);
+ return (errno);
+ }
+
+ hdl = hdl_arg;
+
+ /*
+ * Set entry values in dslibtab.
+ */
+ dsp->dsl_hdl = hdl;
+ dsp->dsl_flags = flags;
+ dsp->dsl_service = strdup(cap->svc_id);
+ dsp->dsl_ops = *ops;
+ (void) mutex_unlock(&dslib_lock);
+ return (0);
+}
+
+/*
+ * Registers a service provider. Kicks off the handshake with other
+ * domain(s) to announce servce. Callback events are as described above.
+ */
+int
+ds_svc_reg(ds_capability_t *cap, ds_ops_t *ops)
+{
+ return (ds_register(cap, ops, 0));
+}
+
+/*
+ * Registers interest in a service from a specific domain. When that
+ * service is registered, the register callback is invoked. When that
+ * service is unregistered, the unregister callback is invoked. When
+ * data is received, the receive data callback is invoked.
+ */
+int
+ds_clnt_reg(ds_capability_t *cap, ds_ops_t *ops)
+{
+ return (ds_register(cap, ops, VLDS_REG_CLIENT));
+}
+
+/*
+ * Given a service name and type, returns the existing handle(s), if
+ * one or more exist. This could be used to poll for the connection being
+ * registered or unregistered, rather than using the register/unregister
+ * callbacks.
+ */
+int
+ds_hdl_lookup(char *service, boolean_t is_client, ds_hdl_t *hdlsp,
+ uint_t maxhdls, uint_t *nhdlsp)
+{
+ vlds_hdl_lookup_arg_t vlds_arg;
+ uint64_t nhdls_arg;
+
+ errno = 0;
+ if (ds_fd < 0) {
+ return (errno = EBADF);
+ }
+
+ if (service == NULL) {
+ return (errno = EINVAL);
+ }
+
+ ds_string_arg(&vlds_arg.vlds_service, service);
+ vlds_arg.vlds_isclient = is_client ? VLDS_REG_CLIENT : 0;
+ vlds_arg.vlds_hdlsp = PTRTOUINT64(hdlsp);
+ vlds_arg.vlds_maxhdls = maxhdls;
+ vlds_arg.vlds_nhdlsp = PTRTOUINT64(&nhdls_arg);
+
+ if (ioctl(ds_fd, VLDS_HDL_LOOKUP, &vlds_arg) < 0) {
+ return (errno);
+ }
+
+ *nhdlsp = nhdls_arg;
+ return (0);
+}
+
+/*
+ * Given a handle, return its associated domain.
+ */
+int
+ds_domain_lookup(ds_hdl_t hdl, ds_domain_hdl_t *dhdlp)
+{
+ vlds_dmn_lookup_arg_t vlds_arg;
+ uint64_t dhdl_arg;
+
+ if (ds_fd < 0) {
+ return (errno = EBADF);
+ }
+
+ vlds_arg.vlds_hdl = hdl;
+ vlds_arg.vlds_dhdlp = PTRTOUINT64(&dhdl_arg);
+
+ if (ioctl(ds_fd, VLDS_DMN_LOOKUP, &vlds_arg) < 0) {
+ return (errno);
+ }
+
+ if (dhdlp) {
+ *dhdlp = dhdl_arg;
+ }
+
+ return (0);
+}
+
+/*
+ * Unregisters either a service or an interest in that service
+ * indicated by the supplied handle.
+ */
+int
+ds_unreg_hdl(ds_hdl_t hdl)
+{
+ dslibentry_t *dsp;
+ vlds_unreg_hdl_arg_t vlds_arg;
+
+ (void) mutex_lock(&dslib_lock);
+ if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) {
+ ds_free_dslibentry(dsp, 1);
+ }
+ (void) mutex_unlock(&dslib_lock);
+
+ if (ds_fd >= 0) {
+ vlds_arg.vlds_hdl = hdl;
+ (void) ioctl(ds_fd, VLDS_UNREG_HDL, &vlds_arg);
+ }
+
+ return (0);
+}
+
+/*
+ * Send data to the appropriate service provider or client
+ * indicated by the provided handle. The sender will block
+ * until the message has been sent. There is no guarantee
+ * that multiple calls to ds_send_msg by the same thread
+ * will result in the data showing up at the receiver in
+ * the same order as sent. If multiple messages are required,
+ * it will be up to the sender and receiver to implement a
+ * protocol.
+ */
+int
+ds_send_msg(ds_hdl_t hdl, void *buf, size_t buflen)
+{
+ vlds_send_msg_arg_t vlds_arg;
+
+ if (ds_fd < 0) {
+ return (errno = EBADF);
+ }
+
+ vlds_arg.vlds_hdl = hdl;
+ vlds_arg.vlds_bufp = PTRTOUINT64(buf);
+ vlds_arg.vlds_buflen = buflen;
+
+ if (ioctl(ds_fd, VLDS_SEND_MSG, &vlds_arg) < 0) {
+ return (errno);
+ }
+
+ return (0);
+}
+
+/*
+ * Receive data from the appropriate service provider or client
+ * indicated by the provided handle. The sender will block
+ * until a message has been received.
+ */
+int
+ds_recv_msg(ds_hdl_t hdl, void *buf, size_t buflen, size_t *msglen)
+{
+ vlds_recv_msg_arg_t vlds_arg;
+ uint64_t msglen_arg;
+
+ if (ds_fd < 0) {
+ return (errno = EBADF);
+ }
+
+ vlds_arg.vlds_hdl = hdl;
+ vlds_arg.vlds_bufp = PTRTOUINT64(buf);
+ vlds_arg.vlds_buflen = buflen;
+ vlds_arg.vlds_msglenp = PTRTOUINT64(&msglen_arg);
+
+ if (ioctl(ds_fd, VLDS_RECV_MSG, &vlds_arg) < 0) {
+ if (errno == EFBIG && msglen) {
+ *msglen = msglen_arg;
+ }
+ return (errno);
+ }
+
+ if (msglen) {
+ *msglen = msglen_arg;
+ }
+
+ return (0);
+}
+
+int
+ds_isready(ds_hdl_t hdl, boolean_t *is_ready)
+{
+ vlds_hdl_isready_arg_t vlds_arg;
+ uint64_t is_ready_arg;
+
+ if (ds_fd < 0) {
+ return (errno = EBADF);
+ }
+
+ vlds_arg.vlds_hdl = hdl;
+ vlds_arg.vlds_isreadyp = PTRTOUINT64(&is_ready_arg);
+
+ if (ioctl(ds_fd, VLDS_HDL_ISREADY, &vlds_arg) < 0) {
+ return (errno);
+ }
+
+ *is_ready = (is_ready_arg != 0);
+ return (0);
+}
+
+/*
+ * Given a domain name, return its associated domain handle.
+ */
+int
+ds_dom_name_to_hdl(char *domain_name, ds_domain_hdl_t *dhdlp)
+{
+ vlds_dom_nam2hdl_arg_t vlds_arg;
+ uint64_t dhdl_arg;
+
+ if (ds_fd < 0) {
+ return (errno = EBADF);
+ }
+
+ ds_string_arg(&vlds_arg.vlds_domain_name, domain_name);
+ vlds_arg.vlds_dhdlp = PTRTOUINT64(&dhdl_arg);
+
+ if (ioctl(ds_fd, VLDS_DOM_NAM2HDL, &vlds_arg) < 0) {
+ return (errno);
+ }
+
+ if (dhdlp) {
+ *dhdlp = dhdl_arg;
+ }
+
+ return (0);
+}
+
+/*
+ * Given a domain handle, return its associated domain name.
+ */
+int
+ds_dom_hdl_to_name(ds_domain_hdl_t dhdl, char *domain_name, uint_t maxnamlen)
+{
+ vlds_dom_hdl2nam_arg_t vlds_arg;
+
+ if (ds_fd < 0) {
+ return (errno = EBADF);
+ }
+
+ vlds_arg.vlds_dhdl = dhdl;
+ vlds_arg.vlds_domain_name.vlds_strp = PTRTOUINT64(domain_name);
+ vlds_arg.vlds_domain_name.vlds_strlen = maxnamlen;
+
+ if (ioctl(ds_fd, VLDS_DOM_HDL2NAM, &vlds_arg) < 0) {
+ return (errno);
+ }
+
+ return (0);
+}
+
+void
+ds_unreg_svc(char *service, boolean_t is_client)
+{
+ ds_hdl_t hdl;
+ uint_t nhdls;
+
+ while (ds_hdl_lookup(service, is_client, &hdl, 1, &nhdls) == 0 &&
+ nhdls == 1) {
+ (void) ds_unreg_hdl(hdl);
+ }
+}
+
+void
+ds_fini(void)
+{
+ int i;
+ dslibentry_t *dsp;
+
+ if (ds_fd >= 0) {
+ (void) close(ds_fd);
+ ds_fd = -1;
+ }
+ if (ds_evchan) {
+ (void) sysevent_evc_unsubscribe(ds_evchan, ds_sid_name);
+ (void) sysevent_evc_unbind(ds_evchan);
+ ds_evchan = NULL;
+ }
+ if (ndslib > 0) {
+ (void) mutex_lock(&dslib_lock);
+ for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) {
+ if (dsp->dsl_hdl == NULL)
+ continue;
+ if (dsp->dsl_service) {
+ free(dsp->dsl_service);
+ }
+ }
+ free(dslibtab);
+ ndslib = 0;
+ dslibtab = NULL;
+ (void) mutex_unlock(&dslib_lock);
+ (void) mutex_destroy(&dslib_lock);
+ }
+}
diff --git a/usr/src/lib/libds/common/libds.h b/usr/src/lib/libds/common/libds.h
new file mode 100644
index 0000000000..149e53c91a
--- /dev/null
+++ b/usr/src/lib/libds/common/libds.h
@@ -0,0 +1,95 @@
+/*
+ * CDDL HEADER START
+ *
+ * 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]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBDS_H
+#define _LIBDS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+/*
+ * LDOMs User Domain Services library Interfaces
+ */
+
+typedef uint64_t ds_hdl_t; /* service handle */
+typedef uint64_t ds_domain_hdl_t; /* domain handle */
+typedef void *ds_cb_arg_t; /* client callback arg */
+
+#define DS_INVALID_HDL (0) /* a ds handle cannot be zero */
+
+/*
+ * LDOMs User Domain Services versioning
+ */
+typedef struct ds_ver {
+ uint16_t major;
+ uint16_t minor;
+} ds_ver_t;
+
+/*
+ * LDOMs User Domain Services capability
+ */
+typedef struct ds_capability {
+ char *svc_id; /* service identifier */
+ ds_ver_t *vers; /* list of supported versions */
+ uint_t nvers; /* number of supported versions */
+} ds_capability_t;
+
+/*
+ * LDOMs User Domain Services event callbacks
+ */
+typedef struct ds_ops {
+ void (*ds_reg_cb)(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver,
+ ds_domain_hdl_t dhdl);
+ void (*ds_unreg_cb)(ds_hdl_t hdl, ds_cb_arg_t arg);
+ void (*ds_data_cb)(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf,
+ size_t buflen);
+ ds_cb_arg_t cb_arg;
+} ds_ops_t;
+
+extern int ds_init(void);
+extern int ds_svc_reg(ds_capability_t *cap, ds_ops_t *ops);
+extern int ds_clnt_reg(ds_capability_t *cap, ds_ops_t *ops);
+extern int ds_hdl_lookup(char *service, boolean_t is_client, ds_hdl_t *hdlsp,
+ uint_t maxhdls, uint_t *nhdlsp);
+extern int ds_domain_lookup(ds_hdl_t hdl, ds_domain_hdl_t *dhdlp);
+extern int ds_unreg_hdl(ds_hdl_t hdl);
+extern int ds_send_msg(ds_hdl_t hdl, void *buf, size_t buflen);
+extern int ds_recv_msg(ds_hdl_t hdl, void *buf, size_t buflen,
+ size_t *msglen);
+extern int ds_isready(ds_hdl_t hdl, boolean_t *is_ready);
+extern int ds_dom_name_to_hdl(char *domain_name, ds_domain_hdl_t *dhdlp);
+extern int ds_dom_hdl_to_name(ds_domain_hdl_t dhdl, char *domain_name,
+ uint_t maxnamlen);
+extern void ds_unreg_svc(char *service, boolean_t is_client);
+extern void ds_fini(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBDS_H */
diff --git a/usr/src/lib/libds/common/llib-lds b/usr/src/lib/libds/common/llib-lds
new file mode 100644
index 0000000000..83867420d8
--- /dev/null
+++ b/usr/src/lib/libds/common/llib-lds
@@ -0,0 +1,29 @@
+/*
+ * CDDL HEADER START
+ *
+ * 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]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include "libds.h"
diff --git a/usr/src/lib/libds/common/mapfile-vers b/usr/src/lib/libds/common/mapfile-vers
new file mode 100644
index 0000000000..889d1c47f0
--- /dev/null
+++ b/usr/src/lib/libds/common/mapfile-vers
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# 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]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+SUNWprivate {
+ global:
+ ds_init;
+ ds_svc_reg;
+ ds_clnt_reg;
+ ds_hdl_lookup;
+ ds_domain_lookup;
+ ds_unreg_hdl;
+ ds_send_msg;
+ ds_recv_msg;
+ ds_isready;
+ ds_dom_name_to_hdl;
+ ds_dom_hdl_to_name;
+ ds_unreg_svc;
+ ds_fini;
+ local:
+ *;
+};
diff --git a/usr/src/lib/libds/sparc/Makefile b/usr/src/lib/libds/sparc/Makefile
new file mode 100644
index 0000000000..ea09428ea0
--- /dev/null
+++ b/usr/src/lib/libds/sparc/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# 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]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libds/sparcv9/Makefile b/usr/src/lib/libds/sparcv9/Makefile
new file mode 100644
index 0000000000..40e4cef06c
--- /dev/null
+++ b/usr/src/lib/libds/sparcv9/Makefile
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# 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]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)