111833SMichael.Christensen@Sun.COM /*
211833SMichael.Christensen@Sun.COM * CDDL HEADER START
311833SMichael.Christensen@Sun.COM *
411833SMichael.Christensen@Sun.COM * The contents of this file are subject to the terms of the
511833SMichael.Christensen@Sun.COM * Common Development and Distribution License (the "License").
611833SMichael.Christensen@Sun.COM * You may not use this file except in compliance with the License.
711833SMichael.Christensen@Sun.COM *
811833SMichael.Christensen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911833SMichael.Christensen@Sun.COM * or http://www.opensolaris.org/os/licensing.
1011833SMichael.Christensen@Sun.COM * See the License for the specific language governing permissions
1111833SMichael.Christensen@Sun.COM * and limitations under the License.
1211833SMichael.Christensen@Sun.COM *
1311833SMichael.Christensen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1411833SMichael.Christensen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511833SMichael.Christensen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1611833SMichael.Christensen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1711833SMichael.Christensen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1811833SMichael.Christensen@Sun.COM *
1911833SMichael.Christensen@Sun.COM * CDDL HEADER END
2011833SMichael.Christensen@Sun.COM */
2111833SMichael.Christensen@Sun.COM /*
22*12913SMichael.Christensen@Sun.COM * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2311833SMichael.Christensen@Sun.COM */
2411833SMichael.Christensen@Sun.COM
2511833SMichael.Christensen@Sun.COM #include <dlfcn.h>
2611833SMichael.Christensen@Sun.COM #include <errno.h>
2711833SMichael.Christensen@Sun.COM #include <fcntl.h>
2811833SMichael.Christensen@Sun.COM #include <stdio.h>
2911833SMichael.Christensen@Sun.COM #include <stdlib.h>
3011833SMichael.Christensen@Sun.COM #include <strings.h>
3111833SMichael.Christensen@Sun.COM #include <synch.h>
3211833SMichael.Christensen@Sun.COM #include <thread.h>
3311833SMichael.Christensen@Sun.COM #include <unistd.h>
3411833SMichael.Christensen@Sun.COM #include <utility.h>
3511833SMichael.Christensen@Sun.COM #include <sys/mdesc.h>
3611833SMichael.Christensen@Sun.COM #include <sys/mdesc_impl.h>
3711833SMichael.Christensen@Sun.COM #include <sys/debug.h>
3811833SMichael.Christensen@Sun.COM #include <sys/stat.h>
3911833SMichael.Christensen@Sun.COM #include <sys/types.h>
4011833SMichael.Christensen@Sun.COM #include <sys/utsname.h>
4111833SMichael.Christensen@Sun.COM
4211833SMichael.Christensen@Sun.COM #include "ldma.h"
4311833SMichael.Christensen@Sun.COM #include "libds.h"
4411833SMichael.Christensen@Sun.COM #include "libv12n.h"
4511833SMichael.Christensen@Sun.COM
4611833SMichael.Christensen@Sun.COM /*
4711833SMichael.Christensen@Sun.COM * sun4 support for libv12n.
4811833SMichael.Christensen@Sun.COM *
4911833SMichael.Christensen@Sun.COM * Non-sun4v support is minimal. The v12n_capabilities() function will
5011833SMichael.Christensen@Sun.COM * only return 0 (not supported, not enabled, no implementation).
5111833SMichael.Christensen@Sun.COM *
5211833SMichael.Christensen@Sun.COM * For sun4v the support for v12n_capabilities(), v12n_domain_roles(),
5311833SMichael.Christensen@Sun.COM * v12n_domain_name() and v12n_domain_uuid() are supported by scanning the
5411833SMichael.Christensen@Sun.COM * MD from /dev/mdesc for specific properties. For v12n_ctrl_domain() and
5511833SMichael.Christensen@Sun.COM * v12n_chassis_serialno(), the ldoms agent daemon (ldmad) on the control
5611833SMichael.Christensen@Sun.COM * domain supplies the required information via the "agent-system" domain
5711833SMichael.Christensen@Sun.COM * service.
5811833SMichael.Christensen@Sun.COM */
5911833SMichael.Christensen@Sun.COM
6011833SMichael.Christensen@Sun.COM /* libds statics */
6111833SMichael.Christensen@Sun.COM static void *v12n_ds_dlhdl = NULL;
6211833SMichael.Christensen@Sun.COM static int (*v12n_ds_send_msg)(ds_hdl_t, void *, size_t) = NULL;
6311833SMichael.Christensen@Sun.COM static int (*v12n_ds_clnt_reg)(ds_capability_t *, ds_ops_t *);
6411833SMichael.Christensen@Sun.COM static int (*v12n_ds_unreg_svc)(char *, boolean_t);
6511833SMichael.Christensen@Sun.COM
6611833SMichael.Christensen@Sun.COM /*
6711833SMichael.Christensen@Sun.COM * Defines to support the 'agent-system' domain service.
6811833SMichael.Christensen@Sun.COM */
6911833SMichael.Christensen@Sun.COM
7011833SMichael.Christensen@Sun.COM #define LDMA_SYSTEM_NVERS \
7111833SMichael.Christensen@Sun.COM (sizeof (v12n_ldma_system_vers) / sizeof (ds_ver_t))
7211833SMichael.Christensen@Sun.COM static ds_ver_t v12n_ldma_system_vers[] = { { 1, 0} };
7311833SMichael.Christensen@Sun.COM
7411833SMichael.Christensen@Sun.COM static ds_capability_t v12n_ldma_cap = {
7511833SMichael.Christensen@Sun.COM LDMA_NAME_SYSTEM, /* svc_id */
7611833SMichael.Christensen@Sun.COM v12n_ldma_system_vers, /* vers */
7711833SMichael.Christensen@Sun.COM LDMA_SYSTEM_NVERS /* nvers */
7811833SMichael.Christensen@Sun.COM };
7911833SMichael.Christensen@Sun.COM
8011833SMichael.Christensen@Sun.COM static void v12n_ldma_register_handler(ds_hdl_t hdl, ds_cb_arg_t arg,
8111833SMichael.Christensen@Sun.COM ds_ver_t *ver, ds_domain_hdl_t dhdl);
8211833SMichael.Christensen@Sun.COM static void v12n_ldma_data_handler(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf,
8311833SMichael.Christensen@Sun.COM size_t buflen);
8411833SMichael.Christensen@Sun.COM
8511833SMichael.Christensen@Sun.COM static ds_ops_t v12n_ldma_ops = {
8611833SMichael.Christensen@Sun.COM v12n_ldma_register_handler, /* ds_reg_cb */
8711833SMichael.Christensen@Sun.COM NULL, /* ds_unreg_cb */
8811833SMichael.Christensen@Sun.COM v12n_ldma_data_handler, /* ds_data_cb */
8911833SMichael.Christensen@Sun.COM NULL /* ds_cb_arg */
9011833SMichael.Christensen@Sun.COM };
9111833SMichael.Christensen@Sun.COM
9211833SMichael.Christensen@Sun.COM /* v12n_ldma_cv_state values */
9311833SMichael.Christensen@Sun.COM #define V12N_LDMA_CVINVALID -1 /* invalid value for cv_state */
9411833SMichael.Christensen@Sun.COM #define V12N_LDMA_REGWAITING 0 /* waiting for ctrl domain reg */
9511833SMichael.Christensen@Sun.COM #define V12N_LDMA_REGRECEIVED 1 /* received ctrl domain reg */
9611833SMichael.Christensen@Sun.COM #define V12N_LDMA_MSGWAITING 2 /* waiting for message response */
9711833SMichael.Christensen@Sun.COM #define V12N_LDMA_MSGRECEIVED 3 /* received message response */
9811833SMichael.Christensen@Sun.COM #define V12N_LDMA_MSGERROR 4 /* received a bad message */
9911833SMichael.Christensen@Sun.COM
10011833SMichael.Christensen@Sun.COM /* 'agent-system' data used in async registration/data message handlers */
10111833SMichael.Christensen@Sun.COM static ds_hdl_t v12n_ldma_ctrl_hdl = DS_INVALID_HDL;
10211833SMichael.Christensen@Sun.COM static int v12n_ldma_msgtype;
10311833SMichael.Christensen@Sun.COM static char *v12n_ldma_msgstr;
10411833SMichael.Christensen@Sun.COM static mutex_t v12n_ldma_lock = DEFAULTMUTEX;
10511833SMichael.Christensen@Sun.COM static cond_t v12n_ldma_cv = DEFAULTCV;
10611833SMichael.Christensen@Sun.COM static int v12n_ldma_cv_state = V12N_LDMA_CVINVALID;
10711833SMichael.Christensen@Sun.COM static mutex_t v12n_ldma_cv_lock = DEFAULTMUTEX;
10811833SMichael.Christensen@Sun.COM
10911833SMichael.Christensen@Sun.COM /* 'agent-system' timeout values in seconds */
11011833SMichael.Christensen@Sun.COM static int v12n_ldma_timeout = 15;
11111833SMichael.Christensen@Sun.COM static int v12n_ldma_sleeptime = 1;
11211833SMichael.Christensen@Sun.COM
11311833SMichael.Christensen@Sun.COM
11411833SMichael.Christensen@Sun.COM #define V12N_LDOMS_SUPPORTED (V12N_CAP_SUPPORTED | V12N_CAP_ENABLED | \
11511833SMichael.Christensen@Sun.COM V12N_CAP_IMPL_LDOMS)
11611833SMichael.Christensen@Sun.COM
11711833SMichael.Christensen@Sun.COM #define MD_DEVICE "/dev/mdesc"
11811833SMichael.Christensen@Sun.COM
11911833SMichael.Christensen@Sun.COM /*
12011833SMichael.Christensen@Sun.COM * libv12n routines to support /dev/mdesc.
12111833SMichael.Christensen@Sun.COM */
12211833SMichael.Christensen@Sun.COM
12311833SMichael.Christensen@Sun.COM /*
12411833SMichael.Christensen@Sun.COM * Wrapper for MD free: need unused size argument.
12511833SMichael.Christensen@Sun.COM */
12611833SMichael.Christensen@Sun.COM /* ARGSUSED */
12711833SMichael.Christensen@Sun.COM static void
v12n_md_free(void * buf,size_t n)12811833SMichael.Christensen@Sun.COM v12n_md_free(void *buf, size_t n)
12911833SMichael.Christensen@Sun.COM {
13011833SMichael.Christensen@Sun.COM free(buf);
13111833SMichael.Christensen@Sun.COM }
13211833SMichael.Christensen@Sun.COM
13311833SMichael.Christensen@Sun.COM /*
13411833SMichael.Christensen@Sun.COM * Wrapper for MD init: read MD and invoke md_init_intern.
13511833SMichael.Christensen@Sun.COM */
13611833SMichael.Christensen@Sun.COM static md_t *
v12n_md_init()13711833SMichael.Christensen@Sun.COM v12n_md_init()
13811833SMichael.Christensen@Sun.COM {
13911833SMichael.Christensen@Sun.COM md_t *mdp;
14011833SMichael.Christensen@Sun.COM char *buf = NULL;
14111833SMichael.Christensen@Sun.COM md_header_t mdh;
14211833SMichael.Christensen@Sun.COM int md_size;
14311833SMichael.Christensen@Sun.COM int fd;
14411833SMichael.Christensen@Sun.COM
14511833SMichael.Christensen@Sun.COM /*
14611833SMichael.Christensen@Sun.COM * Open the Machine Description (MD)
14711833SMichael.Christensen@Sun.COM */
14811833SMichael.Christensen@Sun.COM fd = open(MD_DEVICE, O_RDONLY);
14911833SMichael.Christensen@Sun.COM if (fd == -1) {
15011833SMichael.Christensen@Sun.COM return (NULL);
15111833SMichael.Christensen@Sun.COM }
15211833SMichael.Christensen@Sun.COM
15311833SMichael.Christensen@Sun.COM if (read(fd, &mdh, sizeof (md_header_t)) != sizeof (md_header_t))
15411833SMichael.Christensen@Sun.COM goto errdone;
15511833SMichael.Christensen@Sun.COM
15611833SMichael.Christensen@Sun.COM md_size = sizeof (md_header_t) + mdh.node_blk_sz + mdh.name_blk_sz +
15711833SMichael.Christensen@Sun.COM mdh.data_blk_sz;
15811833SMichael.Christensen@Sun.COM
15911833SMichael.Christensen@Sun.COM if ((buf = malloc(md_size)) == NULL)
16011833SMichael.Christensen@Sun.COM goto errdone;
16111833SMichael.Christensen@Sun.COM
16211833SMichael.Christensen@Sun.COM (void) memcpy(buf, &mdh, sizeof (md_header_t));
16311833SMichael.Christensen@Sun.COM if (read(fd, buf + sizeof (md_header_t),
16411833SMichael.Christensen@Sun.COM md_size - sizeof (md_header_t)) != md_size - sizeof (md_header_t)) {
16511833SMichael.Christensen@Sun.COM goto errdone;
16611833SMichael.Christensen@Sun.COM }
16711833SMichael.Christensen@Sun.COM
16811833SMichael.Christensen@Sun.COM mdp = md_init_intern((uint64_t *)((void *)buf), malloc, v12n_md_free);
16911833SMichael.Christensen@Sun.COM
17011833SMichael.Christensen@Sun.COM (void) close(fd);
17111833SMichael.Christensen@Sun.COM
17211833SMichael.Christensen@Sun.COM return (mdp);
17311833SMichael.Christensen@Sun.COM
17411833SMichael.Christensen@Sun.COM errdone:
17511833SMichael.Christensen@Sun.COM (void) close(fd);
17611833SMichael.Christensen@Sun.COM free(buf);
17711833SMichael.Christensen@Sun.COM
17811833SMichael.Christensen@Sun.COM return (NULL);
17911833SMichael.Christensen@Sun.COM }
18011833SMichael.Christensen@Sun.COM
18111833SMichael.Christensen@Sun.COM /*
18211833SMichael.Christensen@Sun.COM * Wrapper for md_fini. Allow NULL md ptr and free MD buffer.
18311833SMichael.Christensen@Sun.COM */
18411833SMichael.Christensen@Sun.COM static void
v12n_md_fini(void * md)18511833SMichael.Christensen@Sun.COM v12n_md_fini(void *md)
18611833SMichael.Christensen@Sun.COM {
18711833SMichael.Christensen@Sun.COM md_impl_t *mdp = (md_impl_t *)md;
18811833SMichael.Christensen@Sun.COM
18911833SMichael.Christensen@Sun.COM if (mdp) {
19011833SMichael.Christensen@Sun.COM free(mdp->caddr);
19111833SMichael.Christensen@Sun.COM (void) md_fini(md);
19211833SMichael.Christensen@Sun.COM }
19311833SMichael.Christensen@Sun.COM }
19411833SMichael.Christensen@Sun.COM
19511833SMichael.Christensen@Sun.COM /*
19611833SMichael.Christensen@Sun.COM * See if LDoms domaining is enabled, returns 1 if enabled.
19711833SMichael.Christensen@Sun.COM * Get the value of the 'domaining-enabled' property under the
19811833SMichael.Christensen@Sun.COM * 'platform' node. Value of 1 => domaining is enabled.
19911833SMichael.Christensen@Sun.COM */
20011833SMichael.Christensen@Sun.COM static int
v12n_domaining_enabled()20111833SMichael.Christensen@Sun.COM v12n_domaining_enabled()
20211833SMichael.Christensen@Sun.COM {
20311833SMichael.Christensen@Sun.COM mde_cookie_t *nodes, rootnode;
20411833SMichael.Christensen@Sun.COM int nnodes;
20511833SMichael.Christensen@Sun.COM uint64_t prop_val = 0;
20611833SMichael.Christensen@Sun.COM md_t *mdp;
20711833SMichael.Christensen@Sun.COM
20811833SMichael.Christensen@Sun.COM if ((mdp = v12n_md_init()) == NULL) {
20911833SMichael.Christensen@Sun.COM return (0);
21011833SMichael.Christensen@Sun.COM }
21111833SMichael.Christensen@Sun.COM
21211833SMichael.Christensen@Sun.COM nnodes = md_node_count(mdp);
21311833SMichael.Christensen@Sun.COM nodes = malloc(nnodes * sizeof (mde_cookie_t));
21411833SMichael.Christensen@Sun.COM if (nodes == NULL) {
21511833SMichael.Christensen@Sun.COM v12n_md_fini(mdp);
21611833SMichael.Christensen@Sun.COM return (0);
21711833SMichael.Christensen@Sun.COM }
21811833SMichael.Christensen@Sun.COM
21911833SMichael.Christensen@Sun.COM rootnode = md_root_node(mdp);
22011833SMichael.Christensen@Sun.COM
22111833SMichael.Christensen@Sun.COM nnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"),
22211833SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), nodes);
22311833SMichael.Christensen@Sun.COM
22411833SMichael.Christensen@Sun.COM if (nnodes >= 1) {
22511833SMichael.Christensen@Sun.COM (void) md_get_prop_val(mdp, nodes[0], "domaining-enabled",
22611833SMichael.Christensen@Sun.COM &prop_val);
22711833SMichael.Christensen@Sun.COM }
22811833SMichael.Christensen@Sun.COM
22911833SMichael.Christensen@Sun.COM v12n_md_fini(mdp);
23011833SMichael.Christensen@Sun.COM free(nodes);
23111833SMichael.Christensen@Sun.COM return (prop_val == 1);
23211833SMichael.Christensen@Sun.COM }
23311833SMichael.Christensen@Sun.COM
23411833SMichael.Christensen@Sun.COM int
v12n_capabilities()23511833SMichael.Christensen@Sun.COM v12n_capabilities()
23611833SMichael.Christensen@Sun.COM {
23711833SMichael.Christensen@Sun.COM struct utsname uinfo;
23811833SMichael.Christensen@Sun.COM struct stat st;
23911833SMichael.Christensen@Sun.COM int cap;
24011833SMichael.Christensen@Sun.COM
24111833SMichael.Christensen@Sun.COM /*
24211833SMichael.Christensen@Sun.COM * Check if this is an LDoms system. When using LDoms each
24311833SMichael.Christensen@Sun.COM * domain should have a /dev/mdesc device providing access to
24411833SMichael.Christensen@Sun.COM * the Machine Description (MD) of the domain. If this device
24511833SMichael.Christensen@Sun.COM * does not exist then this is not an LDoms system.
24611833SMichael.Christensen@Sun.COM */
24711833SMichael.Christensen@Sun.COM if (uname(&uinfo) == -1 || strcmp(uinfo.machine, "sun4v")) {
24811833SMichael.Christensen@Sun.COM /*
24911833SMichael.Christensen@Sun.COM * Not sun4v -> LDoms not supported
25011833SMichael.Christensen@Sun.COM */
25111833SMichael.Christensen@Sun.COM cap = 0;
25211833SMichael.Christensen@Sun.COM } else if (stat(MD_DEVICE, &st) == 0) {
25311833SMichael.Christensen@Sun.COM /*
25411833SMichael.Christensen@Sun.COM * sun4v + /dev/mdesc exists -> Check if LDoms enabled
25511833SMichael.Christensen@Sun.COM * via the 'domaining-enabled' property.
25611833SMichael.Christensen@Sun.COM */
25711833SMichael.Christensen@Sun.COM cap = (V12N_CAP_SUPPORTED | V12N_CAP_IMPL_LDOMS |
25811833SMichael.Christensen@Sun.COM (v12n_domaining_enabled() ? V12N_CAP_ENABLED : 0));
25911833SMichael.Christensen@Sun.COM } else if (errno == ENOENT) {
26011833SMichael.Christensen@Sun.COM /*
26111833SMichael.Christensen@Sun.COM * sun4v + /dev/mdesc does not exist -> LDoms supported
26211833SMichael.Christensen@Sun.COM * but not enabled.
26311833SMichael.Christensen@Sun.COM */
26411833SMichael.Christensen@Sun.COM cap = (V12N_CAP_SUPPORTED | V12N_CAP_IMPL_LDOMS);
26511833SMichael.Christensen@Sun.COM }
26611833SMichael.Christensen@Sun.COM
26711833SMichael.Christensen@Sun.COM return (cap);
26811833SMichael.Christensen@Sun.COM }
26911833SMichael.Christensen@Sun.COM
27011833SMichael.Christensen@Sun.COM /*
27111833SMichael.Christensen@Sun.COM * Routines to support v12n_domain_roles.
27211833SMichael.Christensen@Sun.COM */
27311833SMichael.Christensen@Sun.COM static int
v12n_scan_md_nodes(md_t * mdp,char * node_name,char * node_str_prop,char ** props)27411833SMichael.Christensen@Sun.COM v12n_scan_md_nodes(md_t *mdp, char *node_name, char *node_str_prop,
27511833SMichael.Christensen@Sun.COM char **props)
27611833SMichael.Christensen@Sun.COM {
27711833SMichael.Christensen@Sun.COM mde_cookie_t *nodes, rootnode;
27811833SMichael.Christensen@Sun.COM int nnodes, i, j;
27911833SMichael.Christensen@Sun.COM char *prop_str;
28011833SMichael.Christensen@Sun.COM
28111833SMichael.Christensen@Sun.COM nnodes = md_node_count(mdp);
28211833SMichael.Christensen@Sun.COM nodes = malloc(nnodes * sizeof (mde_cookie_t));
28311833SMichael.Christensen@Sun.COM if (nodes == NULL) {
28411833SMichael.Christensen@Sun.COM return (0);
28511833SMichael.Christensen@Sun.COM }
28611833SMichael.Christensen@Sun.COM
28711833SMichael.Christensen@Sun.COM rootnode = md_root_node(mdp);
28811833SMichael.Christensen@Sun.COM
28911833SMichael.Christensen@Sun.COM nnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, node_name),
29011833SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), nodes);
29111833SMichael.Christensen@Sun.COM
29211833SMichael.Christensen@Sun.COM if (node_str_prop == NULL)
29311833SMichael.Christensen@Sun.COM return (nnodes > 0);
29411833SMichael.Christensen@Sun.COM
29511833SMichael.Christensen@Sun.COM for (i = 0; i < nnodes; i++) {
29611833SMichael.Christensen@Sun.COM if (md_get_prop_str(mdp, nodes[i], node_str_prop, &prop_str))
29711833SMichael.Christensen@Sun.COM continue;
29811833SMichael.Christensen@Sun.COM for (j = 0; props[j] != NULL; j++) {
29911833SMichael.Christensen@Sun.COM if (strcmp(prop_str, props[j]) == 0) {
30011833SMichael.Christensen@Sun.COM free(nodes);
30111833SMichael.Christensen@Sun.COM return (1);
30211833SMichael.Christensen@Sun.COM }
30311833SMichael.Christensen@Sun.COM }
30411833SMichael.Christensen@Sun.COM }
30511833SMichael.Christensen@Sun.COM free(nodes);
30611833SMichael.Christensen@Sun.COM return (0);
30711833SMichael.Christensen@Sun.COM }
30811833SMichael.Christensen@Sun.COM
30911833SMichael.Christensen@Sun.COM /*
31011833SMichael.Christensen@Sun.COM * Check if MD has a hypervisor access point, returns 1 if true.
31111833SMichael.Christensen@Sun.COM * Check the MD for a 'virtual-device-port' node whose 'vldc-svc-name' is
31211833SMichael.Christensen@Sun.COM * 'hvctl'.
31311833SMichael.Christensen@Sun.COM */
31411833SMichael.Christensen@Sun.COM static int
v12n_check_hv_access(md_t * mdp)31511833SMichael.Christensen@Sun.COM v12n_check_hv_access(md_t *mdp)
31611833SMichael.Christensen@Sun.COM {
31711833SMichael.Christensen@Sun.COM static char *hvctl_str[] = {
31811833SMichael.Christensen@Sun.COM "hvctl",
31911833SMichael.Christensen@Sun.COM NULL
32011833SMichael.Christensen@Sun.COM };
32111833SMichael.Christensen@Sun.COM
32211833SMichael.Christensen@Sun.COM return (v12n_scan_md_nodes(mdp, "virtual-device-port", "vldc-svc-name",
32311833SMichael.Christensen@Sun.COM hvctl_str));
32411833SMichael.Christensen@Sun.COM }
32511833SMichael.Christensen@Sun.COM
32611833SMichael.Christensen@Sun.COM /*
32711833SMichael.Christensen@Sun.COM * Check if MD has a virtual device service (vcc, vsw, vds), returns 1 if true.
32811833SMichael.Christensen@Sun.COM * Need to check all the MD 'virtual-device' nodes for a 'device-type' property
32911833SMichael.Christensen@Sun.COM * of 'vcc', 'vsw' or 'vds'.
33011833SMichael.Christensen@Sun.COM */
33111833SMichael.Christensen@Sun.COM static int
v12n_check_virtual_service(md_t * mdp)33211833SMichael.Christensen@Sun.COM v12n_check_virtual_service(md_t *mdp)
33311833SMichael.Christensen@Sun.COM {
33411833SMichael.Christensen@Sun.COM static char *vdevs[] = {
33511833SMichael.Christensen@Sun.COM "vcc",
33611833SMichael.Christensen@Sun.COM "vsw",
33711833SMichael.Christensen@Sun.COM "vds",
33811833SMichael.Christensen@Sun.COM NULL
33911833SMichael.Christensen@Sun.COM };
34011833SMichael.Christensen@Sun.COM
34111833SMichael.Christensen@Sun.COM return (v12n_scan_md_nodes(mdp, "virtual-device", "device-type",
34211833SMichael.Christensen@Sun.COM vdevs));
34311833SMichael.Christensen@Sun.COM }
34411833SMichael.Christensen@Sun.COM
34511833SMichael.Christensen@Sun.COM /*
34611833SMichael.Christensen@Sun.COM * Check if MD has an physical I/O device node, returns 1 if true.
34711833SMichael.Christensen@Sun.COM */
34811833SMichael.Christensen@Sun.COM static int
v12n_check_io_service(md_t * mdp)34911833SMichael.Christensen@Sun.COM v12n_check_io_service(md_t *mdp)
35011833SMichael.Christensen@Sun.COM {
35111833SMichael.Christensen@Sun.COM return (v12n_scan_md_nodes(mdp, "iodevice", NULL, NULL));
35211833SMichael.Christensen@Sun.COM }
35311833SMichael.Christensen@Sun.COM
35411833SMichael.Christensen@Sun.COM /*
35511833SMichael.Christensen@Sun.COM * Check if a MD node is root PCI device, returns 1 if true.
35611833SMichael.Christensen@Sun.COM * Need to check all the MD 'iodevice' nodes for a 'device-type' property
35711833SMichael.Christensen@Sun.COM * of 'pciex'.
35811833SMichael.Christensen@Sun.COM */
35911833SMichael.Christensen@Sun.COM static int
v12n_check_root(md_t * mdp)36011833SMichael.Christensen@Sun.COM v12n_check_root(md_t *mdp)
36111833SMichael.Christensen@Sun.COM {
36211833SMichael.Christensen@Sun.COM static char *pciex[] = {
36311833SMichael.Christensen@Sun.COM "pciex",
36411833SMichael.Christensen@Sun.COM NULL
36511833SMichael.Christensen@Sun.COM };
36611833SMichael.Christensen@Sun.COM
36711833SMichael.Christensen@Sun.COM return (v12n_scan_md_nodes(mdp, "iodevice", "device-type", pciex));
36811833SMichael.Christensen@Sun.COM }
36911833SMichael.Christensen@Sun.COM
37011833SMichael.Christensen@Sun.COM /*
37111833SMichael.Christensen@Sun.COM * Get the domain roles for the domain.
37211833SMichael.Christensen@Sun.COM */
37311833SMichael.Christensen@Sun.COM int
v12n_domain_roles()37411833SMichael.Christensen@Sun.COM v12n_domain_roles()
37511833SMichael.Christensen@Sun.COM {
37611833SMichael.Christensen@Sun.COM md_t *mdp;
37711833SMichael.Christensen@Sun.COM int roles = 0;
37811833SMichael.Christensen@Sun.COM
37911833SMichael.Christensen@Sun.COM if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
38011833SMichael.Christensen@Sun.COM errno = ENOTSUP;
38111833SMichael.Christensen@Sun.COM return (-1);
38211833SMichael.Christensen@Sun.COM }
38311833SMichael.Christensen@Sun.COM
38411833SMichael.Christensen@Sun.COM if ((mdp = v12n_md_init()) == NULL) {
38511833SMichael.Christensen@Sun.COM errno = EACCES;
38611833SMichael.Christensen@Sun.COM return (-1);
38711833SMichael.Christensen@Sun.COM }
38811833SMichael.Christensen@Sun.COM
38911833SMichael.Christensen@Sun.COM if (v12n_check_hv_access(mdp))
39011833SMichael.Christensen@Sun.COM roles |= V12N_ROLE_CONTROL;
39111833SMichael.Christensen@Sun.COM
39211833SMichael.Christensen@Sun.COM if (v12n_check_virtual_service(mdp))
39311833SMichael.Christensen@Sun.COM roles |= V12N_ROLE_SERVICE;
39411833SMichael.Christensen@Sun.COM
39511833SMichael.Christensen@Sun.COM if (v12n_check_io_service(mdp))
39611833SMichael.Christensen@Sun.COM roles |= V12N_ROLE_IO;
39711833SMichael.Christensen@Sun.COM
39811833SMichael.Christensen@Sun.COM if (v12n_check_root(mdp))
39911833SMichael.Christensen@Sun.COM roles |= V12N_ROLE_ROOT;
40011833SMichael.Christensen@Sun.COM
40111833SMichael.Christensen@Sun.COM v12n_md_fini(mdp);
40211833SMichael.Christensen@Sun.COM
40311833SMichael.Christensen@Sun.COM return (roles);
40411833SMichael.Christensen@Sun.COM }
40511833SMichael.Christensen@Sun.COM
40611833SMichael.Christensen@Sun.COM /*
40711833SMichael.Christensen@Sun.COM * Get domain name from MD's virtual domain service node, returns 1 on success.
40811833SMichael.Christensen@Sun.COM * The domain name is a string property 'vlds-domain-name' under the
40911833SMichael.Christensen@Sun.COM * 'virtual-device' device node whose name is 'virtual-domain-service'.
41011833SMichael.Christensen@Sun.COM */
41111833SMichael.Christensen@Sun.COM static int
v12n_get_md_domain_name(md_t * mdp,char ** vds_dnamep)41211833SMichael.Christensen@Sun.COM v12n_get_md_domain_name(md_t *mdp, char **vds_dnamep)
41311833SMichael.Christensen@Sun.COM {
41411833SMichael.Christensen@Sun.COM mde_cookie_t *vdev_nodes, rootnode;
41511833SMichael.Christensen@Sun.COM int list_size, nvdevs, num_nodes, i, rv;
41611833SMichael.Christensen@Sun.COM char *vldc_name;
41711833SMichael.Christensen@Sun.COM
41811833SMichael.Christensen@Sun.COM num_nodes = md_node_count(mdp);
41911833SMichael.Christensen@Sun.COM list_size = num_nodes * sizeof (mde_cookie_t);
42011833SMichael.Christensen@Sun.COM vdev_nodes = malloc(list_size);
42111833SMichael.Christensen@Sun.COM if (vdev_nodes == NULL) {
42211833SMichael.Christensen@Sun.COM return (0);
42311833SMichael.Christensen@Sun.COM }
42411833SMichael.Christensen@Sun.COM
42511833SMichael.Christensen@Sun.COM rootnode = md_root_node(mdp);
42611833SMichael.Christensen@Sun.COM
42711833SMichael.Christensen@Sun.COM nvdevs = md_scan_dag(mdp, rootnode, md_find_name(mdp, "virtual-device"),
42811833SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), vdev_nodes);
42911833SMichael.Christensen@Sun.COM
43011833SMichael.Christensen@Sun.COM rv = 0;
43111833SMichael.Christensen@Sun.COM for (i = 0; i < nvdevs; i++) {
43211833SMichael.Christensen@Sun.COM if (md_get_prop_str(mdp, vdev_nodes[i], "name", &vldc_name))
43311833SMichael.Christensen@Sun.COM continue;
43411833SMichael.Christensen@Sun.COM if (strcmp(vldc_name, "virtual-domain-service") == 0) {
43511833SMichael.Christensen@Sun.COM rv = (md_get_prop_str(mdp, vdev_nodes[i],
43611833SMichael.Christensen@Sun.COM "vlds-domain-name", vds_dnamep) == 0);
43711833SMichael.Christensen@Sun.COM break;
43811833SMichael.Christensen@Sun.COM }
43911833SMichael.Christensen@Sun.COM }
44011833SMichael.Christensen@Sun.COM free(vdev_nodes);
44111833SMichael.Christensen@Sun.COM return (rv);
44211833SMichael.Christensen@Sun.COM }
44311833SMichael.Christensen@Sun.COM
44411833SMichael.Christensen@Sun.COM /*
44511833SMichael.Christensen@Sun.COM * String copyout utility.
44611833SMichael.Christensen@Sun.COM */
44711833SMichael.Christensen@Sun.COM static size_t
v12n_string_copyout(char * sout,char * sfrom,size_t count)44811833SMichael.Christensen@Sun.COM v12n_string_copyout(char *sout, char *sfrom, size_t count)
44911833SMichael.Christensen@Sun.COM {
45011833SMichael.Christensen@Sun.COM size_t ret = strlen(sfrom) + 1;
45111833SMichael.Christensen@Sun.COM
45211833SMichael.Christensen@Sun.COM if (sout != NULL && count > 0) {
45311833SMichael.Christensen@Sun.COM count = MIN(ret, count);
45411833SMichael.Christensen@Sun.COM (void) memcpy(sout, sfrom, count);
45511833SMichael.Christensen@Sun.COM }
45611833SMichael.Christensen@Sun.COM return (ret);
45711833SMichael.Christensen@Sun.COM }
45811833SMichael.Christensen@Sun.COM
45911833SMichael.Christensen@Sun.COM /*
46011833SMichael.Christensen@Sun.COM * Get the domain name of this domain.
46111833SMichael.Christensen@Sun.COM */
46211833SMichael.Christensen@Sun.COM size_t
v12n_domain_name(char * buf,size_t count)46311833SMichael.Christensen@Sun.COM v12n_domain_name(char *buf, size_t count)
46411833SMichael.Christensen@Sun.COM {
46511833SMichael.Christensen@Sun.COM md_t *mdp = NULL;
46611833SMichael.Christensen@Sun.COM char *ldmname;
46711833SMichael.Christensen@Sun.COM int rv = -1;
46811833SMichael.Christensen@Sun.COM
46911833SMichael.Christensen@Sun.COM if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
47011833SMichael.Christensen@Sun.COM errno = ENOTSUP;
47111833SMichael.Christensen@Sun.COM } else if ((mdp = v12n_md_init()) == NULL) {
47211833SMichael.Christensen@Sun.COM errno = EACCES;
47311833SMichael.Christensen@Sun.COM } else if (!v12n_get_md_domain_name(mdp, &ldmname)) {
47411833SMichael.Christensen@Sun.COM errno = ESRCH;
47511833SMichael.Christensen@Sun.COM } else {
47611833SMichael.Christensen@Sun.COM rv = v12n_string_copyout(buf, ldmname, count);
47711833SMichael.Christensen@Sun.COM }
47811833SMichael.Christensen@Sun.COM
47911833SMichael.Christensen@Sun.COM v12n_md_fini(mdp);
48011833SMichael.Christensen@Sun.COM return (rv);
48111833SMichael.Christensen@Sun.COM }
48211833SMichael.Christensen@Sun.COM
48311833SMichael.Christensen@Sun.COM /*
48411833SMichael.Christensen@Sun.COM * Get UUID string from MD, returns 1 on success.
48511833SMichael.Christensen@Sun.COM * The UUID is a string property 'uuid' under the 'platform' node of the MD.
48611833SMichael.Christensen@Sun.COM */
48711833SMichael.Christensen@Sun.COM static int
v12n_get_md_uuid_str(md_t * mdp,char ** uuid_strp)48811833SMichael.Christensen@Sun.COM v12n_get_md_uuid_str(md_t *mdp, char **uuid_strp)
48911833SMichael.Christensen@Sun.COM {
49011833SMichael.Christensen@Sun.COM mde_cookie_t *plat_nodes, rootnode;
49111833SMichael.Christensen@Sun.COM int list_size, npnodes, num_nodes, rv;
49211833SMichael.Christensen@Sun.COM
49311833SMichael.Christensen@Sun.COM num_nodes = md_node_count(mdp);
49411833SMichael.Christensen@Sun.COM list_size = num_nodes * sizeof (mde_cookie_t);
49511833SMichael.Christensen@Sun.COM plat_nodes = malloc(list_size);
49611833SMichael.Christensen@Sun.COM if (plat_nodes == NULL) {
49711833SMichael.Christensen@Sun.COM return (0);
49811833SMichael.Christensen@Sun.COM }
49911833SMichael.Christensen@Sun.COM
50011833SMichael.Christensen@Sun.COM rootnode = md_root_node(mdp);
50111833SMichael.Christensen@Sun.COM
50211833SMichael.Christensen@Sun.COM npnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"),
50311833SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), plat_nodes);
50411833SMichael.Christensen@Sun.COM
50511833SMichael.Christensen@Sun.COM if (npnodes >= 1)
50611833SMichael.Christensen@Sun.COM rv = !md_get_prop_str(mdp, plat_nodes[0], "uuid", uuid_strp);
50711833SMichael.Christensen@Sun.COM else
50811833SMichael.Christensen@Sun.COM rv = 0;
50911833SMichael.Christensen@Sun.COM
51011833SMichael.Christensen@Sun.COM free(plat_nodes);
51111833SMichael.Christensen@Sun.COM return (rv);
51211833SMichael.Christensen@Sun.COM }
51311833SMichael.Christensen@Sun.COM
51411833SMichael.Christensen@Sun.COM /*
51511833SMichael.Christensen@Sun.COM * Get the domain UUID.
51611833SMichael.Christensen@Sun.COM */
51711833SMichael.Christensen@Sun.COM int
v12n_domain_uuid(uuid_t uuid)51811833SMichael.Christensen@Sun.COM v12n_domain_uuid(uuid_t uuid)
51911833SMichael.Christensen@Sun.COM {
52011833SMichael.Christensen@Sun.COM md_t *mdp = NULL;
52111833SMichael.Christensen@Sun.COM char *uuid_str;
52211833SMichael.Christensen@Sun.COM int rv = -1;
52311833SMichael.Christensen@Sun.COM
52411833SMichael.Christensen@Sun.COM if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
52511833SMichael.Christensen@Sun.COM errno = ENOTSUP;
52611833SMichael.Christensen@Sun.COM } else if ((mdp = v12n_md_init()) == NULL) {
52711833SMichael.Christensen@Sun.COM errno = EACCES;
52811833SMichael.Christensen@Sun.COM } else if (!v12n_get_md_uuid_str(mdp, &uuid_str)) {
52911833SMichael.Christensen@Sun.COM errno = ESRCH;
53011833SMichael.Christensen@Sun.COM } else {
53111833SMichael.Christensen@Sun.COM rv = uuid_parse(uuid_str, uuid);
53211833SMichael.Christensen@Sun.COM }
53311833SMichael.Christensen@Sun.COM
53411833SMichael.Christensen@Sun.COM v12n_md_fini(mdp);
53511833SMichael.Christensen@Sun.COM
53611833SMichael.Christensen@Sun.COM return (rv);
53711833SMichael.Christensen@Sun.COM }
53811833SMichael.Christensen@Sun.COM
53911833SMichael.Christensen@Sun.COM /*
54011833SMichael.Christensen@Sun.COM * Send 'agent-sytem' request message.
54111833SMichael.Christensen@Sun.COM */
54211833SMichael.Christensen@Sun.COM static int
v12n_ldma_send_request()54311833SMichael.Christensen@Sun.COM v12n_ldma_send_request()
54411833SMichael.Christensen@Sun.COM {
54511833SMichael.Christensen@Sun.COM ldma_message_header_t ldmamsg;
54611833SMichael.Christensen@Sun.COM
54711833SMichael.Christensen@Sun.COM if (v12n_ds_send_msg == NULL || v12n_ldma_ctrl_hdl == DS_INVALID_HDL)
54811833SMichael.Christensen@Sun.COM return (ENOENT);
54911833SMichael.Christensen@Sun.COM
55011833SMichael.Christensen@Sun.COM ldmamsg.msg_num = 0;
55111833SMichael.Christensen@Sun.COM ldmamsg.msg_type = v12n_ldma_msgtype;
55211833SMichael.Christensen@Sun.COM ldmamsg.msg_info = 0;
55311833SMichael.Christensen@Sun.COM return (v12n_ds_send_msg(v12n_ldma_ctrl_hdl, (char *)&ldmamsg,
55411833SMichael.Christensen@Sun.COM sizeof (ldmamsg)));
55511833SMichael.Christensen@Sun.COM }
55611833SMichael.Christensen@Sun.COM
55711833SMichael.Christensen@Sun.COM /*
55811833SMichael.Christensen@Sun.COM * 'agent-system' registration handler.
55911833SMichael.Christensen@Sun.COM * If we get a registration from the control domain (domain 0), then send
56011833SMichael.Christensen@Sun.COM * the requested message. Otherwise, ignore the registration.
56111833SMichael.Christensen@Sun.COM */
56211833SMichael.Christensen@Sun.COM /* ARGSUSED */
56311833SMichael.Christensen@Sun.COM static void
v12n_ldma_register_handler(ds_hdl_t hdl,ds_cb_arg_t arg,ds_ver_t * ver,ds_domain_hdl_t dhdl)56411833SMichael.Christensen@Sun.COM v12n_ldma_register_handler(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver,
56511833SMichael.Christensen@Sun.COM ds_domain_hdl_t dhdl)
56611833SMichael.Christensen@Sun.COM {
56711833SMichael.Christensen@Sun.COM
56811833SMichael.Christensen@Sun.COM /* got registration from control domain */
56911833SMichael.Christensen@Sun.COM if (dhdl == 0) {
57011833SMichael.Christensen@Sun.COM (void) mutex_lock(&v12n_ldma_cv_lock);
57111833SMichael.Christensen@Sun.COM if (v12n_ldma_cv_state == V12N_LDMA_REGWAITING) {
57211833SMichael.Christensen@Sun.COM v12n_ldma_ctrl_hdl = hdl;
57311833SMichael.Christensen@Sun.COM v12n_ldma_cv_state = V12N_LDMA_REGRECEIVED;
57411833SMichael.Christensen@Sun.COM (void) cond_signal(&v12n_ldma_cv);
57511833SMichael.Christensen@Sun.COM }
57611833SMichael.Christensen@Sun.COM (void) mutex_unlock(&v12n_ldma_cv_lock);
57711833SMichael.Christensen@Sun.COM }
57811833SMichael.Christensen@Sun.COM }
57911833SMichael.Christensen@Sun.COM
58011833SMichael.Christensen@Sun.COM /*
58111833SMichael.Christensen@Sun.COM * 'agent-system' data handler.
58211833SMichael.Christensen@Sun.COM */
58311833SMichael.Christensen@Sun.COM /* ARGSUSED */
58411833SMichael.Christensen@Sun.COM static void
v12n_ldma_data_handler(ds_hdl_t hdl,ds_cb_arg_t arg,void * buf,size_t buflen)58511833SMichael.Christensen@Sun.COM v12n_ldma_data_handler(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf,
58611833SMichael.Christensen@Sun.COM size_t buflen)
58711833SMichael.Christensen@Sun.COM {
58811833SMichael.Christensen@Sun.COM char *data;
58911833SMichael.Christensen@Sun.COM ldma_message_header_t *ldmp;
59011833SMichael.Christensen@Sun.COM int n;
59111833SMichael.Christensen@Sun.COM int cv_state = V12N_LDMA_MSGERROR;
59211833SMichael.Christensen@Sun.COM
59311833SMichael.Christensen@Sun.COM /*
59411833SMichael.Christensen@Sun.COM * Ignore any message not from the control domain.
59511833SMichael.Christensen@Sun.COM */
59611833SMichael.Christensen@Sun.COM if (v12n_ldma_ctrl_hdl != hdl)
59711833SMichael.Christensen@Sun.COM return;
59811833SMichael.Christensen@Sun.COM
59911833SMichael.Christensen@Sun.COM /*
60011833SMichael.Christensen@Sun.COM * Ignore any unexpected message.
60111833SMichael.Christensen@Sun.COM */
60211833SMichael.Christensen@Sun.COM if (buflen < LDMA_MESSAGE_HEADER_SIZE)
60311833SMichael.Christensen@Sun.COM return;
60411833SMichael.Christensen@Sun.COM
60511833SMichael.Christensen@Sun.COM /*
60611833SMichael.Christensen@Sun.COM * Ignore message with unexpected msgnum.
60711833SMichael.Christensen@Sun.COM */
60811833SMichael.Christensen@Sun.COM ldmp = (ldma_message_header_t *)buf;
60911833SMichael.Christensen@Sun.COM if (ldmp->msg_num != 0)
61011833SMichael.Christensen@Sun.COM return;
61111833SMichael.Christensen@Sun.COM
61211833SMichael.Christensen@Sun.COM switch (ldmp->msg_type) {
61311833SMichael.Christensen@Sun.COM
61411833SMichael.Christensen@Sun.COM case LDMA_MSG_RESULT:
61511833SMichael.Christensen@Sun.COM if (ldmp->msg_info == 0 ||
61611833SMichael.Christensen@Sun.COM ldmp->msg_info > LDMA_MESSAGE_DLEN(buflen)) {
61711833SMichael.Christensen@Sun.COM cv_state = V12N_LDMA_MSGERROR;
61811833SMichael.Christensen@Sun.COM break;
61911833SMichael.Christensen@Sun.COM }
62011833SMichael.Christensen@Sun.COM data = LDMA_HDR2DATA(buf);
62111833SMichael.Christensen@Sun.COM
62211833SMichael.Christensen@Sun.COM /* ensure that data ends with a '\0' */
62311833SMichael.Christensen@Sun.COM data[ldmp->msg_info - 1] = '\0';
62411833SMichael.Christensen@Sun.COM switch (v12n_ldma_msgtype) {
62511833SMichael.Christensen@Sun.COM
62611833SMichael.Christensen@Sun.COM case LDMA_MSGSYS_GET_SYSINFO:
62711833SMichael.Christensen@Sun.COM /*
62811833SMichael.Christensen@Sun.COM * Control domain nodename is second string in the
62911833SMichael.Christensen@Sun.COM * message. Make sure there is enough data in the msg
63011833SMichael.Christensen@Sun.COM * to have a second string.
63111833SMichael.Christensen@Sun.COM */
63211833SMichael.Christensen@Sun.COM n = strlen(data);
63311833SMichael.Christensen@Sun.COM if (LDMA_MESSAGE_DLEN(buflen) <= n + 3) {
63411833SMichael.Christensen@Sun.COM cv_state = V12N_LDMA_MSGERROR;
63511833SMichael.Christensen@Sun.COM break;
63611833SMichael.Christensen@Sun.COM }
63711833SMichael.Christensen@Sun.COM data += n + 1;
63811833SMichael.Christensen@Sun.COM if ((v12n_ldma_msgstr = strdup(data)) == NULL)
63911833SMichael.Christensen@Sun.COM cv_state = V12N_LDMA_MSGERROR;
64011833SMichael.Christensen@Sun.COM else
64111833SMichael.Christensen@Sun.COM cv_state = V12N_LDMA_MSGRECEIVED;
64211833SMichael.Christensen@Sun.COM break;
64311833SMichael.Christensen@Sun.COM
64411833SMichael.Christensen@Sun.COM case LDMA_MSGSYS_GET_CHASSISNO:
64511833SMichael.Christensen@Sun.COM if ((v12n_ldma_msgstr = strdup(data)) == NULL)
64611833SMichael.Christensen@Sun.COM cv_state = V12N_LDMA_MSGERROR;
64711833SMichael.Christensen@Sun.COM else
64811833SMichael.Christensen@Sun.COM cv_state = V12N_LDMA_MSGRECEIVED;
64911833SMichael.Christensen@Sun.COM break;
65011833SMichael.Christensen@Sun.COM
65111833SMichael.Christensen@Sun.COM default:
65211833SMichael.Christensen@Sun.COM /* v12n_ldma_msgtype must be valid */
65311833SMichael.Christensen@Sun.COM ASSERT(0);
65411833SMichael.Christensen@Sun.COM }
65511833SMichael.Christensen@Sun.COM break;
65611833SMichael.Christensen@Sun.COM
65711833SMichael.Christensen@Sun.COM case LDMA_MSG_ERROR:
65811833SMichael.Christensen@Sun.COM cv_state = V12N_LDMA_MSGERROR;
65911833SMichael.Christensen@Sun.COM break;
66011833SMichael.Christensen@Sun.COM
66111833SMichael.Christensen@Sun.COM default:
66211833SMichael.Christensen@Sun.COM /* unexpected message, ignored */
66311833SMichael.Christensen@Sun.COM return;
66411833SMichael.Christensen@Sun.COM }
66511833SMichael.Christensen@Sun.COM
66611833SMichael.Christensen@Sun.COM (void) mutex_lock(&v12n_ldma_cv_lock);
66711833SMichael.Christensen@Sun.COM v12n_ldma_cv_state = cv_state;
66811833SMichael.Christensen@Sun.COM (void) cond_signal(&v12n_ldma_cv);
66911833SMichael.Christensen@Sun.COM (void) mutex_unlock(&v12n_ldma_cv_lock);
67011833SMichael.Christensen@Sun.COM }
67111833SMichael.Christensen@Sun.COM
67211833SMichael.Christensen@Sun.COM
67311833SMichael.Christensen@Sun.COM /*
67411833SMichael.Christensen@Sun.COM * libds doesn't exist on non-sun4v, dynamically load it and get the
67511833SMichael.Christensen@Sun.COM * function pointers to the needed lib functions.
67611833SMichael.Christensen@Sun.COM */
67711833SMichael.Christensen@Sun.COM static int
v12n_libds_init(void)67811833SMichael.Christensen@Sun.COM v12n_libds_init(void)
67911833SMichael.Christensen@Sun.COM {
68011833SMichael.Christensen@Sun.COM if (v12n_ds_dlhdl != NULL) {
68111833SMichael.Christensen@Sun.COM if (v12n_ds_clnt_reg == NULL || v12n_ds_send_msg == NULL ||
68211833SMichael.Christensen@Sun.COM v12n_ds_unreg_svc == NULL)
68311833SMichael.Christensen@Sun.COM return (ENOENT);
68411833SMichael.Christensen@Sun.COM return (0);
68511833SMichael.Christensen@Sun.COM }
68611833SMichael.Christensen@Sun.COM
68711833SMichael.Christensen@Sun.COM if ((v12n_ds_dlhdl = dlopen("libds.so.1",
68811833SMichael.Christensen@Sun.COM RTLD_NOW | RTLD_GLOBAL)) == NULL)
68911833SMichael.Christensen@Sun.COM return (ENOENT);
69011833SMichael.Christensen@Sun.COM
69111833SMichael.Christensen@Sun.COM if ((v12n_ds_clnt_reg = (int (*)(ds_capability_t *, ds_ops_t *))
69211833SMichael.Christensen@Sun.COM dlsym(v12n_ds_dlhdl, "ds_clnt_reg")) == NULL)
69311833SMichael.Christensen@Sun.COM return (ENOENT);
69411833SMichael.Christensen@Sun.COM
69511833SMichael.Christensen@Sun.COM if ((v12n_ds_send_msg = (int (*)(ds_hdl_t, void *, size_t))
69611833SMichael.Christensen@Sun.COM dlsym(v12n_ds_dlhdl, "ds_send_msg")) == NULL)
69711833SMichael.Christensen@Sun.COM return (ENOENT);
69811833SMichael.Christensen@Sun.COM
69911833SMichael.Christensen@Sun.COM if ((v12n_ds_unreg_svc = (int (*)(char *, boolean_t))
70011833SMichael.Christensen@Sun.COM dlsym(v12n_ds_dlhdl, "ds_unreg_svc")) == NULL)
70111833SMichael.Christensen@Sun.COM return (ENOENT);
70211833SMichael.Christensen@Sun.COM
70311833SMichael.Christensen@Sun.COM return (0);
70411833SMichael.Christensen@Sun.COM }
70511833SMichael.Christensen@Sun.COM
70611833SMichael.Christensen@Sun.COM /*
70711833SMichael.Christensen@Sun.COM * Initiate and wait for an ldmad 'agent-system' domain service.
70811833SMichael.Christensen@Sun.COM * Dynamically load libds, register the client 'agent-system' service
70911833SMichael.Christensen@Sun.COM * and wait for a specified amount of time for the 'agent-system'
71011833SMichael.Christensen@Sun.COM * service on the control domain to respond to the request.
71111833SMichael.Christensen@Sun.COM */
71211833SMichael.Christensen@Sun.COM static int
v12n_get_ldma_system_msg(int msgtype,char ** strp)71311833SMichael.Christensen@Sun.COM v12n_get_ldma_system_msg(int msgtype, char **strp)
71411833SMichael.Christensen@Sun.COM {
71511833SMichael.Christensen@Sun.COM int tout;
71611833SMichael.Christensen@Sun.COM int err = 0;
71711833SMichael.Christensen@Sun.COM timestruc_t timeout;
71811833SMichael.Christensen@Sun.COM
71911833SMichael.Christensen@Sun.COM /*
72011833SMichael.Christensen@Sun.COM * Ensure that there's only one thread trying to do a
72111833SMichael.Christensen@Sun.COM * 'agent-system' client registration/message at a time.
72211833SMichael.Christensen@Sun.COM */
72311833SMichael.Christensen@Sun.COM (void) mutex_lock(&v12n_ldma_lock);
724*12913SMichael.Christensen@Sun.COM if ((err = v12n_libds_init()) != 0) {
725*12913SMichael.Christensen@Sun.COM (void) mutex_unlock(&v12n_ldma_lock);
726*12913SMichael.Christensen@Sun.COM return (err);
727*12913SMichael.Christensen@Sun.COM }
72811833SMichael.Christensen@Sun.COM
72911833SMichael.Christensen@Sun.COM v12n_ldma_msgtype = msgtype;
73011833SMichael.Christensen@Sun.COM v12n_ldma_msgstr = NULL;
73111833SMichael.Christensen@Sun.COM
73211833SMichael.Christensen@Sun.COM /* initialize v12n_ldma_cv_state variable before registering service */
73311833SMichael.Christensen@Sun.COM (void) mutex_lock(&v12n_ldma_cv_lock);
73411833SMichael.Christensen@Sun.COM v12n_ldma_cv_state = V12N_LDMA_REGWAITING;
73511833SMichael.Christensen@Sun.COM (void) mutex_unlock(&v12n_ldma_cv_lock);
73611833SMichael.Christensen@Sun.COM
73711833SMichael.Christensen@Sun.COM /*
73811833SMichael.Christensen@Sun.COM * Other instances may be trying to load the "agent-system" service.
73911833SMichael.Christensen@Sun.COM * If a collision happens (EBUSY error), wait and try again.
74011833SMichael.Christensen@Sun.COM */
74111833SMichael.Christensen@Sun.COM for (tout = 0; tout < v12n_ldma_timeout; tout += v12n_ldma_sleeptime) {
74211833SMichael.Christensen@Sun.COM if ((err = v12n_ds_clnt_reg(&v12n_ldma_cap,
74311833SMichael.Christensen@Sun.COM &v12n_ldma_ops)) == 0)
74411833SMichael.Christensen@Sun.COM break;
74511833SMichael.Christensen@Sun.COM if (err != EALREADY) {
74611833SMichael.Christensen@Sun.COM goto done;
74711833SMichael.Christensen@Sun.COM }
74811833SMichael.Christensen@Sun.COM (void) sleep(v12n_ldma_sleeptime);
74911833SMichael.Christensen@Sun.COM }
75011833SMichael.Christensen@Sun.COM
75111833SMichael.Christensen@Sun.COM if (tout >= v12n_ldma_timeout) {
75211833SMichael.Christensen@Sun.COM err = EBUSY;
75311833SMichael.Christensen@Sun.COM goto done;
75411833SMichael.Christensen@Sun.COM }
75511833SMichael.Christensen@Sun.COM
75611833SMichael.Christensen@Sun.COM /*
75711833SMichael.Christensen@Sun.COM * Wait for control domain registration.
75811833SMichael.Christensen@Sun.COM */
75911833SMichael.Christensen@Sun.COM timeout.tv_sec = v12n_ldma_timeout;
76011833SMichael.Christensen@Sun.COM timeout.tv_nsec = 0;
76111833SMichael.Christensen@Sun.COM
76211833SMichael.Christensen@Sun.COM (void) mutex_lock(&v12n_ldma_cv_lock);
76311833SMichael.Christensen@Sun.COM while (v12n_ldma_cv_state == V12N_LDMA_REGWAITING) {
76411833SMichael.Christensen@Sun.COM if ((err = cond_reltimedwait(&v12n_ldma_cv,
76511833SMichael.Christensen@Sun.COM &v12n_ldma_cv_lock, &timeout)) != EINTR)
76611833SMichael.Christensen@Sun.COM break;
76711833SMichael.Christensen@Sun.COM }
76811833SMichael.Christensen@Sun.COM
76911833SMichael.Christensen@Sun.COM /*
77011833SMichael.Christensen@Sun.COM * Check for timeout or an error.
77111833SMichael.Christensen@Sun.COM */
77211833SMichael.Christensen@Sun.COM if (v12n_ldma_cv_state != V12N_LDMA_REGRECEIVED) {
77311833SMichael.Christensen@Sun.COM if (err == 0)
77411833SMichael.Christensen@Sun.COM err = EPROTO;
77511833SMichael.Christensen@Sun.COM (void) mutex_unlock(&v12n_ldma_cv_lock);
77611833SMichael.Christensen@Sun.COM goto done;
77711833SMichael.Christensen@Sun.COM }
77811833SMichael.Christensen@Sun.COM
77911833SMichael.Christensen@Sun.COM /*
78011833SMichael.Christensen@Sun.COM * Received a registration request, send the request message.
78111833SMichael.Christensen@Sun.COM */
78211833SMichael.Christensen@Sun.COM v12n_ldma_cv_state = V12N_LDMA_MSGWAITING;
78311833SMichael.Christensen@Sun.COM if ((err = v12n_ldma_send_request()) != 0) {
78411833SMichael.Christensen@Sun.COM (void) mutex_unlock(&v12n_ldma_cv_lock);
78511833SMichael.Christensen@Sun.COM goto done;
78611833SMichael.Christensen@Sun.COM }
78711833SMichael.Christensen@Sun.COM
78811833SMichael.Christensen@Sun.COM while (v12n_ldma_cv_state == V12N_LDMA_MSGWAITING) {
78911833SMichael.Christensen@Sun.COM if ((err = cond_reltimedwait(&v12n_ldma_cv,
79011833SMichael.Christensen@Sun.COM &v12n_ldma_cv_lock, &timeout)) != EINTR)
79111833SMichael.Christensen@Sun.COM break;
79211833SMichael.Christensen@Sun.COM }
79311833SMichael.Christensen@Sun.COM
79411833SMichael.Christensen@Sun.COM if (v12n_ldma_cv_state != V12N_LDMA_MSGRECEIVED) {
79511833SMichael.Christensen@Sun.COM if (err == 0)
79611833SMichael.Christensen@Sun.COM err = EPROTO;
79711833SMichael.Christensen@Sun.COM (void) mutex_unlock(&v12n_ldma_cv_lock);
79811833SMichael.Christensen@Sun.COM goto done;
79911833SMichael.Christensen@Sun.COM }
80011833SMichael.Christensen@Sun.COM
80111833SMichael.Christensen@Sun.COM v12n_ldma_cv_state = V12N_LDMA_CVINVALID;
80211833SMichael.Christensen@Sun.COM (void) mutex_unlock(&v12n_ldma_cv_lock);
80311833SMichael.Christensen@Sun.COM
80411833SMichael.Christensen@Sun.COM /*
80511833SMichael.Christensen@Sun.COM * If v12n_ldma_msgstr is set, a valid data response was seen.
80611833SMichael.Christensen@Sun.COM */
80711833SMichael.Christensen@Sun.COM if (v12n_ldma_msgstr == NULL)
80811833SMichael.Christensen@Sun.COM err = ENODATA;
80911833SMichael.Christensen@Sun.COM else {
81011833SMichael.Christensen@Sun.COM if (*v12n_ldma_msgstr == '\0' ||
81111833SMichael.Christensen@Sun.COM (*strp = strdup(v12n_ldma_msgstr)) == NULL)
81211833SMichael.Christensen@Sun.COM err = ENODATA;
81311833SMichael.Christensen@Sun.COM free(v12n_ldma_msgstr);
81411833SMichael.Christensen@Sun.COM v12n_ldma_msgstr = NULL;
81511833SMichael.Christensen@Sun.COM }
81611833SMichael.Christensen@Sun.COM
81711833SMichael.Christensen@Sun.COM done:
81811833SMichael.Christensen@Sun.COM v12n_ds_unreg_svc(LDMA_NAME_SYSTEM, B_TRUE);
81911833SMichael.Christensen@Sun.COM v12n_ldma_msgtype = -1;
82011833SMichael.Christensen@Sun.COM v12n_ldma_ctrl_hdl = DS_INVALID_HDL;
82111833SMichael.Christensen@Sun.COM (void) mutex_unlock(&v12n_ldma_lock);
82211833SMichael.Christensen@Sun.COM
82311833SMichael.Christensen@Sun.COM return (err);
82411833SMichael.Christensen@Sun.COM }
82511833SMichael.Christensen@Sun.COM
82611833SMichael.Christensen@Sun.COM /*
82711833SMichael.Christensen@Sun.COM * Get the nodename of the control domain. Returns the equivalent
82811833SMichael.Christensen@Sun.COM * of 'uname -n' on the control domain.
82911833SMichael.Christensen@Sun.COM * This is obtained via the 'agent-system' domain service provided
83011833SMichael.Christensen@Sun.COM * by ldmad.
83111833SMichael.Christensen@Sun.COM */
83211833SMichael.Christensen@Sun.COM size_t
v12n_ctrl_domain(char * buf,size_t count)83311833SMichael.Christensen@Sun.COM v12n_ctrl_domain(char *buf, size_t count)
83411833SMichael.Christensen@Sun.COM {
83511833SMichael.Christensen@Sun.COM char *str;
83611833SMichael.Christensen@Sun.COM int err;
83711833SMichael.Christensen@Sun.COM size_t rv = (size_t)(-1);
83811833SMichael.Christensen@Sun.COM
83911833SMichael.Christensen@Sun.COM if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
84011833SMichael.Christensen@Sun.COM errno = ENOTSUP;
84111833SMichael.Christensen@Sun.COM } else if ((err = v12n_get_ldma_system_msg(LDMA_MSGSYS_GET_SYSINFO,
84211833SMichael.Christensen@Sun.COM &str)) != 0) {
84311833SMichael.Christensen@Sun.COM errno = err;
84411833SMichael.Christensen@Sun.COM } else {
84511833SMichael.Christensen@Sun.COM rv = v12n_string_copyout(buf, str, count);
84611833SMichael.Christensen@Sun.COM }
84711833SMichael.Christensen@Sun.COM return (rv);
84811833SMichael.Christensen@Sun.COM }
84911833SMichael.Christensen@Sun.COM
85011833SMichael.Christensen@Sun.COM /*
85111833SMichael.Christensen@Sun.COM * Get the Chassis serial number from the Control Domain.
85211833SMichael.Christensen@Sun.COM * This is obtained via the 'agent-system' domain service provided
85311833SMichael.Christensen@Sun.COM * by ldmad.
85411833SMichael.Christensen@Sun.COM */
85511833SMichael.Christensen@Sun.COM size_t
v12n_chassis_serialno(char * buf,size_t count)85611833SMichael.Christensen@Sun.COM v12n_chassis_serialno(char *buf, size_t count)
85711833SMichael.Christensen@Sun.COM {
85811833SMichael.Christensen@Sun.COM char *str;
85911833SMichael.Christensen@Sun.COM int err;
86011833SMichael.Christensen@Sun.COM size_t rv = (size_t)(-1);
86111833SMichael.Christensen@Sun.COM
86211833SMichael.Christensen@Sun.COM if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
86311833SMichael.Christensen@Sun.COM errno = ENOTSUP;
86411833SMichael.Christensen@Sun.COM } else if ((err = v12n_get_ldma_system_msg(LDMA_MSGSYS_GET_CHASSISNO,
86511833SMichael.Christensen@Sun.COM &str)) != 0) {
86611833SMichael.Christensen@Sun.COM errno = err;
86711833SMichael.Christensen@Sun.COM } else {
86811833SMichael.Christensen@Sun.COM rv = v12n_string_copyout(buf, str, count);
86911833SMichael.Christensen@Sun.COM }
87011833SMichael.Christensen@Sun.COM return (rv);
87111833SMichael.Christensen@Sun.COM }
872