1*82629e30SMike Christensen /* 2*82629e30SMike Christensen * CDDL HEADER START 3*82629e30SMike Christensen * 4*82629e30SMike Christensen * The contents of this file are subject to the terms of the 5*82629e30SMike Christensen * Common Development and Distribution License (the "License"). 6*82629e30SMike Christensen * You may not use this file except in compliance with the License. 7*82629e30SMike Christensen * 8*82629e30SMike Christensen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*82629e30SMike Christensen * or http://www.opensolaris.org/os/licensing. 10*82629e30SMike Christensen * See the License for the specific language governing permissions 11*82629e30SMike Christensen * and limitations under the License. 12*82629e30SMike Christensen * 13*82629e30SMike Christensen * When distributing Covered Code, include this CDDL HEADER in each 14*82629e30SMike Christensen * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*82629e30SMike Christensen * If applicable, add the following below this CDDL HEADER, with the 16*82629e30SMike Christensen * fields enclosed by brackets "[]" replaced with your own identifying 17*82629e30SMike Christensen * information: Portions Copyright [yyyy] [name of copyright owner] 18*82629e30SMike Christensen * 19*82629e30SMike Christensen * CDDL HEADER END 20*82629e30SMike Christensen */ 21*82629e30SMike Christensen /* 22*82629e30SMike Christensen * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23*82629e30SMike Christensen * Use is subject to license terms. 24*82629e30SMike Christensen */ 25*82629e30SMike Christensen 26*82629e30SMike Christensen #include <dlfcn.h> 27*82629e30SMike Christensen #include <errno.h> 28*82629e30SMike Christensen #include <fcntl.h> 29*82629e30SMike Christensen #include <stdio.h> 30*82629e30SMike Christensen #include <stdlib.h> 31*82629e30SMike Christensen #include <strings.h> 32*82629e30SMike Christensen #include <synch.h> 33*82629e30SMike Christensen #include <thread.h> 34*82629e30SMike Christensen #include <unistd.h> 35*82629e30SMike Christensen #include <utility.h> 36*82629e30SMike Christensen #include <sys/mdesc.h> 37*82629e30SMike Christensen #include <sys/mdesc_impl.h> 38*82629e30SMike Christensen #include <sys/debug.h> 39*82629e30SMike Christensen #include <sys/stat.h> 40*82629e30SMike Christensen #include <sys/types.h> 41*82629e30SMike Christensen #include <sys/utsname.h> 42*82629e30SMike Christensen 43*82629e30SMike Christensen #include "ldma.h" 44*82629e30SMike Christensen #include "libds.h" 45*82629e30SMike Christensen #include "libv12n.h" 46*82629e30SMike Christensen 47*82629e30SMike Christensen /* 48*82629e30SMike Christensen * sun4 support for libv12n. 49*82629e30SMike Christensen * 50*82629e30SMike Christensen * Non-sun4v support is minimal. The v12n_capabilities() function will 51*82629e30SMike Christensen * only return 0 (not supported, not enabled, no implementation). 52*82629e30SMike Christensen * 53*82629e30SMike Christensen * For sun4v the support for v12n_capabilities(), v12n_domain_roles(), 54*82629e30SMike Christensen * v12n_domain_name() and v12n_domain_uuid() are supported by scanning the 55*82629e30SMike Christensen * MD from /dev/mdesc for specific properties. For v12n_ctrl_domain() and 56*82629e30SMike Christensen * v12n_chassis_serialno(), the ldoms agent daemon (ldmad) on the control 57*82629e30SMike Christensen * domain supplies the required information via the "agent-system" domain 58*82629e30SMike Christensen * service. 59*82629e30SMike Christensen */ 60*82629e30SMike Christensen 61*82629e30SMike Christensen /* libds statics */ 62*82629e30SMike Christensen static void *v12n_ds_dlhdl = NULL; 63*82629e30SMike Christensen static int (*v12n_ds_send_msg)(ds_hdl_t, void *, size_t) = NULL; 64*82629e30SMike Christensen static int (*v12n_ds_clnt_reg)(ds_capability_t *, ds_ops_t *); 65*82629e30SMike Christensen static int (*v12n_ds_unreg_svc)(char *, boolean_t); 66*82629e30SMike Christensen 67*82629e30SMike Christensen /* 68*82629e30SMike Christensen * Defines to support the 'agent-system' domain service. 69*82629e30SMike Christensen */ 70*82629e30SMike Christensen 71*82629e30SMike Christensen #define LDMA_SYSTEM_NVERS \ 72*82629e30SMike Christensen (sizeof (v12n_ldma_system_vers) / sizeof (ds_ver_t)) 73*82629e30SMike Christensen static ds_ver_t v12n_ldma_system_vers[] = { { 1, 0} }; 74*82629e30SMike Christensen 75*82629e30SMike Christensen static ds_capability_t v12n_ldma_cap = { 76*82629e30SMike Christensen LDMA_NAME_SYSTEM, /* svc_id */ 77*82629e30SMike Christensen v12n_ldma_system_vers, /* vers */ 78*82629e30SMike Christensen LDMA_SYSTEM_NVERS /* nvers */ 79*82629e30SMike Christensen }; 80*82629e30SMike Christensen 81*82629e30SMike Christensen static void v12n_ldma_register_handler(ds_hdl_t hdl, ds_cb_arg_t arg, 82*82629e30SMike Christensen ds_ver_t *ver, ds_domain_hdl_t dhdl); 83*82629e30SMike Christensen static void v12n_ldma_data_handler(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf, 84*82629e30SMike Christensen size_t buflen); 85*82629e30SMike Christensen 86*82629e30SMike Christensen static ds_ops_t v12n_ldma_ops = { 87*82629e30SMike Christensen v12n_ldma_register_handler, /* ds_reg_cb */ 88*82629e30SMike Christensen NULL, /* ds_unreg_cb */ 89*82629e30SMike Christensen v12n_ldma_data_handler, /* ds_data_cb */ 90*82629e30SMike Christensen NULL /* ds_cb_arg */ 91*82629e30SMike Christensen }; 92*82629e30SMike Christensen 93*82629e30SMike Christensen /* v12n_ldma_cv_state values */ 94*82629e30SMike Christensen #define V12N_LDMA_CVINVALID -1 /* invalid value for cv_state */ 95*82629e30SMike Christensen #define V12N_LDMA_REGWAITING 0 /* waiting for ctrl domain reg */ 96*82629e30SMike Christensen #define V12N_LDMA_REGRECEIVED 1 /* received ctrl domain reg */ 97*82629e30SMike Christensen #define V12N_LDMA_MSGWAITING 2 /* waiting for message response */ 98*82629e30SMike Christensen #define V12N_LDMA_MSGRECEIVED 3 /* received message response */ 99*82629e30SMike Christensen #define V12N_LDMA_MSGERROR 4 /* received a bad message */ 100*82629e30SMike Christensen 101*82629e30SMike Christensen /* 'agent-system' data used in async registration/data message handlers */ 102*82629e30SMike Christensen static ds_hdl_t v12n_ldma_ctrl_hdl = DS_INVALID_HDL; 103*82629e30SMike Christensen static int v12n_ldma_msgtype; 104*82629e30SMike Christensen static char *v12n_ldma_msgstr; 105*82629e30SMike Christensen static mutex_t v12n_ldma_lock = DEFAULTMUTEX; 106*82629e30SMike Christensen static cond_t v12n_ldma_cv = DEFAULTCV; 107*82629e30SMike Christensen static int v12n_ldma_cv_state = V12N_LDMA_CVINVALID; 108*82629e30SMike Christensen static mutex_t v12n_ldma_cv_lock = DEFAULTMUTEX; 109*82629e30SMike Christensen 110*82629e30SMike Christensen /* 'agent-system' timeout values in seconds */ 111*82629e30SMike Christensen static int v12n_ldma_timeout = 15; 112*82629e30SMike Christensen static int v12n_ldma_sleeptime = 1; 113*82629e30SMike Christensen 114*82629e30SMike Christensen 115*82629e30SMike Christensen #define V12N_LDOMS_SUPPORTED (V12N_CAP_SUPPORTED | V12N_CAP_ENABLED | \ 116*82629e30SMike Christensen V12N_CAP_IMPL_LDOMS) 117*82629e30SMike Christensen 118*82629e30SMike Christensen #define MD_DEVICE "/dev/mdesc" 119*82629e30SMike Christensen 120*82629e30SMike Christensen /* 121*82629e30SMike Christensen * libv12n routines to support /dev/mdesc. 122*82629e30SMike Christensen */ 123*82629e30SMike Christensen 124*82629e30SMike Christensen /* 125*82629e30SMike Christensen * Wrapper for MD free: need unused size argument. 126*82629e30SMike Christensen */ 127*82629e30SMike Christensen /* ARGSUSED */ 128*82629e30SMike Christensen static void 129*82629e30SMike Christensen v12n_md_free(void *buf, size_t n) 130*82629e30SMike Christensen { 131*82629e30SMike Christensen free(buf); 132*82629e30SMike Christensen } 133*82629e30SMike Christensen 134*82629e30SMike Christensen /* 135*82629e30SMike Christensen * Wrapper for MD init: read MD and invoke md_init_intern. 136*82629e30SMike Christensen */ 137*82629e30SMike Christensen static md_t * 138*82629e30SMike Christensen v12n_md_init() 139*82629e30SMike Christensen { 140*82629e30SMike Christensen md_t *mdp; 141*82629e30SMike Christensen char *buf = NULL; 142*82629e30SMike Christensen md_header_t mdh; 143*82629e30SMike Christensen int md_size; 144*82629e30SMike Christensen int fd; 145*82629e30SMike Christensen 146*82629e30SMike Christensen /* 147*82629e30SMike Christensen * Open the Machine Description (MD) 148*82629e30SMike Christensen */ 149*82629e30SMike Christensen fd = open(MD_DEVICE, O_RDONLY); 150*82629e30SMike Christensen if (fd == -1) { 151*82629e30SMike Christensen return (NULL); 152*82629e30SMike Christensen } 153*82629e30SMike Christensen 154*82629e30SMike Christensen if (read(fd, &mdh, sizeof (md_header_t)) != sizeof (md_header_t)) 155*82629e30SMike Christensen goto errdone; 156*82629e30SMike Christensen 157*82629e30SMike Christensen md_size = sizeof (md_header_t) + mdh.node_blk_sz + mdh.name_blk_sz + 158*82629e30SMike Christensen mdh.data_blk_sz; 159*82629e30SMike Christensen 160*82629e30SMike Christensen if ((buf = malloc(md_size)) == NULL) 161*82629e30SMike Christensen goto errdone; 162*82629e30SMike Christensen 163*82629e30SMike Christensen (void) memcpy(buf, &mdh, sizeof (md_header_t)); 164*82629e30SMike Christensen if (read(fd, buf + sizeof (md_header_t), 165*82629e30SMike Christensen md_size - sizeof (md_header_t)) != md_size - sizeof (md_header_t)) { 166*82629e30SMike Christensen goto errdone; 167*82629e30SMike Christensen } 168*82629e30SMike Christensen 169*82629e30SMike Christensen mdp = md_init_intern((uint64_t *)((void *)buf), malloc, v12n_md_free); 170*82629e30SMike Christensen 171*82629e30SMike Christensen (void) close(fd); 172*82629e30SMike Christensen 173*82629e30SMike Christensen return (mdp); 174*82629e30SMike Christensen 175*82629e30SMike Christensen errdone: 176*82629e30SMike Christensen (void) close(fd); 177*82629e30SMike Christensen free(buf); 178*82629e30SMike Christensen 179*82629e30SMike Christensen return (NULL); 180*82629e30SMike Christensen } 181*82629e30SMike Christensen 182*82629e30SMike Christensen /* 183*82629e30SMike Christensen * Wrapper for md_fini. Allow NULL md ptr and free MD buffer. 184*82629e30SMike Christensen */ 185*82629e30SMike Christensen static void 186*82629e30SMike Christensen v12n_md_fini(void *md) 187*82629e30SMike Christensen { 188*82629e30SMike Christensen md_impl_t *mdp = (md_impl_t *)md; 189*82629e30SMike Christensen 190*82629e30SMike Christensen if (mdp) { 191*82629e30SMike Christensen free(mdp->caddr); 192*82629e30SMike Christensen (void) md_fini(md); 193*82629e30SMike Christensen } 194*82629e30SMike Christensen } 195*82629e30SMike Christensen 196*82629e30SMike Christensen /* 197*82629e30SMike Christensen * See if LDoms domaining is enabled, returns 1 if enabled. 198*82629e30SMike Christensen * Get the value of the 'domaining-enabled' property under the 199*82629e30SMike Christensen * 'platform' node. Value of 1 => domaining is enabled. 200*82629e30SMike Christensen */ 201*82629e30SMike Christensen static int 202*82629e30SMike Christensen v12n_domaining_enabled() 203*82629e30SMike Christensen { 204*82629e30SMike Christensen mde_cookie_t *nodes, rootnode; 205*82629e30SMike Christensen int nnodes; 206*82629e30SMike Christensen uint64_t prop_val = 0; 207*82629e30SMike Christensen md_t *mdp; 208*82629e30SMike Christensen 209*82629e30SMike Christensen if ((mdp = v12n_md_init()) == NULL) { 210*82629e30SMike Christensen return (0); 211*82629e30SMike Christensen } 212*82629e30SMike Christensen 213*82629e30SMike Christensen nnodes = md_node_count(mdp); 214*82629e30SMike Christensen nodes = malloc(nnodes * sizeof (mde_cookie_t)); 215*82629e30SMike Christensen if (nodes == NULL) { 216*82629e30SMike Christensen v12n_md_fini(mdp); 217*82629e30SMike Christensen return (0); 218*82629e30SMike Christensen } 219*82629e30SMike Christensen 220*82629e30SMike Christensen rootnode = md_root_node(mdp); 221*82629e30SMike Christensen 222*82629e30SMike Christensen nnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"), 223*82629e30SMike Christensen md_find_name(mdp, "fwd"), nodes); 224*82629e30SMike Christensen 225*82629e30SMike Christensen if (nnodes >= 1) { 226*82629e30SMike Christensen (void) md_get_prop_val(mdp, nodes[0], "domaining-enabled", 227*82629e30SMike Christensen &prop_val); 228*82629e30SMike Christensen } 229*82629e30SMike Christensen 230*82629e30SMike Christensen v12n_md_fini(mdp); 231*82629e30SMike Christensen free(nodes); 232*82629e30SMike Christensen return (prop_val == 1); 233*82629e30SMike Christensen } 234*82629e30SMike Christensen 235*82629e30SMike Christensen int 236*82629e30SMike Christensen v12n_capabilities() 237*82629e30SMike Christensen { 238*82629e30SMike Christensen struct utsname uinfo; 239*82629e30SMike Christensen struct stat st; 240*82629e30SMike Christensen int cap; 241*82629e30SMike Christensen 242*82629e30SMike Christensen /* 243*82629e30SMike Christensen * Check if this is an LDoms system. When using LDoms each 244*82629e30SMike Christensen * domain should have a /dev/mdesc device providing access to 245*82629e30SMike Christensen * the Machine Description (MD) of the domain. If this device 246*82629e30SMike Christensen * does not exist then this is not an LDoms system. 247*82629e30SMike Christensen */ 248*82629e30SMike Christensen if (uname(&uinfo) == -1 || strcmp(uinfo.machine, "sun4v")) { 249*82629e30SMike Christensen /* 250*82629e30SMike Christensen * Not sun4v -> LDoms not supported 251*82629e30SMike Christensen */ 252*82629e30SMike Christensen cap = 0; 253*82629e30SMike Christensen } else if (stat(MD_DEVICE, &st) == 0) { 254*82629e30SMike Christensen /* 255*82629e30SMike Christensen * sun4v + /dev/mdesc exists -> Check if LDoms enabled 256*82629e30SMike Christensen * via the 'domaining-enabled' property. 257*82629e30SMike Christensen */ 258*82629e30SMike Christensen cap = (V12N_CAP_SUPPORTED | V12N_CAP_IMPL_LDOMS | 259*82629e30SMike Christensen (v12n_domaining_enabled() ? V12N_CAP_ENABLED : 0)); 260*82629e30SMike Christensen } else if (errno == ENOENT) { 261*82629e30SMike Christensen /* 262*82629e30SMike Christensen * sun4v + /dev/mdesc does not exist -> LDoms supported 263*82629e30SMike Christensen * but not enabled. 264*82629e30SMike Christensen */ 265*82629e30SMike Christensen cap = (V12N_CAP_SUPPORTED | V12N_CAP_IMPL_LDOMS); 266*82629e30SMike Christensen } 267*82629e30SMike Christensen 268*82629e30SMike Christensen return (cap); 269*82629e30SMike Christensen } 270*82629e30SMike Christensen 271*82629e30SMike Christensen /* 272*82629e30SMike Christensen * Routines to support v12n_domain_roles. 273*82629e30SMike Christensen */ 274*82629e30SMike Christensen static int 275*82629e30SMike Christensen v12n_scan_md_nodes(md_t *mdp, char *node_name, char *node_str_prop, 276*82629e30SMike Christensen char **props) 277*82629e30SMike Christensen { 278*82629e30SMike Christensen mde_cookie_t *nodes, rootnode; 279*82629e30SMike Christensen int nnodes, i, j; 280*82629e30SMike Christensen char *prop_str; 281*82629e30SMike Christensen 282*82629e30SMike Christensen nnodes = md_node_count(mdp); 283*82629e30SMike Christensen nodes = malloc(nnodes * sizeof (mde_cookie_t)); 284*82629e30SMike Christensen if (nodes == NULL) { 285*82629e30SMike Christensen return (0); 286*82629e30SMike Christensen } 287*82629e30SMike Christensen 288*82629e30SMike Christensen rootnode = md_root_node(mdp); 289*82629e30SMike Christensen 290*82629e30SMike Christensen nnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, node_name), 291*82629e30SMike Christensen md_find_name(mdp, "fwd"), nodes); 292*82629e30SMike Christensen 293*82629e30SMike Christensen if (node_str_prop == NULL) 294*82629e30SMike Christensen return (nnodes > 0); 295*82629e30SMike Christensen 296*82629e30SMike Christensen for (i = 0; i < nnodes; i++) { 297*82629e30SMike Christensen if (md_get_prop_str(mdp, nodes[i], node_str_prop, &prop_str)) 298*82629e30SMike Christensen continue; 299*82629e30SMike Christensen for (j = 0; props[j] != NULL; j++) { 300*82629e30SMike Christensen if (strcmp(prop_str, props[j]) == 0) { 301*82629e30SMike Christensen free(nodes); 302*82629e30SMike Christensen return (1); 303*82629e30SMike Christensen } 304*82629e30SMike Christensen } 305*82629e30SMike Christensen } 306*82629e30SMike Christensen free(nodes); 307*82629e30SMike Christensen return (0); 308*82629e30SMike Christensen } 309*82629e30SMike Christensen 310*82629e30SMike Christensen /* 311*82629e30SMike Christensen * Check if MD has a hypervisor access point, returns 1 if true. 312*82629e30SMike Christensen * Check the MD for a 'virtual-device-port' node whose 'vldc-svc-name' is 313*82629e30SMike Christensen * 'hvctl'. 314*82629e30SMike Christensen */ 315*82629e30SMike Christensen static int 316*82629e30SMike Christensen v12n_check_hv_access(md_t *mdp) 317*82629e30SMike Christensen { 318*82629e30SMike Christensen static char *hvctl_str[] = { 319*82629e30SMike Christensen "hvctl", 320*82629e30SMike Christensen NULL 321*82629e30SMike Christensen }; 322*82629e30SMike Christensen 323*82629e30SMike Christensen return (v12n_scan_md_nodes(mdp, "virtual-device-port", "vldc-svc-name", 324*82629e30SMike Christensen hvctl_str)); 325*82629e30SMike Christensen } 326*82629e30SMike Christensen 327*82629e30SMike Christensen /* 328*82629e30SMike Christensen * Check if MD has a virtual device service (vcc, vsw, vds), returns 1 if true. 329*82629e30SMike Christensen * Need to check all the MD 'virtual-device' nodes for a 'device-type' property 330*82629e30SMike Christensen * of 'vcc', 'vsw' or 'vds'. 331*82629e30SMike Christensen */ 332*82629e30SMike Christensen static int 333*82629e30SMike Christensen v12n_check_virtual_service(md_t *mdp) 334*82629e30SMike Christensen { 335*82629e30SMike Christensen static char *vdevs[] = { 336*82629e30SMike Christensen "vcc", 337*82629e30SMike Christensen "vsw", 338*82629e30SMike Christensen "vds", 339*82629e30SMike Christensen NULL 340*82629e30SMike Christensen }; 341*82629e30SMike Christensen 342*82629e30SMike Christensen return (v12n_scan_md_nodes(mdp, "virtual-device", "device-type", 343*82629e30SMike Christensen vdevs)); 344*82629e30SMike Christensen } 345*82629e30SMike Christensen 346*82629e30SMike Christensen /* 347*82629e30SMike Christensen * Check if MD has an physical I/O device node, returns 1 if true. 348*82629e30SMike Christensen */ 349*82629e30SMike Christensen static int 350*82629e30SMike Christensen v12n_check_io_service(md_t *mdp) 351*82629e30SMike Christensen { 352*82629e30SMike Christensen return (v12n_scan_md_nodes(mdp, "iodevice", NULL, NULL)); 353*82629e30SMike Christensen } 354*82629e30SMike Christensen 355*82629e30SMike Christensen /* 356*82629e30SMike Christensen * Check if a MD node is root PCI device, returns 1 if true. 357*82629e30SMike Christensen * Need to check all the MD 'iodevice' nodes for a 'device-type' property 358*82629e30SMike Christensen * of 'pciex'. 359*82629e30SMike Christensen */ 360*82629e30SMike Christensen static int 361*82629e30SMike Christensen v12n_check_root(md_t *mdp) 362*82629e30SMike Christensen { 363*82629e30SMike Christensen static char *pciex[] = { 364*82629e30SMike Christensen "pciex", 365*82629e30SMike Christensen NULL 366*82629e30SMike Christensen }; 367*82629e30SMike Christensen 368*82629e30SMike Christensen return (v12n_scan_md_nodes(mdp, "iodevice", "device-type", pciex)); 369*82629e30SMike Christensen } 370*82629e30SMike Christensen 371*82629e30SMike Christensen /* 372*82629e30SMike Christensen * Get the domain roles for the domain. 373*82629e30SMike Christensen */ 374*82629e30SMike Christensen int 375*82629e30SMike Christensen v12n_domain_roles() 376*82629e30SMike Christensen { 377*82629e30SMike Christensen md_t *mdp; 378*82629e30SMike Christensen int roles = 0; 379*82629e30SMike Christensen 380*82629e30SMike Christensen if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) { 381*82629e30SMike Christensen errno = ENOTSUP; 382*82629e30SMike Christensen return (-1); 383*82629e30SMike Christensen } 384*82629e30SMike Christensen 385*82629e30SMike Christensen if ((mdp = v12n_md_init()) == NULL) { 386*82629e30SMike Christensen errno = EACCES; 387*82629e30SMike Christensen return (-1); 388*82629e30SMike Christensen } 389*82629e30SMike Christensen 390*82629e30SMike Christensen if (v12n_check_hv_access(mdp)) 391*82629e30SMike Christensen roles |= V12N_ROLE_CONTROL; 392*82629e30SMike Christensen 393*82629e30SMike Christensen if (v12n_check_virtual_service(mdp)) 394*82629e30SMike Christensen roles |= V12N_ROLE_SERVICE; 395*82629e30SMike Christensen 396*82629e30SMike Christensen if (v12n_check_io_service(mdp)) 397*82629e30SMike Christensen roles |= V12N_ROLE_IO; 398*82629e30SMike Christensen 399*82629e30SMike Christensen if (v12n_check_root(mdp)) 400*82629e30SMike Christensen roles |= V12N_ROLE_ROOT; 401*82629e30SMike Christensen 402*82629e30SMike Christensen v12n_md_fini(mdp); 403*82629e30SMike Christensen 404*82629e30SMike Christensen return (roles); 405*82629e30SMike Christensen } 406*82629e30SMike Christensen 407*82629e30SMike Christensen /* 408*82629e30SMike Christensen * Get domain name from MD's virtual domain service node, returns 1 on success. 409*82629e30SMike Christensen * The domain name is a string property 'vlds-domain-name' under the 410*82629e30SMike Christensen * 'virtual-device' device node whose name is 'virtual-domain-service'. 411*82629e30SMike Christensen */ 412*82629e30SMike Christensen static int 413*82629e30SMike Christensen v12n_get_md_domain_name(md_t *mdp, char **vds_dnamep) 414*82629e30SMike Christensen { 415*82629e30SMike Christensen mde_cookie_t *vdev_nodes, rootnode; 416*82629e30SMike Christensen int list_size, nvdevs, num_nodes, i, rv; 417*82629e30SMike Christensen char *vldc_name; 418*82629e30SMike Christensen 419*82629e30SMike Christensen num_nodes = md_node_count(mdp); 420*82629e30SMike Christensen list_size = num_nodes * sizeof (mde_cookie_t); 421*82629e30SMike Christensen vdev_nodes = malloc(list_size); 422*82629e30SMike Christensen if (vdev_nodes == NULL) { 423*82629e30SMike Christensen return (0); 424*82629e30SMike Christensen } 425*82629e30SMike Christensen 426*82629e30SMike Christensen rootnode = md_root_node(mdp); 427*82629e30SMike Christensen 428*82629e30SMike Christensen nvdevs = md_scan_dag(mdp, rootnode, md_find_name(mdp, "virtual-device"), 429*82629e30SMike Christensen md_find_name(mdp, "fwd"), vdev_nodes); 430*82629e30SMike Christensen 431*82629e30SMike Christensen rv = 0; 432*82629e30SMike Christensen for (i = 0; i < nvdevs; i++) { 433*82629e30SMike Christensen if (md_get_prop_str(mdp, vdev_nodes[i], "name", &vldc_name)) 434*82629e30SMike Christensen continue; 435*82629e30SMike Christensen if (strcmp(vldc_name, "virtual-domain-service") == 0) { 436*82629e30SMike Christensen rv = (md_get_prop_str(mdp, vdev_nodes[i], 437*82629e30SMike Christensen "vlds-domain-name", vds_dnamep) == 0); 438*82629e30SMike Christensen break; 439*82629e30SMike Christensen } 440*82629e30SMike Christensen } 441*82629e30SMike Christensen free(vdev_nodes); 442*82629e30SMike Christensen return (rv); 443*82629e30SMike Christensen } 444*82629e30SMike Christensen 445*82629e30SMike Christensen /* 446*82629e30SMike Christensen * String copyout utility. 447*82629e30SMike Christensen */ 448*82629e30SMike Christensen static size_t 449*82629e30SMike Christensen v12n_string_copyout(char *sout, char *sfrom, size_t count) 450*82629e30SMike Christensen { 451*82629e30SMike Christensen size_t ret = strlen(sfrom) + 1; 452*82629e30SMike Christensen 453*82629e30SMike Christensen if (sout != NULL && count > 0) { 454*82629e30SMike Christensen count = MIN(ret, count); 455*82629e30SMike Christensen (void) memcpy(sout, sfrom, count); 456*82629e30SMike Christensen } 457*82629e30SMike Christensen return (ret); 458*82629e30SMike Christensen } 459*82629e30SMike Christensen 460*82629e30SMike Christensen /* 461*82629e30SMike Christensen * Get the domain name of this domain. 462*82629e30SMike Christensen */ 463*82629e30SMike Christensen size_t 464*82629e30SMike Christensen v12n_domain_name(char *buf, size_t count) 465*82629e30SMike Christensen { 466*82629e30SMike Christensen md_t *mdp = NULL; 467*82629e30SMike Christensen char *ldmname; 468*82629e30SMike Christensen int rv = -1; 469*82629e30SMike Christensen 470*82629e30SMike Christensen if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) { 471*82629e30SMike Christensen errno = ENOTSUP; 472*82629e30SMike Christensen } else if ((mdp = v12n_md_init()) == NULL) { 473*82629e30SMike Christensen errno = EACCES; 474*82629e30SMike Christensen } else if (!v12n_get_md_domain_name(mdp, &ldmname)) { 475*82629e30SMike Christensen errno = ESRCH; 476*82629e30SMike Christensen } else { 477*82629e30SMike Christensen rv = v12n_string_copyout(buf, ldmname, count); 478*82629e30SMike Christensen } 479*82629e30SMike Christensen 480*82629e30SMike Christensen v12n_md_fini(mdp); 481*82629e30SMike Christensen return (rv); 482*82629e30SMike Christensen } 483*82629e30SMike Christensen 484*82629e30SMike Christensen /* 485*82629e30SMike Christensen * Get UUID string from MD, returns 1 on success. 486*82629e30SMike Christensen * The UUID is a string property 'uuid' under the 'platform' node of the MD. 487*82629e30SMike Christensen */ 488*82629e30SMike Christensen static int 489*82629e30SMike Christensen v12n_get_md_uuid_str(md_t *mdp, char **uuid_strp) 490*82629e30SMike Christensen { 491*82629e30SMike Christensen mde_cookie_t *plat_nodes, rootnode; 492*82629e30SMike Christensen int list_size, npnodes, num_nodes, rv; 493*82629e30SMike Christensen 494*82629e30SMike Christensen num_nodes = md_node_count(mdp); 495*82629e30SMike Christensen list_size = num_nodes * sizeof (mde_cookie_t); 496*82629e30SMike Christensen plat_nodes = malloc(list_size); 497*82629e30SMike Christensen if (plat_nodes == NULL) { 498*82629e30SMike Christensen return (0); 499*82629e30SMike Christensen } 500*82629e30SMike Christensen 501*82629e30SMike Christensen rootnode = md_root_node(mdp); 502*82629e30SMike Christensen 503*82629e30SMike Christensen npnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"), 504*82629e30SMike Christensen md_find_name(mdp, "fwd"), plat_nodes); 505*82629e30SMike Christensen 506*82629e30SMike Christensen if (npnodes >= 1) 507*82629e30SMike Christensen rv = !md_get_prop_str(mdp, plat_nodes[0], "uuid", uuid_strp); 508*82629e30SMike Christensen else 509*82629e30SMike Christensen rv = 0; 510*82629e30SMike Christensen 511*82629e30SMike Christensen free(plat_nodes); 512*82629e30SMike Christensen return (rv); 513*82629e30SMike Christensen } 514*82629e30SMike Christensen 515*82629e30SMike Christensen /* 516*82629e30SMike Christensen * Get the domain UUID. 517*82629e30SMike Christensen */ 518*82629e30SMike Christensen int 519*82629e30SMike Christensen v12n_domain_uuid(uuid_t uuid) 520*82629e30SMike Christensen { 521*82629e30SMike Christensen md_t *mdp = NULL; 522*82629e30SMike Christensen char *uuid_str; 523*82629e30SMike Christensen int rv = -1; 524*82629e30SMike Christensen 525*82629e30SMike Christensen if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) { 526*82629e30SMike Christensen errno = ENOTSUP; 527*82629e30SMike Christensen } else if ((mdp = v12n_md_init()) == NULL) { 528*82629e30SMike Christensen errno = EACCES; 529*82629e30SMike Christensen } else if (!v12n_get_md_uuid_str(mdp, &uuid_str)) { 530*82629e30SMike Christensen errno = ESRCH; 531*82629e30SMike Christensen } else { 532*82629e30SMike Christensen rv = uuid_parse(uuid_str, uuid); 533*82629e30SMike Christensen } 534*82629e30SMike Christensen 535*82629e30SMike Christensen v12n_md_fini(mdp); 536*82629e30SMike Christensen 537*82629e30SMike Christensen return (rv); 538*82629e30SMike Christensen } 539*82629e30SMike Christensen 540*82629e30SMike Christensen /* 541*82629e30SMike Christensen * Send 'agent-sytem' request message. 542*82629e30SMike Christensen */ 543*82629e30SMike Christensen static int 544*82629e30SMike Christensen v12n_ldma_send_request() 545*82629e30SMike Christensen { 546*82629e30SMike Christensen ldma_message_header_t ldmamsg; 547*82629e30SMike Christensen 548*82629e30SMike Christensen if (v12n_ds_send_msg == NULL || v12n_ldma_ctrl_hdl == DS_INVALID_HDL) 549*82629e30SMike Christensen return (ENOENT); 550*82629e30SMike Christensen 551*82629e30SMike Christensen ldmamsg.msg_num = 0; 552*82629e30SMike Christensen ldmamsg.msg_type = v12n_ldma_msgtype; 553*82629e30SMike Christensen ldmamsg.msg_info = 0; 554*82629e30SMike Christensen return (v12n_ds_send_msg(v12n_ldma_ctrl_hdl, (char *)&ldmamsg, 555*82629e30SMike Christensen sizeof (ldmamsg))); 556*82629e30SMike Christensen } 557*82629e30SMike Christensen 558*82629e30SMike Christensen /* 559*82629e30SMike Christensen * 'agent-system' registration handler. 560*82629e30SMike Christensen * If we get a registration from the control domain (domain 0), then send 561*82629e30SMike Christensen * the requested message. Otherwise, ignore the registration. 562*82629e30SMike Christensen */ 563*82629e30SMike Christensen /* ARGSUSED */ 564*82629e30SMike Christensen static void 565*82629e30SMike Christensen v12n_ldma_register_handler(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver, 566*82629e30SMike Christensen ds_domain_hdl_t dhdl) 567*82629e30SMike Christensen { 568*82629e30SMike Christensen 569*82629e30SMike Christensen /* got registration from control domain */ 570*82629e30SMike Christensen if (dhdl == 0) { 571*82629e30SMike Christensen (void) mutex_lock(&v12n_ldma_cv_lock); 572*82629e30SMike Christensen if (v12n_ldma_cv_state == V12N_LDMA_REGWAITING) { 573*82629e30SMike Christensen v12n_ldma_ctrl_hdl = hdl; 574*82629e30SMike Christensen v12n_ldma_cv_state = V12N_LDMA_REGRECEIVED; 575*82629e30SMike Christensen (void) cond_signal(&v12n_ldma_cv); 576*82629e30SMike Christensen } 577*82629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock); 578*82629e30SMike Christensen } 579*82629e30SMike Christensen } 580*82629e30SMike Christensen 581*82629e30SMike Christensen /* 582*82629e30SMike Christensen * 'agent-system' data handler. 583*82629e30SMike Christensen */ 584*82629e30SMike Christensen /* ARGSUSED */ 585*82629e30SMike Christensen static void 586*82629e30SMike Christensen v12n_ldma_data_handler(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf, 587*82629e30SMike Christensen size_t buflen) 588*82629e30SMike Christensen { 589*82629e30SMike Christensen char *data; 590*82629e30SMike Christensen ldma_message_header_t *ldmp; 591*82629e30SMike Christensen int n; 592*82629e30SMike Christensen int cv_state = V12N_LDMA_MSGERROR; 593*82629e30SMike Christensen 594*82629e30SMike Christensen /* 595*82629e30SMike Christensen * Ignore any message not from the control domain. 596*82629e30SMike Christensen */ 597*82629e30SMike Christensen if (v12n_ldma_ctrl_hdl != hdl) 598*82629e30SMike Christensen return; 599*82629e30SMike Christensen 600*82629e30SMike Christensen /* 601*82629e30SMike Christensen * Ignore any unexpected message. 602*82629e30SMike Christensen */ 603*82629e30SMike Christensen if (buflen < LDMA_MESSAGE_HEADER_SIZE) 604*82629e30SMike Christensen return; 605*82629e30SMike Christensen 606*82629e30SMike Christensen /* 607*82629e30SMike Christensen * Ignore message with unexpected msgnum. 608*82629e30SMike Christensen */ 609*82629e30SMike Christensen ldmp = (ldma_message_header_t *)buf; 610*82629e30SMike Christensen if (ldmp->msg_num != 0) 611*82629e30SMike Christensen return; 612*82629e30SMike Christensen 613*82629e30SMike Christensen switch (ldmp->msg_type) { 614*82629e30SMike Christensen 615*82629e30SMike Christensen case LDMA_MSG_RESULT: 616*82629e30SMike Christensen if (ldmp->msg_info == 0 || 617*82629e30SMike Christensen ldmp->msg_info > LDMA_MESSAGE_DLEN(buflen)) { 618*82629e30SMike Christensen cv_state = V12N_LDMA_MSGERROR; 619*82629e30SMike Christensen break; 620*82629e30SMike Christensen } 621*82629e30SMike Christensen data = LDMA_HDR2DATA(buf); 622*82629e30SMike Christensen 623*82629e30SMike Christensen /* ensure that data ends with a '\0' */ 624*82629e30SMike Christensen data[ldmp->msg_info - 1] = '\0'; 625*82629e30SMike Christensen switch (v12n_ldma_msgtype) { 626*82629e30SMike Christensen 627*82629e30SMike Christensen case LDMA_MSGSYS_GET_SYSINFO: 628*82629e30SMike Christensen /* 629*82629e30SMike Christensen * Control domain nodename is second string in the 630*82629e30SMike Christensen * message. Make sure there is enough data in the msg 631*82629e30SMike Christensen * to have a second string. 632*82629e30SMike Christensen */ 633*82629e30SMike Christensen n = strlen(data); 634*82629e30SMike Christensen if (LDMA_MESSAGE_DLEN(buflen) <= n + 3) { 635*82629e30SMike Christensen cv_state = V12N_LDMA_MSGERROR; 636*82629e30SMike Christensen break; 637*82629e30SMike Christensen } 638*82629e30SMike Christensen data += n + 1; 639*82629e30SMike Christensen if ((v12n_ldma_msgstr = strdup(data)) == NULL) 640*82629e30SMike Christensen cv_state = V12N_LDMA_MSGERROR; 641*82629e30SMike Christensen else 642*82629e30SMike Christensen cv_state = V12N_LDMA_MSGRECEIVED; 643*82629e30SMike Christensen break; 644*82629e30SMike Christensen 645*82629e30SMike Christensen case LDMA_MSGSYS_GET_CHASSISNO: 646*82629e30SMike Christensen if ((v12n_ldma_msgstr = strdup(data)) == NULL) 647*82629e30SMike Christensen cv_state = V12N_LDMA_MSGERROR; 648*82629e30SMike Christensen else 649*82629e30SMike Christensen cv_state = V12N_LDMA_MSGRECEIVED; 650*82629e30SMike Christensen break; 651*82629e30SMike Christensen 652*82629e30SMike Christensen default: 653*82629e30SMike Christensen /* v12n_ldma_msgtype must be valid */ 654*82629e30SMike Christensen ASSERT(0); 655*82629e30SMike Christensen } 656*82629e30SMike Christensen break; 657*82629e30SMike Christensen 658*82629e30SMike Christensen case LDMA_MSG_ERROR: 659*82629e30SMike Christensen cv_state = V12N_LDMA_MSGERROR; 660*82629e30SMike Christensen break; 661*82629e30SMike Christensen 662*82629e30SMike Christensen default: 663*82629e30SMike Christensen /* unexpected message, ignored */ 664*82629e30SMike Christensen return; 665*82629e30SMike Christensen } 666*82629e30SMike Christensen 667*82629e30SMike Christensen (void) mutex_lock(&v12n_ldma_cv_lock); 668*82629e30SMike Christensen v12n_ldma_cv_state = cv_state; 669*82629e30SMike Christensen (void) cond_signal(&v12n_ldma_cv); 670*82629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock); 671*82629e30SMike Christensen } 672*82629e30SMike Christensen 673*82629e30SMike Christensen 674*82629e30SMike Christensen /* 675*82629e30SMike Christensen * libds doesn't exist on non-sun4v, dynamically load it and get the 676*82629e30SMike Christensen * function pointers to the needed lib functions. 677*82629e30SMike Christensen */ 678*82629e30SMike Christensen static int 679*82629e30SMike Christensen v12n_libds_init(void) 680*82629e30SMike Christensen { 681*82629e30SMike Christensen if (v12n_ds_dlhdl != NULL) { 682*82629e30SMike Christensen if (v12n_ds_clnt_reg == NULL || v12n_ds_send_msg == NULL || 683*82629e30SMike Christensen v12n_ds_unreg_svc == NULL) 684*82629e30SMike Christensen return (ENOENT); 685*82629e30SMike Christensen return (0); 686*82629e30SMike Christensen } 687*82629e30SMike Christensen 688*82629e30SMike Christensen if ((v12n_ds_dlhdl = dlopen("libds.so.1", 689*82629e30SMike Christensen RTLD_NOW | RTLD_GLOBAL)) == NULL) 690*82629e30SMike Christensen return (ENOENT); 691*82629e30SMike Christensen 692*82629e30SMike Christensen if ((v12n_ds_clnt_reg = (int (*)(ds_capability_t *, ds_ops_t *)) 693*82629e30SMike Christensen dlsym(v12n_ds_dlhdl, "ds_clnt_reg")) == NULL) 694*82629e30SMike Christensen return (ENOENT); 695*82629e30SMike Christensen 696*82629e30SMike Christensen if ((v12n_ds_send_msg = (int (*)(ds_hdl_t, void *, size_t)) 697*82629e30SMike Christensen dlsym(v12n_ds_dlhdl, "ds_send_msg")) == NULL) 698*82629e30SMike Christensen return (ENOENT); 699*82629e30SMike Christensen 700*82629e30SMike Christensen if ((v12n_ds_unreg_svc = (int (*)(char *, boolean_t)) 701*82629e30SMike Christensen dlsym(v12n_ds_dlhdl, "ds_unreg_svc")) == NULL) 702*82629e30SMike Christensen return (ENOENT); 703*82629e30SMike Christensen 704*82629e30SMike Christensen return (0); 705*82629e30SMike Christensen } 706*82629e30SMike Christensen 707*82629e30SMike Christensen /* 708*82629e30SMike Christensen * Initiate and wait for an ldmad 'agent-system' domain service. 709*82629e30SMike Christensen * Dynamically load libds, register the client 'agent-system' service 710*82629e30SMike Christensen * and wait for a specified amount of time for the 'agent-system' 711*82629e30SMike Christensen * service on the control domain to respond to the request. 712*82629e30SMike Christensen */ 713*82629e30SMike Christensen static int 714*82629e30SMike Christensen v12n_get_ldma_system_msg(int msgtype, char **strp) 715*82629e30SMike Christensen { 716*82629e30SMike Christensen int tout; 717*82629e30SMike Christensen int err = 0; 718*82629e30SMike Christensen timestruc_t timeout; 719*82629e30SMike Christensen 720*82629e30SMike Christensen /* 721*82629e30SMike Christensen * Ensure that there's only one thread trying to do a 722*82629e30SMike Christensen * 'agent-system' client registration/message at a time. 723*82629e30SMike Christensen */ 724*82629e30SMike Christensen (void) mutex_lock(&v12n_ldma_lock); 725*82629e30SMike Christensen if ((err = v12n_libds_init()) != 0) 726*82629e30SMike Christensen goto done; 727*82629e30SMike Christensen 728*82629e30SMike Christensen v12n_ldma_msgtype = msgtype; 729*82629e30SMike Christensen v12n_ldma_msgstr = NULL; 730*82629e30SMike Christensen 731*82629e30SMike Christensen /* initialize v12n_ldma_cv_state variable before registering service */ 732*82629e30SMike Christensen (void) mutex_lock(&v12n_ldma_cv_lock); 733*82629e30SMike Christensen v12n_ldma_cv_state = V12N_LDMA_REGWAITING; 734*82629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock); 735*82629e30SMike Christensen 736*82629e30SMike Christensen /* 737*82629e30SMike Christensen * Other instances may be trying to load the "agent-system" service. 738*82629e30SMike Christensen * If a collision happens (EBUSY error), wait and try again. 739*82629e30SMike Christensen */ 740*82629e30SMike Christensen for (tout = 0; tout < v12n_ldma_timeout; tout += v12n_ldma_sleeptime) { 741*82629e30SMike Christensen if ((err = v12n_ds_clnt_reg(&v12n_ldma_cap, 742*82629e30SMike Christensen &v12n_ldma_ops)) == 0) 743*82629e30SMike Christensen break; 744*82629e30SMike Christensen if (err != EALREADY) { 745*82629e30SMike Christensen goto done; 746*82629e30SMike Christensen } 747*82629e30SMike Christensen (void) sleep(v12n_ldma_sleeptime); 748*82629e30SMike Christensen } 749*82629e30SMike Christensen 750*82629e30SMike Christensen if (tout >= v12n_ldma_timeout) { 751*82629e30SMike Christensen err = EBUSY; 752*82629e30SMike Christensen goto done; 753*82629e30SMike Christensen } 754*82629e30SMike Christensen 755*82629e30SMike Christensen /* 756*82629e30SMike Christensen * Wait for control domain registration. 757*82629e30SMike Christensen */ 758*82629e30SMike Christensen timeout.tv_sec = v12n_ldma_timeout; 759*82629e30SMike Christensen timeout.tv_nsec = 0; 760*82629e30SMike Christensen 761*82629e30SMike Christensen (void) mutex_lock(&v12n_ldma_cv_lock); 762*82629e30SMike Christensen while (v12n_ldma_cv_state == V12N_LDMA_REGWAITING) { 763*82629e30SMike Christensen if ((err = cond_reltimedwait(&v12n_ldma_cv, 764*82629e30SMike Christensen &v12n_ldma_cv_lock, &timeout)) != EINTR) 765*82629e30SMike Christensen break; 766*82629e30SMike Christensen } 767*82629e30SMike Christensen 768*82629e30SMike Christensen /* 769*82629e30SMike Christensen * Check for timeout or an error. 770*82629e30SMike Christensen */ 771*82629e30SMike Christensen if (v12n_ldma_cv_state != V12N_LDMA_REGRECEIVED) { 772*82629e30SMike Christensen if (err == 0) 773*82629e30SMike Christensen err = EPROTO; 774*82629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock); 775*82629e30SMike Christensen goto done; 776*82629e30SMike Christensen } 777*82629e30SMike Christensen 778*82629e30SMike Christensen /* 779*82629e30SMike Christensen * Received a registration request, send the request message. 780*82629e30SMike Christensen */ 781*82629e30SMike Christensen v12n_ldma_cv_state = V12N_LDMA_MSGWAITING; 782*82629e30SMike Christensen if ((err = v12n_ldma_send_request()) != 0) { 783*82629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock); 784*82629e30SMike Christensen goto done; 785*82629e30SMike Christensen } 786*82629e30SMike Christensen 787*82629e30SMike Christensen while (v12n_ldma_cv_state == V12N_LDMA_MSGWAITING) { 788*82629e30SMike Christensen if ((err = cond_reltimedwait(&v12n_ldma_cv, 789*82629e30SMike Christensen &v12n_ldma_cv_lock, &timeout)) != EINTR) 790*82629e30SMike Christensen break; 791*82629e30SMike Christensen } 792*82629e30SMike Christensen 793*82629e30SMike Christensen if (v12n_ldma_cv_state != V12N_LDMA_MSGRECEIVED) { 794*82629e30SMike Christensen if (err == 0) 795*82629e30SMike Christensen err = EPROTO; 796*82629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock); 797*82629e30SMike Christensen goto done; 798*82629e30SMike Christensen } 799*82629e30SMike Christensen 800*82629e30SMike Christensen v12n_ldma_cv_state = V12N_LDMA_CVINVALID; 801*82629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock); 802*82629e30SMike Christensen 803*82629e30SMike Christensen /* 804*82629e30SMike Christensen * If v12n_ldma_msgstr is set, a valid data response was seen. 805*82629e30SMike Christensen */ 806*82629e30SMike Christensen if (v12n_ldma_msgstr == NULL) 807*82629e30SMike Christensen err = ENODATA; 808*82629e30SMike Christensen else { 809*82629e30SMike Christensen if (*v12n_ldma_msgstr == '\0' || 810*82629e30SMike Christensen (*strp = strdup(v12n_ldma_msgstr)) == NULL) 811*82629e30SMike Christensen err = ENODATA; 812*82629e30SMike Christensen free(v12n_ldma_msgstr); 813*82629e30SMike Christensen v12n_ldma_msgstr = NULL; 814*82629e30SMike Christensen } 815*82629e30SMike Christensen 816*82629e30SMike Christensen done: 817*82629e30SMike Christensen v12n_ds_unreg_svc(LDMA_NAME_SYSTEM, B_TRUE); 818*82629e30SMike Christensen v12n_ldma_msgtype = -1; 819*82629e30SMike Christensen v12n_ldma_ctrl_hdl = DS_INVALID_HDL; 820*82629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_lock); 821*82629e30SMike Christensen 822*82629e30SMike Christensen return (err); 823*82629e30SMike Christensen } 824*82629e30SMike Christensen 825*82629e30SMike Christensen /* 826*82629e30SMike Christensen * Get the nodename of the control domain. Returns the equivalent 827*82629e30SMike Christensen * of 'uname -n' on the control domain. 828*82629e30SMike Christensen * This is obtained via the 'agent-system' domain service provided 829*82629e30SMike Christensen * by ldmad. 830*82629e30SMike Christensen */ 831*82629e30SMike Christensen size_t 832*82629e30SMike Christensen v12n_ctrl_domain(char *buf, size_t count) 833*82629e30SMike Christensen { 834*82629e30SMike Christensen char *str; 835*82629e30SMike Christensen int err; 836*82629e30SMike Christensen size_t rv = (size_t)(-1); 837*82629e30SMike Christensen 838*82629e30SMike Christensen if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) { 839*82629e30SMike Christensen errno = ENOTSUP; 840*82629e30SMike Christensen } else if ((err = v12n_get_ldma_system_msg(LDMA_MSGSYS_GET_SYSINFO, 841*82629e30SMike Christensen &str)) != 0) { 842*82629e30SMike Christensen errno = err; 843*82629e30SMike Christensen } else { 844*82629e30SMike Christensen rv = v12n_string_copyout(buf, str, count); 845*82629e30SMike Christensen } 846*82629e30SMike Christensen return (rv); 847*82629e30SMike Christensen } 848*82629e30SMike Christensen 849*82629e30SMike Christensen /* 850*82629e30SMike Christensen * Get the Chassis serial number from the Control Domain. 851*82629e30SMike Christensen * This is obtained via the 'agent-system' domain service provided 852*82629e30SMike Christensen * by ldmad. 853*82629e30SMike Christensen */ 854*82629e30SMike Christensen size_t 855*82629e30SMike Christensen v12n_chassis_serialno(char *buf, size_t count) 856*82629e30SMike Christensen { 857*82629e30SMike Christensen char *str; 858*82629e30SMike Christensen int err; 859*82629e30SMike Christensen size_t rv = (size_t)(-1); 860*82629e30SMike Christensen 861*82629e30SMike Christensen if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) { 862*82629e30SMike Christensen errno = ENOTSUP; 863*82629e30SMike Christensen } else if ((err = v12n_get_ldma_system_msg(LDMA_MSGSYS_GET_CHASSISNO, 864*82629e30SMike Christensen &str)) != 0) { 865*82629e30SMike Christensen errno = err; 866*82629e30SMike Christensen } else { 867*82629e30SMike Christensen rv = v12n_string_copyout(buf, str, count); 868*82629e30SMike Christensen } 869*82629e30SMike Christensen return (rv); 870*82629e30SMike Christensen } 871