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
ldom_pri_config(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
ldom_pri_unconfig(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
ldom_pri_init(void)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
ldom_pri_fini(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
ldom_pri_get(uint8_t wait,uint64_t * token,uint64_t ** buf,void * (* allocp)(size_t),void (* freep)(void *,size_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
get_local_core_md(ldom_hdl_t * lhp,uint64_t ** buf)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
get_local_md_prop_value(ldom_hdl_t * lhp,char * node,char * prop,uint64_t * val)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
cpu_phys2virt(ldom_hdl_t * lhp,uint32_t cpuid)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
get_type(ldom_hdl_t * lhp,uint32_t * type)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
ldom_get_type(ldom_hdl_t * lhp,uint32_t * type)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
ldom_fmri_status(ldom_hdl_t * lhp,nvlist_t * nvl)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
ldom_fmri_retire(ldom_hdl_t * lhp,nvlist_t * nvl)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
ldom_fmri_unretire(ldom_hdl_t * lhp,nvlist_t * nvl)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
fmri_blacklist(ldom_hdl_t * lhp,nvlist_t * nvl,int cmd)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
ldom_fmri_blacklist(ldom_hdl_t * lhp,nvlist_t * nvl)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
ldom_fmri_unblacklist(ldom_hdl_t * lhp,nvlist_t * nvl)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
ldom_get_local_md(ldom_hdl_t * lhp,uint64_t ** buf)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
ldom_get_core_md(ldom_hdl_t * lhp,uint64_t ** buf)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
ldom_find_id(ldom_hdl_t * lhp,uint64_t addr,ldom_rsrc_t rsrc,uint64_t * virt_addr,char * name,int name_size,uint64_t * did)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
ldom_register_event(ldom_hdl_t * lhp,ldom_reg_cb_t cb,ldom_cb_arg_t data)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
ldom_unregister_event(ldom_hdl_t * lhp)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 *
ldom_init(void * (* allocp)(size_t size),void (* freep)(void * addr,size_t size))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
ldom_fini(ldom_hdl_t * lhp)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