1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <unistd.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <strings.h> 31 #include <fcntl.h> 32 #include <pthread.h> 33 #include <errno.h> 34 #include <libnvpair.h> 35 #include <dlfcn.h> 36 #include <link.h> 37 #include <assert.h> 38 39 #include <fm/libtopo.h> 40 #include <sys/processor.h> 41 #include <sys/stat.h> 42 #include <sys/mdesc.h> 43 #include <sys/param.h> 44 #include <sys/systeminfo.h> 45 #include <sys/mem.h> 46 #include <sys/bl.h> 47 #include <sys/fm/protocol.h> 48 #include <fm/fmd_fmri.h> 49 #include <fm/fmd_agent.h> 50 #include <sys/pri.h> 51 52 #include "ldom.h" 53 #include "ldom_alloc.h" 54 #include "ldmsvcs_utils.h" 55 #include "ldom_xmpp_client.h" 56 57 #define MD_STR_PLATFORM "platform" 58 #define MD_STR_DOM_CAPABLE "domaining-enabled" 59 #define MD_STR_IODEVICE "iodevice" 60 #define MD_STR_NAME "name" 61 #define MD_STR_DEVICE_TYPE "device-type" 62 #define MD_STR_CFGHDL "cfg-handle" 63 #define MD_STR_PCIEX "pciex" 64 #define MD_STR_PCI "pci" 65 #define MD_STR_NIU "niu" 66 67 static int ldom_ldmd_is_up = 0; /* assume stays up if ever seen up */ 68 69 static void *ldom_dl_hp = (void *)NULL; 70 static const char *ldom_dl_path = "libpri.so.1"; 71 static int ldom_dl_mode = (RTLD_NOW | RTLD_LOCAL); 72 73 static pthread_mutex_t ldom_pri_lock = PTHREAD_MUTEX_INITIALIZER; 74 static int ldom_pri_ref_cnt = 0; /* num of outstanding ldom_pri_init()s */ 75 static int ldom_pri_init_done = 0; /* bool for real pri_init() done */ 76 static int (*ldom_pri_fp_init)(void) = (int (*)(void))NULL; 77 static void (*ldom_pri_fp_fini)(void) = (void (*)(void))NULL; 78 static ssize_t (*ldom_pri_fp_get)(uint8_t wait, uint64_t *token, uint64_t **buf, 79 void *(*allocp)(size_t), void (*freep)(void *, size_t)) = 80 (ssize_t (*)(uint8_t wait, uint64_t *token, uint64_t **buf, 81 void *(*allocp)(size_t), void (*freep)(void *, size_t)))NULL; 82 83 static void 84 ldom_pri_config(void) 85 { 86 char isa[MAXNAMELEN]; /* used to see if machine is sun4v */ 87 88 if (sysinfo(SI_MACHINE, isa, MAXNAMELEN) < 0) 89 return; 90 if (strcmp(isa, "sun4v") != 0) 91 return; 92 if ((ldom_dl_hp = dlopen(ldom_dl_path, ldom_dl_mode)) == NULL) 93 return; 94 95 ldom_pri_fp_init = (int (*)(void))dlsym(ldom_dl_hp, "pri_init"); 96 ldom_pri_fp_fini = (void (*)(void))dlsym(ldom_dl_hp, "pri_fini"); 97 ldom_pri_fp_get = (ssize_t (*)(uint8_t wait, uint64_t *token, 98 uint64_t **buf, void *(*allocp)(size_t), 99 void (*freep)(void *, size_t)))dlsym(ldom_dl_hp, "pri_get"); 100 } 101 102 static void 103 ldom_pri_unconfig(void) 104 { 105 if (ldom_dl_hp == NULL) 106 return; 107 108 ldom_pri_fp_init = (int (*)(void))NULL; 109 ldom_pri_fp_fini = (void (*)(void))NULL; 110 ldom_pri_fp_get = (ssize_t (*)(uint8_t wait, uint64_t *token, 111 uint64_t **buf, void *(*allocp)(size_t), 112 void (*freep)(void *, size_t)))NULL; 113 (void) dlclose(ldom_dl_hp); 114 ldom_dl_hp = (void *)NULL; 115 } 116 117 /* 118 * ldom_pri_lock is assumed already held by anyone accessing ldom_pri_ref_cnt 119 */ 120 121 static int 122 ldom_pri_init(void) 123 { 124 if (ldom_pri_ref_cnt == 0) { 125 ldom_pri_config(); 126 /* 127 * ldom_pri_init() is called before we know whether we 128 * have LDOMS FW or not; defer calling pri_init() via 129 * ldom_pri_fp_init until the first time we try to 130 * actually get a PRI 131 */ 132 } 133 ldom_pri_ref_cnt++; 134 135 assert(ldom_pri_ref_cnt > 0); 136 137 return (0); 138 } 139 140 static void 141 ldom_pri_fini(void) 142 { 143 assert(ldom_pri_ref_cnt > 0); 144 145 ldom_pri_ref_cnt--; 146 if (ldom_pri_ref_cnt == 0) { 147 if (ldom_pri_init_done && (ldom_pri_fp_fini != NULL)) { 148 (*ldom_pri_fp_fini)(); 149 ldom_pri_init_done = 0; 150 } 151 ldom_pri_unconfig(); 152 } 153 } 154 155 static ssize_t 156 ldom_pri_get(uint8_t wait, uint64_t *token, uint64_t **buf, 157 void *(*allocp)(size_t), void (*freep)(void *, size_t)) 158 { 159 assert(ldom_pri_ref_cnt > 0); 160 161 if ((!ldom_pri_init_done) && (ldom_pri_fp_init != NULL)) { 162 if ((*ldom_pri_fp_init)() < 0) 163 return (-1); 164 ldom_pri_init_done = 1; 165 } 166 167 if (ldom_pri_fp_get != NULL) 168 return ((*ldom_pri_fp_get)(wait, token, buf, allocp, freep)); 169 else 170 return (-1); 171 } 172 173 static ssize_t 174 get_local_core_md(ldom_hdl_t *lhp, uint64_t **buf) 175 { 176 int fh; 177 size_t size; 178 uint64_t *bufp; 179 180 if ((fh = open("/devices/pseudo/mdesc@0:mdesc", O_RDONLY, 0)) < 0) 181 return (-1); 182 183 if (ioctl(fh, MDESCIOCGSZ, &size) < 0) { 184 (void) close(fh); 185 return (-1); 186 } 187 188 bufp = (uint64_t *)lhp->allocp(size); 189 190 if (read(fh, bufp, size) < 0) { 191 lhp->freep(bufp, size); 192 (void) close(fh); 193 return (-1); 194 } 195 (void) close(fh); 196 197 *buf = bufp; 198 199 return ((ssize_t)size); 200 } 201 202 203 static int 204 get_local_md_prop_value(ldom_hdl_t *lhp, char *node, char *prop, uint64_t *val) 205 { 206 int rc = 1; 207 uint64_t *bufp; 208 ssize_t bufsiz; 209 210 if ((bufsiz = get_local_core_md(lhp, &bufp)) > 0) { 211 md_t *mdp; 212 213 if (mdp = md_init_intern(bufp, lhp->allocp, lhp->freep)) { 214 int num_nodes; 215 mde_cookie_t *listp; 216 217 num_nodes = md_node_count(mdp); 218 listp = lhp->allocp(sizeof (mde_cookie_t) * num_nodes); 219 220 if (md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, 221 md_find_name(mdp, node), 222 md_find_name(mdp, "fwd"), listp) > 0 && 223 md_get_prop_val(mdp, listp[0], prop, val) >= 0) { 224 /* found the property */ 225 rc = 0; 226 } 227 228 lhp->freep(listp, sizeof (mde_cookie_t) * num_nodes); 229 (void) md_fini(mdp); 230 } 231 lhp->freep(bufp, bufsiz); 232 } 233 return (rc); 234 } 235 236 /* 237 * search the machine description for a "pid" entry (physical cpuid) and 238 * return the corresponding "id" entry (virtual cpuid). 239 * return -1 if not found. 240 * if the pid property does not exist in a cpu node, assume pid = id. 241 */ 242 static processorid_t 243 cpu_phys2virt(ldom_hdl_t *lhp, uint32_t cpuid) 244 { 245 char isa[MAXNAMELEN]; 246 md_t *mdp; 247 mde_cookie_t *listp; 248 ssize_t bufsize; 249 processorid_t vid; 250 uint64_t *bufp; 251 uint64_t pval, pid, id; 252 int num_nodes, ncpus, i; 253 254 (void) sysinfo(SI_MACHINE, isa, MAXNAMELEN); 255 256 if (strcmp(isa, "sun4v") != 0) 257 return ((processorid_t)cpuid); 258 259 /* 260 * convert the physical cpuid to a virtual cpuid 261 */ 262 if ((bufsize = get_local_core_md(lhp, &bufp)) < 1) 263 return (-1); 264 265 if ((mdp = md_init_intern(bufp, lhp->allocp, lhp->freep)) == NULL || 266 (num_nodes = md_node_count(mdp)) < 1) { 267 lhp->freep(bufp, bufsize); 268 return (-1); 269 } 270 271 listp = (mde_cookie_t *)lhp->allocp(sizeof (mde_cookie_t) * num_nodes); 272 ncpus = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, 273 md_find_name(mdp, "cpu"), md_find_name(mdp, "fwd"), listp); 274 275 vid = -1; 276 for (i = 0; i < ncpus; i++) { 277 if (md_get_prop_val(mdp, listp[i], "id", &pval) < 0) 278 pval = (uint64_t)-1; 279 id = pval; 280 281 /* if pid does not exist, assume pid=id */ 282 if (md_get_prop_val(mdp, listp[i], "pid", &pval) < 0) 283 pval = id; 284 pid = pval; 285 286 if (pid == (uint64_t)cpuid) { 287 /* Found the entry */ 288 vid = (processorid_t)id; 289 break; 290 } 291 } 292 293 lhp->freep(listp, sizeof (mde_cookie_t) * num_nodes); 294 (void) md_fini(mdp); 295 lhp->freep(bufp, bufsize); 296 297 return (vid); 298 } 299 300 static int 301 get_type(ldom_hdl_t *lhp, uint32_t *type) 302 { 303 int num_nodes, cnt, i, rc; 304 char *p; 305 mde_cookie_t *listp; 306 md_t *mdp; 307 uint64_t domain_capable; 308 uint64_t *bufp; 309 ssize_t bufsize; 310 311 *type = 0; 312 313 /* legacy system */ 314 if (get_local_md_prop_value(lhp, MD_STR_PLATFORM, MD_STR_DOM_CAPABLE, 315 &domain_capable) != 0) { 316 *type = LDOM_TYPE_LEGACY; 317 return (0); 318 } 319 320 /* 321 * LDOMS capable FW is installed; it should be ok to 322 * try to communicate with ldmd 323 */ 324 if ((rc = ldmsvcs_check_channel()) == 0) { 325 /* 326 * control ldom 327 * ldmfma channel between FMA and ldmd only exists 328 * on the control domain. 329 */ 330 *type |= LDOM_TYPE_CONTROL; 331 } else if (rc == -1) { 332 return (rc); 333 } 334 335 /* 336 * root domain and io domain 337 */ 338 if ((bufsize = get_local_core_md(lhp, &bufp)) < 1) 339 return (-1); 340 if ((mdp = md_init_intern(bufp, lhp->allocp, lhp->freep)) == NULL) { 341 lhp->freep(bufp, bufsize); 342 return (-1); 343 } 344 if ((num_nodes = md_node_count(mdp)) < 1) { 345 lhp->freep(bufp, bufsize); 346 (void) md_fini(mdp); 347 return (-1); 348 } 349 350 /* Search for the root complex and niu nodes */ 351 listp = lhp->allocp(sizeof (mde_cookie_t) * num_nodes); 352 cnt = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, 353 md_find_name(mdp, MD_STR_IODEVICE), md_find_name(mdp, "fwd"), 354 listp); 355 for (i = 0, p = NULL; i < cnt; i++) { 356 if ((md_get_prop_str(mdp, listp[i], MD_STR_DEVICE_TYPE, &p) 357 == 0) && 358 (p != NULL) && (strcmp(p, MD_STR_PCIEX) == 0)) { 359 *type |= LDOM_TYPE_ROOT; 360 break; 361 } 362 } 363 for (i = 0, p = NULL; i < cnt; i++) { 364 if ((md_get_prop_str(mdp, listp[i], MD_STR_NAME, &p) == 0) && 365 (p != NULL) && (strcmp(p, MD_STR_NIU) == 0)) { 366 *type |= LDOM_TYPE_IO; 367 break; 368 } 369 } 370 lhp->freep(listp, sizeof (mde_cookie_t) * num_nodes); 371 (void) md_fini(mdp); 372 lhp->freep(bufp, bufsize); 373 374 return (0); 375 } 376 377 int 378 ldom_get_type(ldom_hdl_t *lhp, uint32_t *type) 379 { 380 static pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER; 381 static pthread_cond_t cv = PTHREAD_COND_INITIALIZER; 382 static uint32_t ltype = 0; 383 static int busy_init = 0; 384 385 int rc = 0; 386 387 (void) pthread_mutex_lock(&mt); 388 389 while (busy_init == 1) 390 (void) pthread_cond_wait(&cv, &mt); 391 392 if (VALID_LDOM_TYPE(ltype) != 0) { 393 *type = ltype; 394 (void) pthread_mutex_unlock(&mt); 395 return (0); 396 } 397 398 /* 399 * get to this point if the ldom_type has not yet been determined 400 */ 401 busy_init = 1; 402 (void) pthread_mutex_unlock(&mt); 403 404 rc = get_type(lhp, <ype); 405 if (rc == 0) { 406 *type = ltype; 407 } 408 409 (void) pthread_mutex_lock(&mt); 410 busy_init = 0; 411 (void) pthread_mutex_unlock(&mt); 412 413 (void) pthread_cond_broadcast(&cv); 414 415 return (rc); 416 } 417 418 int 419 ldom_fmri_status(ldom_hdl_t *lhp, nvlist_t *nvl) 420 { 421 char *name; 422 int ret = ENOTSUP; 423 424 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) 425 return (EINVAL); 426 427 /* 428 * ldom_ldmd_is_up can only be true if a pri can be obtained from ldmd. 429 */ 430 if (!ldom_ldmd_is_up) { 431 /* Zeus is unavail; use local routines for status/retire */ 432 433 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 434 processorid_t vid; 435 uint32_t cpuid; 436 437 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) 438 == 0 && (vid = cpu_phys2virt(lhp, cpuid)) != -1) 439 return (p_online(vid, P_STATUS)); 440 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 441 fmd_agent_hdl_t *hdl; 442 int err; 443 if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL) { 444 err = errno; 445 } else { 446 err = fmd_agent_page_isretired(hdl, nvl); 447 if (err == FMD_AGENT_RETIRE_DONE) 448 err = 0; 449 else 450 err = fmd_agent_errno(hdl); 451 fmd_agent_close(hdl); 452 } 453 return (err); 454 } 455 456 return (EINVAL); 457 } else { 458 /* Zeus is avail; use Zeus for status/retire */ 459 460 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 461 uint32_t cpuid; 462 463 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, 464 &cpuid) == 0) 465 ret = ldmsvcs_cpu_req_status(lhp, cpuid); 466 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 467 uint64_t pa; 468 469 if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, 470 &pa) == 0) 471 ret = ldmsvcs_mem_req_status(lhp, pa); 472 else 473 ret = EINVAL; 474 } 475 return (ret); 476 } 477 } 478 479 480 int 481 ldom_fmri_retire(ldom_hdl_t *lhp, nvlist_t *nvl) 482 { 483 char *name; 484 int ret = ENOTSUP; 485 486 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) 487 return (EINVAL); 488 489 /* 490 * ldom_ldmd_is_up can only be true if a pri can be obtained from ldmd. 491 */ 492 if (!ldom_ldmd_is_up) { 493 /* Zeus is unavail; use local routines for status/retire */ 494 495 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 496 processorid_t vid; 497 uint32_t cpuid; 498 499 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) 500 == 0 && (vid = cpu_phys2virt(lhp, cpuid)) != -1) 501 return (p_online(vid, P_FAULTED)); 502 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 503 fmd_agent_hdl_t *hdl; 504 int err; 505 if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL) { 506 err = errno; 507 } else { 508 err = fmd_agent_page_retire(hdl, nvl); 509 if (err == FMD_AGENT_RETIRE_DONE) 510 err = 0; 511 else 512 err = fmd_agent_errno(hdl); 513 fmd_agent_close(hdl); 514 } 515 return (err); 516 } 517 518 return (EINVAL); 519 } else { 520 /* Zeus is avail; use Zeus for status/retire */ 521 522 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 523 uint32_t cpuid; 524 525 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, 526 &cpuid) == 0) 527 ret = ldmsvcs_cpu_req_offline(lhp, cpuid); 528 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 529 uint64_t pa; 530 531 if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, 532 &pa) == 0) 533 ret = ldmsvcs_mem_req_retire(lhp, pa); 534 else 535 ret = EINVAL; 536 } 537 return (ret); 538 } 539 } 540 541 int 542 ldom_fmri_unretire(ldom_hdl_t *lhp, nvlist_t *nvl) 543 { 544 char *name; 545 int ret = ENOTSUP; 546 547 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) 548 return (EINVAL); 549 550 /* 551 * ldom_ldmd_is_up can only be true if a pri can be obtained from ldmd. 552 */ 553 if (!ldom_ldmd_is_up) { 554 /* Zeus is unavail; use local routines for status/retire */ 555 556 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 557 processorid_t vid; 558 uint32_t cpuid; 559 560 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) 561 == 0 && (vid = cpu_phys2virt(lhp, cpuid)) != -1) 562 return (p_online(vid, P_ONLINE)); 563 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 564 fmd_agent_hdl_t *hdl; 565 int err; 566 if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL) { 567 err = errno; 568 } else { 569 err = fmd_agent_page_unretire(hdl, nvl); 570 if (err == FMD_AGENT_RETIRE_DONE) 571 err = 0; 572 else 573 err = fmd_agent_errno(hdl); 574 fmd_agent_close(hdl); 575 } 576 return (err); 577 } 578 579 return (EINVAL); 580 } else { 581 /* Zeus is avail; use Zeus for status/retire */ 582 583 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 584 uint32_t cpuid; 585 586 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, 587 &cpuid) == 0) 588 ret = ldmsvcs_cpu_req_online(lhp, cpuid); 589 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 590 uint64_t pa; 591 592 if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, 593 &pa) == 0) 594 ret = ldmsvcs_mem_req_unretire(lhp, pa); 595 else 596 ret = EINVAL; 597 } 598 return (ret); 599 } 600 } 601 602 static int 603 fmri_blacklist(ldom_hdl_t *lhp, nvlist_t *nvl, int cmd) 604 { 605 char *name; 606 uint32_t type = 0; 607 608 if ((ldom_get_type(lhp, &type) != 0) || 609 ((type & LDOM_TYPE_LEGACY) == 0)) 610 return (0); 611 612 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) 613 return (EINVAL); 614 615 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 616 bl_req_t blr; 617 char *class; 618 int fd, rc, err; 619 620 if ((nvlist_lookup_string(nvl, FM_CLASS, &class) != 0) || 621 (class == NULL) || (*class == '\0')) 622 return (EINVAL); 623 624 if ((fd = open("/dev/bl", O_RDONLY)) < 0) 625 return (EIO); 626 627 if (nvlist_size(nvl, &blr.bl_fmrisz, NV_ENCODE_NATIVE) != 0 || 628 blr.bl_fmrisz == 0 || 629 (blr.bl_fmri = (caddr_t)lhp->allocp(blr.bl_fmrisz)) == 630 NULL) { 631 (void) close(fd); 632 return (EINVAL); 633 } 634 635 blr.bl_class = class; 636 637 rc = ioctl(fd, cmd, &blr); 638 err = errno; 639 640 lhp->freep((void *)&blr.bl_fmri, blr.bl_fmrisz); 641 (void) close(fd); 642 643 if (rc < 0 && err != ENOTSUP) { 644 errno = err; 645 return (-1); 646 } 647 } 648 649 return (0); 650 } 651 652 /* 653 * blacklist cpus in a non-LDOMS environment 654 */ 655 int 656 ldom_fmri_blacklist(ldom_hdl_t *lhp, nvlist_t *nvl) 657 { 658 return (fmri_blacklist(lhp, nvl, BLIOC_INSERT)); 659 } 660 661 /* 662 * unblacklist cpus 663 */ 664 int 665 ldom_fmri_unblacklist(ldom_hdl_t *lhp, nvlist_t *nvl) 666 { 667 return (fmri_blacklist(lhp, nvl, BLIOC_DELETE)); 668 } 669 670 671 ssize_t 672 ldom_get_local_md(ldom_hdl_t *lhp, uint64_t **buf) 673 { 674 return (get_local_core_md(lhp, buf)); 675 } 676 677 ssize_t 678 ldom_get_core_md(ldom_hdl_t *lhp, uint64_t **buf) 679 { 680 ssize_t rv; /* return value */ 681 uint64_t tok; /* opaque PRI token */ 682 uint32_t type = 0; 683 684 if (ldom_get_type(lhp, &type) != 0) { 685 return (-1); 686 } 687 688 if ((type & LDOM_TYPE_CONTROL) != 0) { 689 /* Get the pri from Zeus first. If failed, get it from libpri */ 690 if ((rv = ldmsvcs_get_core_md(lhp, buf)) < 1) { 691 (void) pthread_mutex_lock(&ldom_pri_lock); 692 rv = ldom_pri_get(PRI_GET, &tok, 693 buf, lhp->allocp, lhp->freep); 694 (void) pthread_mutex_unlock(&ldom_pri_lock); 695 } else { 696 ldom_ldmd_is_up = 1; 697 xmpp_start(); 698 } 699 } else { 700 /* get the pruned PRI from the libpri */ 701 (void) pthread_mutex_lock(&ldom_pri_lock); 702 rv = ldom_pri_get(PRI_GET, &tok, buf, lhp->allocp, lhp->freep); 703 (void) pthread_mutex_unlock(&ldom_pri_lock); 704 } 705 706 return (rv); 707 } 708 709 int 710 ldom_find_id(ldom_hdl_t *lhp, uint64_t addr, ldom_rsrc_t rsrc, 711 uint64_t *virt_addr, char *name, int name_size, uint64_t *did) 712 { 713 uint32_t type = 0; 714 715 (void) ldom_get_type(lhp, &type); 716 if ((type & LDOM_TYPE_CONTROL) == 0) { 717 return (ENOTSUP); 718 } 719 if (!ldom_ldmd_is_up) { 720 return (EAGAIN); 721 } 722 return (ldmsvcs_io_req_id(lhp, addr, rsrc, virt_addr, 723 name, name_size, did)); 724 } 725 726 int 727 ldom_register_event(ldom_hdl_t *lhp, ldom_reg_cb_t cb, ldom_cb_arg_t data) 728 { 729 uint32_t type = 0; 730 731 (void) ldom_get_type(lhp, &type); 732 if ((type & LDOM_TYPE_CONTROL) == 0) { 733 return (ENOTSUP); 734 } 735 736 return (xmpp_add_client(lhp, cb, data)); 737 } 738 739 int 740 ldom_unregister_event(ldom_hdl_t *lhp) 741 { 742 uint32_t type = 0; 743 744 (void) ldom_get_type(lhp, &type); 745 if ((type & LDOM_TYPE_CONTROL) == 0) { 746 return (ENOTSUP); 747 } 748 749 return (xmpp_remove_client(lhp)); 750 } 751 752 /* 753 * ldom_init() 754 * Description: 755 * Return a libldom handle to the caller for uniquely identify the session 756 * betweem the caller and the libldom.so. The handle is used in 757 * subsequent calls into the libldom.so 758 * 759 * If the caller does not provide a alloc()/free(), the libldom uses its 760 * own functions. 761 */ 762 ldom_hdl_t * 763 ldom_init(void *(*allocp)(size_t size), 764 void (*freep)(void *addr, size_t size)) 765 { 766 struct ldom_hdl *lhp; 767 768 if (allocp == NULL && freep == NULL) { 769 allocp = ldom_alloc; 770 freep = ldom_free; 771 } else if (allocp == NULL || freep == NULL) { 772 /* missing alloc or free functions */ 773 return (NULL); 774 } 775 776 (void) pthread_mutex_lock(&ldom_pri_lock); 777 778 if (ldom_pri_init() < 0) { 779 (void) pthread_mutex_unlock(&ldom_pri_lock); 780 return (NULL); 781 } 782 783 if ((lhp = allocp(sizeof (struct ldom_hdl))) == NULL) { 784 ldom_pri_fini(); 785 (void) pthread_mutex_unlock(&ldom_pri_lock); 786 return (NULL); 787 } 788 789 (void) pthread_mutex_unlock(&ldom_pri_lock); 790 791 lhp->allocp = allocp; 792 lhp->freep = freep; 793 794 ldmsvcs_init(lhp); 795 796 return (lhp); 797 } 798 799 800 void 801 ldom_fini(ldom_hdl_t *lhp) 802 { 803 if (lhp == NULL) 804 return; 805 806 (void) xmpp_remove_client(lhp); 807 ldmsvcs_fini(lhp); 808 lhp->freep(lhp, sizeof (struct ldom_hdl)); 809 810 (void) pthread_mutex_lock(&ldom_pri_lock); 811 812 ldom_pri_fini(); 813 814 (void) pthread_mutex_unlock(&ldom_pri_lock); 815 } 816 817 /* end file */ 818