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 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <unistd.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <fcntl.h> 33 #include <pthread.h> 34 #include <errno.h> 35 #include <libnvpair.h> 36 #include <dlfcn.h> 37 #include <link.h> 38 #include <assert.h> 39 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 <sys/pri.h> 50 51 #include "ldom.h" 52 #include "ldmsvcs_utils.h" 53 54 #define MD_STR_PLATFORM "platform" 55 #define MD_STR_DOM_CAPABLE "domaining-enabled" 56 57 static int ldom_ldmd_is_up = 0; /* assume stays up if ever seen up */ 58 59 static void *ldom_dl_hp = (void *)NULL; 60 static const char *ldom_dl_path = "libpri.so.1"; 61 static int ldom_dl_mode = (RTLD_NOW | RTLD_LOCAL); 62 63 static pthread_mutex_t ldom_pri_lock = PTHREAD_MUTEX_INITIALIZER; 64 static int ldom_pri_ref_cnt = 0; /* num of outstanding ldom_pri_init()s */ 65 static int ldom_pri_init_done = 0; /* bool for real pri_init() done */ 66 static int (*ldom_pri_fp_init)(void) = (int (*)(void))NULL; 67 static void (*ldom_pri_fp_fini)(void) = (void (*)(void))NULL; 68 static ssize_t (*ldom_pri_fp_get)(uint8_t wait, uint64_t *token, uint64_t **buf, 69 void *(*allocp)(size_t), void (*freep)(void *, size_t)) = 70 (ssize_t (*)(uint8_t wait, uint64_t *token, uint64_t **buf, 71 void *(*allocp)(size_t), void (*freep)(void *, size_t)))NULL; 72 73 static void 74 ldom_pri_config(void) 75 { 76 char isa[MAXNAMELEN]; /* used to see if machine is sun4v */ 77 78 if (sysinfo(SI_MACHINE, isa, MAXNAMELEN) < 0) 79 return; 80 if (strcmp(isa, "sun4v") != 0) 81 return; 82 if ((ldom_dl_hp = dlopen(ldom_dl_path, ldom_dl_mode)) == NULL) 83 return; 84 85 ldom_pri_fp_init = (int (*)(void))dlsym(ldom_dl_hp, "pri_init"); 86 ldom_pri_fp_fini = (void (*)(void))dlsym(ldom_dl_hp, "pri_fini"); 87 ldom_pri_fp_get = (ssize_t (*)(uint8_t wait, uint64_t *token, 88 uint64_t **buf, void *(*allocp)(size_t), 89 void (*freep)(void *, size_t)))dlsym(ldom_dl_hp, "pri_get"); 90 } 91 92 static void 93 ldom_pri_unconfig(void) 94 { 95 if (ldom_dl_hp == NULL) 96 return; 97 98 ldom_pri_fp_init = (int (*)(void))NULL; 99 ldom_pri_fp_fini = (void (*)(void))NULL; 100 ldom_pri_fp_get = (ssize_t (*)(uint8_t wait, uint64_t *token, 101 uint64_t **buf, void *(*allocp)(size_t), 102 void (*freep)(void *, size_t)))NULL; 103 (void) dlclose(ldom_dl_hp); 104 ldom_dl_hp = (void *)NULL; 105 } 106 107 /* 108 * ldom_pri_lock is assumed already held by anyone accessing ldom_pri_ref_cnt 109 */ 110 111 static int 112 ldom_pri_init(void) 113 { 114 if (ldom_pri_ref_cnt == 0) { 115 ldom_pri_config(); 116 /* 117 * ldom_pri_init() is called before we know whether we 118 * have LDOMS FW or not; defer calling pri_init() via 119 * ldom_pri_fp_init until the first time we try to 120 * actually get a PRI 121 */ 122 } 123 ldom_pri_ref_cnt++; 124 125 assert(ldom_pri_ref_cnt > 0); 126 127 return (0); 128 } 129 130 static void 131 ldom_pri_fini(void) 132 { 133 assert(ldom_pri_ref_cnt > 0); 134 135 ldom_pri_ref_cnt--; 136 if (ldom_pri_ref_cnt == 0) { 137 if (ldom_pri_init_done && (ldom_pri_fp_fini != NULL)) { 138 (*ldom_pri_fp_fini)(); 139 ldom_pri_init_done = 0; 140 } 141 ldom_pri_unconfig(); 142 } 143 } 144 145 static ssize_t 146 ldom_pri_get(uint8_t wait, uint64_t *token, uint64_t **buf, 147 void *(*allocp)(size_t), void (*freep)(void *, size_t)) 148 { 149 assert(ldom_pri_ref_cnt > 0); 150 151 if ((!ldom_pri_init_done) && (ldom_pri_fp_init != NULL)) { 152 if ((*ldom_pri_fp_init)() < 0) 153 return (-1); 154 ldom_pri_init_done = 1; 155 } 156 157 if (ldom_pri_fp_get != NULL) 158 return ((*ldom_pri_fp_get)(wait, token, buf, allocp, freep)); 159 else 160 return (-1); 161 } 162 163 static ssize_t 164 get_local_core_md(ldom_hdl_t *lhp, uint64_t **buf) 165 { 166 int fh; 167 size_t size; 168 uint64_t *bufp; 169 170 if ((fh = open("/devices/pseudo/mdesc@0:mdesc", O_RDONLY, 0)) < 0) 171 return (-1); 172 173 if (ioctl(fh, MDESCIOCGSZ, &size) < 0) { 174 (void) close(fh); 175 return (-1); 176 } 177 178 bufp = (uint64_t *)lhp->allocp(size); 179 180 if (read(fh, bufp, size) < 0) { 181 lhp->freep(bufp, size); 182 (void) close(fh); 183 return (-1); 184 } 185 (void) close(fh); 186 187 *buf = bufp; 188 189 return ((ssize_t)size); 190 } 191 192 193 static int 194 get_local_md_prop_value(ldom_hdl_t *lhp, char *node, char *prop, uint64_t *val) 195 { 196 int rc = 1; 197 uint64_t *bufp; 198 ssize_t bufsiz; 199 200 if ((bufsiz = get_local_core_md(lhp, &bufp)) > 0) { 201 md_t *mdp; 202 203 if (mdp = md_init_intern(bufp, lhp->allocp, lhp->freep)) { 204 int num_nodes; 205 mde_cookie_t *listp; 206 207 num_nodes = md_node_count(mdp); 208 listp = lhp->allocp(sizeof (mde_cookie_t) * num_nodes); 209 210 if (md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, 211 md_find_name(mdp, node), 212 md_find_name(mdp, "fwd"), listp) > 0 && 213 md_get_prop_val(mdp, listp[0], prop, val) >= 0) { 214 /* found the property */ 215 rc = 0; 216 } 217 218 lhp->freep(listp, sizeof (mde_cookie_t) * num_nodes); 219 (void) md_fini(mdp); 220 } 221 lhp->freep(bufp, bufsiz); 222 } 223 return (rc); 224 } 225 226 static int 227 ldom_getinfo(struct ldom_hdl *lhp) 228 { 229 static pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER; 230 static pthread_cond_t cv = PTHREAD_COND_INITIALIZER; 231 static int major_version = -1; 232 static int service_ldom = -1; 233 static int busy_init = 0; 234 235 int ier, rc = 0; 236 uint64_t domain_capable; 237 238 (void) pthread_mutex_lock(&mt); 239 240 while (busy_init == 1) 241 (void) pthread_cond_wait(&cv, &mt); 242 243 if (major_version != -1 && service_ldom != -1) { 244 lhp->major_version = major_version; 245 lhp->service_ldom = service_ldom; 246 (void) pthread_mutex_unlock(&mt); 247 return (0); 248 } 249 250 /* 251 * get to this point if major_version and service_ldom have not yet 252 * been determined 253 */ 254 busy_init = 1; 255 (void) pthread_mutex_unlock(&mt); 256 257 /* 258 * set defaults which correspond to the case of "LDOMS not 259 * available". note that these can (and will) also apply to 260 * non-sun4v machines. 261 */ 262 major_version = 0; 263 service_ldom = 0; 264 265 if (get_local_md_prop_value(lhp, MD_STR_PLATFORM, MD_STR_DOM_CAPABLE, 266 &domain_capable) == 0) { 267 268 /* 269 * LDOMS capable FW is installed; it should be ok to 270 * try to communicate with ldmd and if that fails/timesout 271 * then use libpri 272 */ 273 major_version = 1; 274 275 if ((ier = ldmsvcs_check_channel()) == 0) { 276 /* 277 * control ldom 278 * ldmfma channel between FMA and ldmd only exists 279 * on the control domain. 280 */ 281 service_ldom = 1; 282 } else if (ier == 1) { 283 /* 284 * guest ldom 285 * non-control ldom such as guest and io service ldom 286 */ 287 service_ldom = 0; 288 } 289 } 290 291 (void) pthread_mutex_lock(&mt); 292 lhp->major_version = major_version; 293 lhp->service_ldom = service_ldom; 294 busy_init = 0; 295 (void) pthread_mutex_unlock(&mt); 296 297 (void) pthread_cond_broadcast(&cv); 298 299 return (rc); 300 } 301 302 303 /* 304 * search the machine description for a "pid" entry (physical cpuid) and 305 * return the corresponding "id" entry (virtual cpuid). 306 * return -1 if not found. 307 * if the pid property does not exist in a cpu node, assume pid = id. 308 */ 309 static processorid_t 310 cpu_phys2virt(ldom_hdl_t *lhp, uint32_t cpuid) 311 { 312 char isa[MAXNAMELEN]; 313 md_t *mdp; 314 mde_cookie_t *listp; 315 ssize_t bufsize; 316 processorid_t vid; 317 uint64_t *bufp; 318 uint64_t pval, pid, id; 319 int num_nodes, ncpus, i; 320 321 (void) sysinfo(SI_MACHINE, isa, MAXNAMELEN); 322 323 if (strcmp(isa, "sun4v") != 0) 324 return ((processorid_t)cpuid); 325 326 /* 327 * convert the physical cpuid to a virtual cpuid 328 */ 329 if ((bufsize = get_local_core_md(lhp, &bufp)) < 1) 330 return (-1); 331 332 if ((mdp = md_init_intern(bufp, lhp->allocp, lhp->freep)) == NULL || 333 (num_nodes = md_node_count(mdp)) < 1) { 334 lhp->freep(bufp, bufsize); 335 return (-1); 336 } 337 338 listp = (mde_cookie_t *)lhp->allocp(sizeof (mde_cookie_t) * num_nodes); 339 ncpus = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, 340 md_find_name(mdp, "cpu"), md_find_name(mdp, "fwd"), listp); 341 342 vid = -1; 343 for (i = 0; i < ncpus; i++) { 344 if (md_get_prop_val(mdp, listp[i], "id", &pval) < 0) 345 pval = (uint64_t)-1; 346 id = pval; 347 348 /* if pid does not exist, assume pid=id */ 349 if (md_get_prop_val(mdp, listp[i], "pid", &pval) < 0) 350 pval = id; 351 pid = pval; 352 353 if (pid == (uint64_t)cpuid) { 354 /* Found the entry */ 355 vid = (processorid_t)id; 356 break; 357 } 358 } 359 360 lhp->freep(listp, sizeof (mde_cookie_t) * num_nodes); 361 (void) md_fini(mdp); 362 lhp->freep(bufp, bufsize); 363 364 return (vid); 365 } 366 367 /* 368 * if checking for status of a retired page: 369 * 0 - page is retired 370 * EAGAIN - page is scheduled for retirement 371 * EIO - page not scheduled for retirement 372 * EINVAL - error 373 * 374 * if retiring a page: 375 * 0 - success in retiring page 376 * EIO - page is already retired 377 * EAGAIN - page is scheduled for retirement 378 * EINVAL - error 379 * 380 * the original decoder for ioctl() return values is 381 * http://fma.eng/documents/engineering/cpumem/page_retire_api.txt 382 */ 383 static int 384 os_mem_page_retire(ldom_hdl_t *lhp, int cmd, nvlist_t *nvl) 385 { 386 mem_page_t mpage; 387 char *fmribuf; 388 size_t fmrisz; 389 int fd, rc, err; 390 391 if (cmd != MEM_PAGE_RETIRE && cmd != MEM_PAGE_FMRI_RETIRE && 392 cmd != MEM_PAGE_ISRETIRED && cmd != MEM_PAGE_FMRI_ISRETIRED && 393 cmd != MEM_PAGE_UNRETIRE && cmd != MEM_PAGE_FMRI_UNRETIRE) 394 return (EINVAL); 395 396 if ((fd = open("/dev/mem", O_RDONLY)) < 0) 397 return (EINVAL); 398 399 if ((errno = nvlist_size(nvl, &fmrisz, NV_ENCODE_NATIVE)) != 0 || 400 fmrisz > MEM_FMRI_MAX_BUFSIZE || 401 (fmribuf = lhp->allocp(fmrisz)) == NULL) { 402 (void) close(fd); 403 return (EINVAL); 404 } 405 406 if ((errno = nvlist_pack(nvl, &fmribuf, &fmrisz, 407 NV_ENCODE_NATIVE, 0)) != 0) { 408 lhp->freep(fmribuf, fmrisz); 409 (void) close(fd); 410 return (EINVAL); 411 } 412 413 mpage.m_fmri = fmribuf; 414 mpage.m_fmrisz = fmrisz; 415 416 rc = ioctl(fd, cmd, &mpage); 417 err = errno; 418 419 lhp->freep(fmribuf, fmrisz); 420 (void) close(fd); 421 422 if (rc < 0) { 423 rc = err; 424 } 425 426 return (rc); 427 } 428 429 430 int 431 ldom_fmri_status(ldom_hdl_t *lhp, nvlist_t *nvl) 432 { 433 char *name; 434 int ret = ENOTSUP; 435 436 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) 437 return (EINVAL); 438 439 /* 440 * ldom_ldmd_is_up can only be true if ldom_major_version() 441 * returned 1 earlier; the major version is constant for the 442 * life of the client process 443 */ 444 445 if (!ldom_ldmd_is_up) { 446 /* Zeus is unavail; use local routines for status/retire */ 447 448 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 449 processorid_t vid; 450 uint32_t cpuid; 451 452 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) 453 == 0 && (vid = cpu_phys2virt(lhp, cpuid)) != -1) 454 return (p_online(vid, P_STATUS)); 455 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 456 return (os_mem_page_retire(lhp, 457 MEM_PAGE_FMRI_ISRETIRED, nvl)); 458 } 459 460 return (EINVAL); 461 } else { 462 /* Zeus is avail; use Zeus for status/retire */ 463 464 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 465 uint32_t cpuid; 466 467 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, 468 &cpuid) == 0) 469 ret = ldmsvcs_cpu_req_status(lhp, cpuid); 470 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 471 uint64_t pa; 472 473 if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, 474 &pa) == 0) 475 ret = ldmsvcs_mem_req_status(lhp, pa); 476 else 477 ret = EINVAL; 478 } 479 return (ret); 480 } 481 } 482 483 484 int 485 ldom_fmri_retire(ldom_hdl_t *lhp, nvlist_t *nvl) 486 { 487 char *name; 488 int ret = ENOTSUP; 489 490 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) 491 return (EINVAL); 492 493 /* 494 * ldom_ldmd_is_up can only be true if ldom_major_version() 495 * returned 1 earlier; the major version is constant for the 496 * life of the client process 497 */ 498 499 if (!ldom_ldmd_is_up) { 500 /* Zeus is unavail; use local routines for status/retire */ 501 502 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 503 processorid_t vid; 504 uint32_t cpuid; 505 506 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) 507 == 0 && (vid = cpu_phys2virt(lhp, cpuid)) != -1) 508 return (p_online(vid, P_FAULTED)); 509 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 510 return (os_mem_page_retire(lhp, 511 MEM_PAGE_FMRI_RETIRE, nvl)); 512 } 513 514 return (EINVAL); 515 } else { 516 /* Zeus is avail; use Zeus for status/retire */ 517 518 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 519 uint32_t cpuid; 520 521 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, 522 &cpuid) == 0) 523 ret = ldmsvcs_cpu_req_offline(lhp, cpuid); 524 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 525 uint64_t pa; 526 527 if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, 528 &pa) == 0) 529 ret = ldmsvcs_mem_req_retire(lhp, pa); 530 else 531 ret = EINVAL; 532 } 533 return (ret); 534 } 535 } 536 537 int 538 ldom_fmri_unretire(ldom_hdl_t *lhp, nvlist_t *nvl) 539 { 540 char *name; 541 int ret = ENOTSUP; 542 543 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) 544 return (EINVAL); 545 546 /* 547 * ldom_ldmd_is_up can only be true if ldom_major_version() 548 * returned 1 earlier; the major version is constant for the 549 * life of the client process 550 */ 551 552 if (!ldom_ldmd_is_up) { 553 /* Zeus is unavail; use local routines for status/retire */ 554 555 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 556 processorid_t vid; 557 uint32_t cpuid; 558 559 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) 560 == 0 && (vid = cpu_phys2virt(lhp, cpuid)) != -1) 561 return (p_online(vid, P_ONLINE)); 562 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 563 return (os_mem_page_retire(lhp, 564 MEM_PAGE_FMRI_UNRETIRE, nvl)); 565 } 566 567 return (EINVAL); 568 } else { 569 /* Zeus is avail; use Zeus for status/retire */ 570 571 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 572 uint32_t cpuid; 573 574 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, 575 &cpuid) == 0) 576 ret = ldmsvcs_cpu_req_online(lhp, cpuid); 577 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 578 uint64_t pa; 579 580 if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, 581 &pa) == 0) 582 ret = ldmsvcs_mem_req_unretire(lhp, pa); 583 else 584 ret = EINVAL; 585 } 586 return (ret); 587 } 588 } 589 590 static int 591 fmri_blacklist(ldom_hdl_t *lhp, nvlist_t *nvl, int cmd) 592 { 593 char *name; 594 595 if (ldom_major_version(lhp) != 0) 596 return (0); 597 598 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) 599 return (EINVAL); 600 601 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 602 bl_req_t blr; 603 char *class; 604 int fd, rc, err; 605 606 if ((nvlist_lookup_string(nvl, FM_CLASS, &class) != 0) || 607 (class == NULL) || (*class == '\0')) 608 return (EINVAL); 609 610 if ((fd = open("/dev/bl", O_RDONLY)) < 0) 611 return (EIO); 612 613 if (nvlist_size(nvl, &blr.bl_fmrisz, NV_ENCODE_NATIVE) != 0 || 614 blr.bl_fmrisz == 0 || 615 (blr.bl_fmri = (caddr_t)lhp->allocp(blr.bl_fmrisz)) == 616 NULL) { 617 (void) close(fd); 618 return (EINVAL); 619 } 620 621 blr.bl_class = class; 622 623 rc = ioctl(fd, cmd, &blr); 624 err = errno; 625 626 lhp->freep((void *)&blr.bl_fmri, blr.bl_fmrisz); 627 (void) close(fd); 628 629 if (rc < 0 && err != ENOTSUP) { 630 errno = err; 631 return (-1); 632 } 633 } 634 635 return (0); 636 } 637 638 /* 639 * blacklist cpus in a non-LDOMS environment 640 */ 641 int 642 ldom_fmri_blacklist(ldom_hdl_t *lhp, nvlist_t *nvl) 643 { 644 return (fmri_blacklist(lhp, nvl, BLIOC_INSERT)); 645 } 646 647 /* 648 * unblacklist cpus 649 */ 650 int 651 ldom_fmri_unblacklist(ldom_hdl_t *lhp, nvlist_t *nvl) 652 { 653 return (fmri_blacklist(lhp, nvl, BLIOC_DELETE)); 654 } 655 656 657 ssize_t 658 ldom_get_core_md(ldom_hdl_t *lhp, uint64_t **buf) 659 { 660 ssize_t rv; /* return value */ 661 uint64_t tok; /* opaque PRI token */ 662 663 switch (ldom_major_version(lhp)) { 664 case 0: 665 /* pre LDOMS */ 666 rv = get_local_core_md(lhp, buf); 667 break; 668 case 1: 669 /* LDOMS 1.0 - Zeus and libpri usable only on service dom */ 670 if (ldom_on_service(lhp) == 1) { 671 if ((rv = ldmsvcs_get_core_md(lhp, buf)) < 1) { 672 (void) pthread_mutex_lock(&ldom_pri_lock); 673 rv = ldom_pri_get(PRI_GET, &tok, 674 buf, lhp->allocp, lhp->freep); 675 (void) pthread_mutex_unlock(&ldom_pri_lock); 676 } else { 677 ldom_ldmd_is_up = 1; 678 } 679 } else { 680 rv = get_local_core_md(lhp, buf); 681 } 682 break; 683 default: 684 rv = -1; 685 break; 686 } 687 688 return (rv); 689 } 690 691 /* 692 * version 0 means no LDOMS 693 */ 694 int 695 ldom_major_version(ldom_hdl_t *lhp) 696 { 697 if (lhp == NULL) 698 return (-1); 699 700 if (ldom_getinfo(lhp) == 0) 701 return (lhp->major_version); 702 else 703 return (0); 704 } 705 706 /* 707 * in the absence of ldoms we are on a single OS instance which is the 708 * equivalent of the service ldom 709 */ 710 int 711 ldom_on_service(ldom_hdl_t *lhp) 712 { 713 if (lhp == NULL) 714 return (-1); 715 716 if (ldom_getinfo(lhp) == 0) 717 return (lhp->service_ldom); 718 else 719 return (1); 720 } 721 722 723 ldom_hdl_t * 724 ldom_init(void *(*allocp)(size_t size), 725 void (*freep)(void *addr, size_t size)) 726 { 727 struct ldom_hdl *lhp; 728 729 (void) pthread_mutex_lock(&ldom_pri_lock); 730 731 if (ldom_pri_init() < 0) { 732 (void) pthread_mutex_unlock(&ldom_pri_lock); 733 return (NULL); 734 } 735 736 if ((lhp = allocp(sizeof (struct ldom_hdl))) == NULL) { 737 ldom_pri_fini(); 738 (void) pthread_mutex_unlock(&ldom_pri_lock); 739 return (NULL); 740 } 741 742 (void) pthread_mutex_unlock(&ldom_pri_lock); 743 744 lhp->major_version = -1; /* version not yet determined */ 745 lhp->allocp = allocp; 746 lhp->freep = freep; 747 748 ldmsvcs_init(lhp); 749 750 return (lhp); 751 } 752 753 754 void 755 ldom_fini(ldom_hdl_t *lhp) 756 { 757 if (lhp == NULL) 758 return; 759 760 ldmsvcs_fini(lhp); 761 lhp->freep(lhp, sizeof (struct ldom_hdl)); 762 763 (void) pthread_mutex_lock(&ldom_pri_lock); 764 765 ldom_pri_fini(); 766 767 (void) pthread_mutex_unlock(&ldom_pri_lock); 768 } 769 770 /* end file */ 771