131e37bb4Svn83148 /*
231e37bb4Svn83148 * CDDL HEADER START
331e37bb4Svn83148 *
431e37bb4Svn83148 * The contents of this file are subject to the terms of the
531e37bb4Svn83148 * Common Development and Distribution License (the "License").
631e37bb4Svn83148 * You may not use this file except in compliance with the License.
731e37bb4Svn83148 *
831e37bb4Svn83148 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
931e37bb4Svn83148 * or http://www.opensolaris.org/os/licensing.
1031e37bb4Svn83148 * See the License for the specific language governing permissions
1131e37bb4Svn83148 * and limitations under the License.
1231e37bb4Svn83148 *
1331e37bb4Svn83148 * When distributing Covered Code, include this CDDL HEADER in each
1431e37bb4Svn83148 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1531e37bb4Svn83148 * If applicable, add the following below this CDDL HEADER, with the
1631e37bb4Svn83148 * fields enclosed by brackets "[]" replaced with your own identifying
1731e37bb4Svn83148 * information: Portions Copyright [yyyy] [name of copyright owner]
1831e37bb4Svn83148 *
1931e37bb4Svn83148 * CDDL HEADER END
2031e37bb4Svn83148 */
2131e37bb4Svn83148 /*
225f149bcaScy152378 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2331e37bb4Svn83148 * Use is subject to license terms.
2431e37bb4Svn83148 */
2531e37bb4Svn83148
2631e37bb4Svn83148 #include <stdio.h>
2731e37bb4Svn83148 #include <unistd.h>
2831e37bb4Svn83148 #include <stdlib.h>
2931e37bb4Svn83148 #include <string.h>
3025351652SVuong Nguyen #include <strings.h>
3131e37bb4Svn83148 #include <fcntl.h>
3231e37bb4Svn83148 #include <pthread.h>
3331e37bb4Svn83148 #include <errno.h>
3431e37bb4Svn83148 #include <libnvpair.h>
35c94f2192Srb144127 #include <dlfcn.h>
36c94f2192Srb144127 #include <link.h>
37c3b50bc5Srb144127 #include <assert.h>
3831e37bb4Svn83148
3925351652SVuong Nguyen #include <fm/libtopo.h>
4031e37bb4Svn83148 #include <sys/processor.h>
4131e37bb4Svn83148 #include <sys/stat.h>
4231e37bb4Svn83148 #include <sys/mdesc.h>
4331e37bb4Svn83148 #include <sys/param.h>
4431e37bb4Svn83148 #include <sys/systeminfo.h>
4531e37bb4Svn83148 #include <sys/mem.h>
4631e37bb4Svn83148 #include <sys/bl.h>
4731e37bb4Svn83148 #include <sys/fm/protocol.h>
4831e37bb4Svn83148 #include <fm/fmd_fmri.h>
49e4b86885SCheng Sean Ye #include <fm/fmd_agent.h>
50ef884685Srb144127 #include <sys/pri.h>
5131e37bb4Svn83148
5231e37bb4Svn83148 #include "ldom.h"
5325351652SVuong Nguyen #include "ldom_alloc.h"
5431e37bb4Svn83148 #include "ldmsvcs_utils.h"
5525351652SVuong Nguyen #include "ldom_xmpp_client.h"
5631e37bb4Svn83148
57c37dbf9cSvn83148 #define MD_STR_PLATFORM "platform"
58c3b50bc5Srb144127 #define MD_STR_DOM_CAPABLE "domaining-enabled"
5925351652SVuong Nguyen #define MD_STR_IODEVICE "iodevice"
6025351652SVuong Nguyen #define MD_STR_NAME "name"
6125351652SVuong Nguyen #define MD_STR_DEVICE_TYPE "device-type"
6225351652SVuong Nguyen #define MD_STR_CFGHDL "cfg-handle"
6325351652SVuong Nguyen #define MD_STR_PCIEX "pciex"
6425351652SVuong Nguyen #define MD_STR_PCI "pci"
6525351652SVuong Nguyen #define MD_STR_NIU "niu"
66c3b50bc5Srb144127
67c3b50bc5Srb144127 static int ldom_ldmd_is_up = 0; /* assume stays up if ever seen up */
6831e37bb4Svn83148
69c94f2192Srb144127 static void *ldom_dl_hp = (void *)NULL;
70c94f2192Srb144127 static const char *ldom_dl_path = "libpri.so.1";
71c94f2192Srb144127 static int ldom_dl_mode = (RTLD_NOW | RTLD_LOCAL);
72c94f2192Srb144127
73c3b50bc5Srb144127 static pthread_mutex_t ldom_pri_lock = PTHREAD_MUTEX_INITIALIZER;
74c3b50bc5Srb144127 static int ldom_pri_ref_cnt = 0; /* num of outstanding ldom_pri_init()s */
75c3b50bc5Srb144127 static int ldom_pri_init_done = 0; /* bool for real pri_init() done */
76c3b50bc5Srb144127 static int (*ldom_pri_fp_init)(void) = (int (*)(void))NULL;
77c3b50bc5Srb144127 static void (*ldom_pri_fp_fini)(void) = (void (*)(void))NULL;
78c3b50bc5Srb144127 static ssize_t (*ldom_pri_fp_get)(uint8_t wait, uint64_t *token, uint64_t **buf,
79c94f2192Srb144127 void *(*allocp)(size_t), void (*freep)(void *, size_t)) =
80c94f2192Srb144127 (ssize_t (*)(uint8_t wait, uint64_t *token, uint64_t **buf,
81c94f2192Srb144127 void *(*allocp)(size_t), void (*freep)(void *, size_t)))NULL;
82c94f2192Srb144127
83c94f2192Srb144127 static void
ldom_pri_config(void)84c94f2192Srb144127 ldom_pri_config(void)
85c94f2192Srb144127 {
86c94f2192Srb144127 char isa[MAXNAMELEN]; /* used to see if machine is sun4v */
87c94f2192Srb144127
88c94f2192Srb144127 if (sysinfo(SI_MACHINE, isa, MAXNAMELEN) < 0)
89c94f2192Srb144127 return;
90c94f2192Srb144127 if (strcmp(isa, "sun4v") != 0)
91c94f2192Srb144127 return;
92c94f2192Srb144127 if ((ldom_dl_hp = dlopen(ldom_dl_path, ldom_dl_mode)) == NULL)
93c94f2192Srb144127 return;
94c94f2192Srb144127
95c3b50bc5Srb144127 ldom_pri_fp_init = (int (*)(void))dlsym(ldom_dl_hp, "pri_init");
96c3b50bc5Srb144127 ldom_pri_fp_fini = (void (*)(void))dlsym(ldom_dl_hp, "pri_fini");
97c3b50bc5Srb144127 ldom_pri_fp_get = (ssize_t (*)(uint8_t wait, uint64_t *token,
98c94f2192Srb144127 uint64_t **buf, void *(*allocp)(size_t),
99c94f2192Srb144127 void (*freep)(void *, size_t)))dlsym(ldom_dl_hp, "pri_get");
100c94f2192Srb144127 }
101c94f2192Srb144127
102c94f2192Srb144127 static void
ldom_pri_unconfig(void)103c94f2192Srb144127 ldom_pri_unconfig(void)
104c94f2192Srb144127 {
105c94f2192Srb144127 if (ldom_dl_hp == NULL)
106c94f2192Srb144127 return;
107c94f2192Srb144127
108c3b50bc5Srb144127 ldom_pri_fp_init = (int (*)(void))NULL;
109c3b50bc5Srb144127 ldom_pri_fp_fini = (void (*)(void))NULL;
110c3b50bc5Srb144127 ldom_pri_fp_get = (ssize_t (*)(uint8_t wait, uint64_t *token,
111c94f2192Srb144127 uint64_t **buf, void *(*allocp)(size_t),
112c94f2192Srb144127 void (*freep)(void *, size_t)))NULL;
113c94f2192Srb144127 (void) dlclose(ldom_dl_hp);
114c94f2192Srb144127 ldom_dl_hp = (void *)NULL;
115c94f2192Srb144127 }
116c94f2192Srb144127
117c3b50bc5Srb144127 /*
118c3b50bc5Srb144127 * ldom_pri_lock is assumed already held by anyone accessing ldom_pri_ref_cnt
119c3b50bc5Srb144127 */
120c3b50bc5Srb144127
121c3b50bc5Srb144127 static int
ldom_pri_init(void)122c3b50bc5Srb144127 ldom_pri_init(void)
123c3b50bc5Srb144127 {
124c3b50bc5Srb144127 if (ldom_pri_ref_cnt == 0) {
125c3b50bc5Srb144127 ldom_pri_config();
126c3b50bc5Srb144127 /*
127c3b50bc5Srb144127 * ldom_pri_init() is called before we know whether we
128c3b50bc5Srb144127 * have LDOMS FW or not; defer calling pri_init() via
129c3b50bc5Srb144127 * ldom_pri_fp_init until the first time we try to
130c3b50bc5Srb144127 * actually get a PRI
131c3b50bc5Srb144127 */
132c3b50bc5Srb144127 }
133c3b50bc5Srb144127 ldom_pri_ref_cnt++;
134c3b50bc5Srb144127
135c3b50bc5Srb144127 assert(ldom_pri_ref_cnt > 0);
136c3b50bc5Srb144127
137c3b50bc5Srb144127 return (0);
138c3b50bc5Srb144127 }
139c3b50bc5Srb144127
140c3b50bc5Srb144127 static void
ldom_pri_fini(void)141c3b50bc5Srb144127 ldom_pri_fini(void)
142c3b50bc5Srb144127 {
143c3b50bc5Srb144127 assert(ldom_pri_ref_cnt > 0);
144c3b50bc5Srb144127
145c3b50bc5Srb144127 ldom_pri_ref_cnt--;
146c3b50bc5Srb144127 if (ldom_pri_ref_cnt == 0) {
147c3b50bc5Srb144127 if (ldom_pri_init_done && (ldom_pri_fp_fini != NULL)) {
148c3b50bc5Srb144127 (*ldom_pri_fp_fini)();
149c3b50bc5Srb144127 ldom_pri_init_done = 0;
150c3b50bc5Srb144127 }
151c3b50bc5Srb144127 ldom_pri_unconfig();
152c3b50bc5Srb144127 }
153c3b50bc5Srb144127 }
154c3b50bc5Srb144127
155c3b50bc5Srb144127 static ssize_t
ldom_pri_get(uint8_t wait,uint64_t * token,uint64_t ** buf,void * (* allocp)(size_t),void (* freep)(void *,size_t))156c3b50bc5Srb144127 ldom_pri_get(uint8_t wait, uint64_t *token, uint64_t **buf,
157c3b50bc5Srb144127 void *(*allocp)(size_t), void (*freep)(void *, size_t))
158c3b50bc5Srb144127 {
159c3b50bc5Srb144127 assert(ldom_pri_ref_cnt > 0);
160c3b50bc5Srb144127
161c3b50bc5Srb144127 if ((!ldom_pri_init_done) && (ldom_pri_fp_init != NULL)) {
162c3b50bc5Srb144127 if ((*ldom_pri_fp_init)() < 0)
163c3b50bc5Srb144127 return (-1);
164c3b50bc5Srb144127 ldom_pri_init_done = 1;
165c3b50bc5Srb144127 }
166c3b50bc5Srb144127
167c3b50bc5Srb144127 if (ldom_pri_fp_get != NULL)
168c3b50bc5Srb144127 return ((*ldom_pri_fp_get)(wait, token, buf, allocp, freep));
169c3b50bc5Srb144127 else
170c3b50bc5Srb144127 return (-1);
171c3b50bc5Srb144127 }
172c3b50bc5Srb144127
17331e37bb4Svn83148 static ssize_t
get_local_core_md(ldom_hdl_t * lhp,uint64_t ** buf)17431e37bb4Svn83148 get_local_core_md(ldom_hdl_t *lhp, uint64_t **buf)
17531e37bb4Svn83148 {
17631e37bb4Svn83148 int fh;
17731e37bb4Svn83148 size_t size;
17831e37bb4Svn83148 uint64_t *bufp;
17931e37bb4Svn83148
18031e37bb4Svn83148 if ((fh = open("/devices/pseudo/mdesc@0:mdesc", O_RDONLY, 0)) < 0)
18131e37bb4Svn83148 return (-1);
18231e37bb4Svn83148
18331e37bb4Svn83148 if (ioctl(fh, MDESCIOCGSZ, &size) < 0) {
18431e37bb4Svn83148 (void) close(fh);
18531e37bb4Svn83148 return (-1);
18631e37bb4Svn83148 }
18731e37bb4Svn83148
18831e37bb4Svn83148 bufp = (uint64_t *)lhp->allocp(size);
18931e37bb4Svn83148
19031e37bb4Svn83148 if (read(fh, bufp, size) < 0) {
19131e37bb4Svn83148 lhp->freep(bufp, size);
19231e37bb4Svn83148 (void) close(fh);
19331e37bb4Svn83148 return (-1);
19431e37bb4Svn83148 }
19531e37bb4Svn83148 (void) close(fh);
19631e37bb4Svn83148
19731e37bb4Svn83148 *buf = bufp;
19831e37bb4Svn83148
19931e37bb4Svn83148 return ((ssize_t)size);
20031e37bb4Svn83148 }
20131e37bb4Svn83148
20231e37bb4Svn83148
20331e37bb4Svn83148 static int
get_local_md_prop_value(ldom_hdl_t * lhp,char * node,char * prop,uint64_t * val)204c37dbf9cSvn83148 get_local_md_prop_value(ldom_hdl_t *lhp, char *node, char *prop, uint64_t *val)
205c37dbf9cSvn83148 {
206c37dbf9cSvn83148 int rc = 1;
207c37dbf9cSvn83148 uint64_t *bufp;
208c37dbf9cSvn83148 ssize_t bufsiz;
209c37dbf9cSvn83148
210c37dbf9cSvn83148 if ((bufsiz = get_local_core_md(lhp, &bufp)) > 0) {
211c37dbf9cSvn83148 md_t *mdp;
212c37dbf9cSvn83148
213c37dbf9cSvn83148 if (mdp = md_init_intern(bufp, lhp->allocp, lhp->freep)) {
214c37dbf9cSvn83148 int num_nodes;
215c37dbf9cSvn83148 mde_cookie_t *listp;
216c37dbf9cSvn83148
217c37dbf9cSvn83148 num_nodes = md_node_count(mdp);
218c37dbf9cSvn83148 listp = lhp->allocp(sizeof (mde_cookie_t) * num_nodes);
219c37dbf9cSvn83148
220c37dbf9cSvn83148 if (md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE,
221c37dbf9cSvn83148 md_find_name(mdp, node),
222c3b50bc5Srb144127 md_find_name(mdp, "fwd"), listp) > 0 &&
223c37dbf9cSvn83148 md_get_prop_val(mdp, listp[0], prop, val) >= 0) {
224c37dbf9cSvn83148 /* found the property */
225c37dbf9cSvn83148 rc = 0;
226c37dbf9cSvn83148 }
227c37dbf9cSvn83148
228c37dbf9cSvn83148 lhp->freep(listp, sizeof (mde_cookie_t) * num_nodes);
229c37dbf9cSvn83148 (void) md_fini(mdp);
230c37dbf9cSvn83148 }
231c37dbf9cSvn83148 lhp->freep(bufp, bufsiz);
232c37dbf9cSvn83148 }
233c37dbf9cSvn83148 return (rc);
234c37dbf9cSvn83148 }
235c37dbf9cSvn83148
23631e37bb4Svn83148 /*
23731e37bb4Svn83148 * search the machine description for a "pid" entry (physical cpuid) and
238c3b50bc5Srb144127 * return the corresponding "id" entry (virtual cpuid).
239c3b50bc5Srb144127 * return -1 if not found.
240c3b50bc5Srb144127 * if the pid property does not exist in a cpu node, assume pid = id.
24131e37bb4Svn83148 */
24231e37bb4Svn83148 static processorid_t
cpu_phys2virt(ldom_hdl_t * lhp,uint32_t cpuid)24331e37bb4Svn83148 cpu_phys2virt(ldom_hdl_t *lhp, uint32_t cpuid)
24431e37bb4Svn83148 {
24531e37bb4Svn83148 char isa[MAXNAMELEN];
24631e37bb4Svn83148 md_t *mdp;
24731e37bb4Svn83148 mde_cookie_t *listp;
24831e37bb4Svn83148 ssize_t bufsize;
24931e37bb4Svn83148 processorid_t vid;
25031e37bb4Svn83148 uint64_t *bufp;
251c3b50bc5Srb144127 uint64_t pval, pid, id;
25231e37bb4Svn83148 int num_nodes, ncpus, i;
25331e37bb4Svn83148
254c3b50bc5Srb144127 (void) sysinfo(SI_MACHINE, isa, MAXNAMELEN);
25531e37bb4Svn83148
25631e37bb4Svn83148 if (strcmp(isa, "sun4v") != 0)
25731e37bb4Svn83148 return ((processorid_t)cpuid);
25831e37bb4Svn83148
25931e37bb4Svn83148 /*
26031e37bb4Svn83148 * convert the physical cpuid to a virtual cpuid
26131e37bb4Svn83148 */
262c3b50bc5Srb144127 if ((bufsize = get_local_core_md(lhp, &bufp)) < 1)
26331e37bb4Svn83148 return (-1);
26431e37bb4Svn83148
26531e37bb4Svn83148 if ((mdp = md_init_intern(bufp, lhp->allocp, lhp->freep)) == NULL ||
26631e37bb4Svn83148 (num_nodes = md_node_count(mdp)) < 1) {
26731e37bb4Svn83148 lhp->freep(bufp, bufsize);
26831e37bb4Svn83148 return (-1);
26931e37bb4Svn83148 }
27031e37bb4Svn83148
27131e37bb4Svn83148 listp = (mde_cookie_t *)lhp->allocp(sizeof (mde_cookie_t) * num_nodes);
27231e37bb4Svn83148 ncpus = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE,
273c3b50bc5Srb144127 md_find_name(mdp, "cpu"), md_find_name(mdp, "fwd"), listp);
27431e37bb4Svn83148
27531e37bb4Svn83148 vid = -1;
27631e37bb4Svn83148 for (i = 0; i < ncpus; i++) {
277c3b50bc5Srb144127 if (md_get_prop_val(mdp, listp[i], "id", &pval) < 0)
278c3b50bc5Srb144127 pval = (uint64_t)-1;
279c3b50bc5Srb144127 id = pval;
28031e37bb4Svn83148
281c3b50bc5Srb144127 /* if pid does not exist, assume pid=id */
282c3b50bc5Srb144127 if (md_get_prop_val(mdp, listp[i], "pid", &pval) < 0)
283c3b50bc5Srb144127 pval = id;
284c3b50bc5Srb144127 pid = pval;
285c3b50bc5Srb144127
286c3b50bc5Srb144127 if (pid == (uint64_t)cpuid) {
287c3b50bc5Srb144127 /* Found the entry */
288c3b50bc5Srb144127 vid = (processorid_t)id;
28931e37bb4Svn83148 break;
29031e37bb4Svn83148 }
29131e37bb4Svn83148 }
29231e37bb4Svn83148
29331e37bb4Svn83148 lhp->freep(listp, sizeof (mde_cookie_t) * num_nodes);
29431e37bb4Svn83148 (void) md_fini(mdp);
29531e37bb4Svn83148 lhp->freep(bufp, bufsize);
29631e37bb4Svn83148
29731e37bb4Svn83148 return (vid);
29831e37bb4Svn83148 }
29931e37bb4Svn83148
30025351652SVuong Nguyen static int
get_type(ldom_hdl_t * lhp,uint32_t * type)30125351652SVuong Nguyen get_type(ldom_hdl_t *lhp, uint32_t *type)
30225351652SVuong Nguyen {
30325351652SVuong Nguyen int num_nodes, cnt, i, rc;
30425351652SVuong Nguyen char *p;
30525351652SVuong Nguyen mde_cookie_t *listp;
30625351652SVuong Nguyen md_t *mdp;
30725351652SVuong Nguyen uint64_t domain_capable;
30825351652SVuong Nguyen uint64_t *bufp;
30925351652SVuong Nguyen ssize_t bufsize;
31025351652SVuong Nguyen
31125351652SVuong Nguyen *type = 0;
31225351652SVuong Nguyen
31325351652SVuong Nguyen /* legacy system */
31425351652SVuong Nguyen if (get_local_md_prop_value(lhp, MD_STR_PLATFORM, MD_STR_DOM_CAPABLE,
31525351652SVuong Nguyen &domain_capable) != 0) {
31625351652SVuong Nguyen *type = LDOM_TYPE_LEGACY;
31725351652SVuong Nguyen return (0);
31825351652SVuong Nguyen }
31925351652SVuong Nguyen
32025351652SVuong Nguyen /*
32125351652SVuong Nguyen * LDOMS capable FW is installed; it should be ok to
32225351652SVuong Nguyen * try to communicate with ldmd
32325351652SVuong Nguyen */
32425351652SVuong Nguyen if ((rc = ldmsvcs_check_channel()) == 0) {
32525351652SVuong Nguyen /*
32625351652SVuong Nguyen * control ldom
32725351652SVuong Nguyen * ldmfma channel between FMA and ldmd only exists
32825351652SVuong Nguyen * on the control domain.
32925351652SVuong Nguyen */
33025351652SVuong Nguyen *type |= LDOM_TYPE_CONTROL;
33125351652SVuong Nguyen } else if (rc == -1) {
33225351652SVuong Nguyen return (rc);
33325351652SVuong Nguyen }
33425351652SVuong Nguyen
33525351652SVuong Nguyen /*
33625351652SVuong Nguyen * root domain and io domain
33725351652SVuong Nguyen */
33825351652SVuong Nguyen if ((bufsize = get_local_core_md(lhp, &bufp)) < 1)
33925351652SVuong Nguyen return (-1);
34025351652SVuong Nguyen if ((mdp = md_init_intern(bufp, lhp->allocp, lhp->freep)) == NULL) {
34125351652SVuong Nguyen lhp->freep(bufp, bufsize);
34225351652SVuong Nguyen return (-1);
34325351652SVuong Nguyen }
34425351652SVuong Nguyen if ((num_nodes = md_node_count(mdp)) < 1) {
34525351652SVuong Nguyen lhp->freep(bufp, bufsize);
34625351652SVuong Nguyen (void) md_fini(mdp);
34725351652SVuong Nguyen return (-1);
34825351652SVuong Nguyen }
34925351652SVuong Nguyen
35025351652SVuong Nguyen /* Search for the root complex and niu nodes */
35125351652SVuong Nguyen listp = lhp->allocp(sizeof (mde_cookie_t) * num_nodes);
35225351652SVuong Nguyen cnt = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE,
35325351652SVuong Nguyen md_find_name(mdp, MD_STR_IODEVICE), md_find_name(mdp, "fwd"),
35425351652SVuong Nguyen listp);
35525351652SVuong Nguyen for (i = 0, p = NULL; i < cnt; i++) {
35625351652SVuong Nguyen if ((md_get_prop_str(mdp, listp[i], MD_STR_DEVICE_TYPE, &p)
35725351652SVuong Nguyen == 0) &&
35825351652SVuong Nguyen (p != NULL) && (strcmp(p, MD_STR_PCIEX) == 0)) {
35925351652SVuong Nguyen *type |= LDOM_TYPE_ROOT;
36025351652SVuong Nguyen break;
36125351652SVuong Nguyen }
36225351652SVuong Nguyen }
36325351652SVuong Nguyen for (i = 0, p = NULL; i < cnt; i++) {
36425351652SVuong Nguyen if ((md_get_prop_str(mdp, listp[i], MD_STR_NAME, &p) == 0) &&
36525351652SVuong Nguyen (p != NULL) && (strcmp(p, MD_STR_NIU) == 0)) {
36625351652SVuong Nguyen *type |= LDOM_TYPE_IO;
36725351652SVuong Nguyen break;
36825351652SVuong Nguyen }
36925351652SVuong Nguyen }
37025351652SVuong Nguyen lhp->freep(listp, sizeof (mde_cookie_t) * num_nodes);
37125351652SVuong Nguyen (void) md_fini(mdp);
37225351652SVuong Nguyen lhp->freep(bufp, bufsize);
37325351652SVuong Nguyen
37425351652SVuong Nguyen return (0);
37525351652SVuong Nguyen }
37625351652SVuong Nguyen
37725351652SVuong Nguyen int
ldom_get_type(ldom_hdl_t * lhp,uint32_t * type)37825351652SVuong Nguyen ldom_get_type(ldom_hdl_t *lhp, uint32_t *type)
37925351652SVuong Nguyen {
38025351652SVuong Nguyen static pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER;
38125351652SVuong Nguyen static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
38225351652SVuong Nguyen static uint32_t ltype = 0;
38325351652SVuong Nguyen static int busy_init = 0;
38425351652SVuong Nguyen
38525351652SVuong Nguyen int rc = 0;
38625351652SVuong Nguyen
38725351652SVuong Nguyen (void) pthread_mutex_lock(&mt);
38825351652SVuong Nguyen
38925351652SVuong Nguyen while (busy_init == 1)
39025351652SVuong Nguyen (void) pthread_cond_wait(&cv, &mt);
39125351652SVuong Nguyen
39225351652SVuong Nguyen if (VALID_LDOM_TYPE(ltype) != 0) {
39325351652SVuong Nguyen *type = ltype;
39425351652SVuong Nguyen (void) pthread_mutex_unlock(&mt);
39525351652SVuong Nguyen return (0);
39625351652SVuong Nguyen }
39725351652SVuong Nguyen
39825351652SVuong Nguyen /*
39925351652SVuong Nguyen * get to this point if the ldom_type has not yet been determined
40025351652SVuong Nguyen */
40125351652SVuong Nguyen busy_init = 1;
40225351652SVuong Nguyen (void) pthread_mutex_unlock(&mt);
40325351652SVuong Nguyen
40425351652SVuong Nguyen rc = get_type(lhp, <ype);
40525351652SVuong Nguyen if (rc == 0) {
40625351652SVuong Nguyen *type = ltype;
40725351652SVuong Nguyen }
40825351652SVuong Nguyen
40925351652SVuong Nguyen (void) pthread_mutex_lock(&mt);
41025351652SVuong Nguyen busy_init = 0;
41125351652SVuong Nguyen (void) pthread_mutex_unlock(&mt);
41225351652SVuong Nguyen
41325351652SVuong Nguyen (void) pthread_cond_broadcast(&cv);
41425351652SVuong Nguyen
41525351652SVuong Nguyen return (rc);
41625351652SVuong Nguyen }
41725351652SVuong Nguyen
41831e37bb4Svn83148 int
ldom_fmri_status(ldom_hdl_t * lhp,nvlist_t * nvl)41931e37bb4Svn83148 ldom_fmri_status(ldom_hdl_t *lhp, nvlist_t *nvl)
42031e37bb4Svn83148 {
42131e37bb4Svn83148 char *name;
422c3b50bc5Srb144127 int ret = ENOTSUP;
42331e37bb4Svn83148
42431e37bb4Svn83148 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0)
42531e37bb4Svn83148 return (EINVAL);
42631e37bb4Svn83148
42731e37bb4Svn83148 /*
42825351652SVuong Nguyen * ldom_ldmd_is_up can only be true if a pri can be obtained from ldmd.
42931e37bb4Svn83148 */
430c3b50bc5Srb144127 if (!ldom_ldmd_is_up) {
431c3b50bc5Srb144127 /* Zeus is unavail; use local routines for status/retire */
432c3b50bc5Srb144127
43331e37bb4Svn83148 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) {
43431e37bb4Svn83148 processorid_t vid;
43531e37bb4Svn83148 uint32_t cpuid;
43631e37bb4Svn83148
437c3b50bc5Srb144127 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid)
438c3b50bc5Srb144127 == 0 && (vid = cpu_phys2virt(lhp, cpuid)) != -1)
43931e37bb4Svn83148 return (p_online(vid, P_STATUS));
44031e37bb4Svn83148 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) {
441e4b86885SCheng Sean Ye fmd_agent_hdl_t *hdl;
442e4b86885SCheng Sean Ye int err;
443e4b86885SCheng Sean Ye if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL) {
444e4b86885SCheng Sean Ye err = errno;
445e4b86885SCheng Sean Ye } else {
446e4b86885SCheng Sean Ye err = fmd_agent_page_isretired(hdl, nvl);
447e4b86885SCheng Sean Ye if (err == FMD_AGENT_RETIRE_DONE)
448e4b86885SCheng Sean Ye err = 0;
449e4b86885SCheng Sean Ye else
450e4b86885SCheng Sean Ye err = fmd_agent_errno(hdl);
451e4b86885SCheng Sean Ye fmd_agent_close(hdl);
452e4b86885SCheng Sean Ye }
453e4b86885SCheng Sean Ye return (err);
45431e37bb4Svn83148 }
45531e37bb4Svn83148
45631e37bb4Svn83148 return (EINVAL);
457c3b50bc5Srb144127 } else {
458c3b50bc5Srb144127 /* Zeus is avail; use Zeus for status/retire */
459c3b50bc5Srb144127
46031e37bb4Svn83148 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) {
46131e37bb4Svn83148 uint32_t cpuid;
46231e37bb4Svn83148
46331e37bb4Svn83148 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID,
46431e37bb4Svn83148 &cpuid) == 0)
46531e37bb4Svn83148 ret = ldmsvcs_cpu_req_status(lhp, cpuid);
46631e37bb4Svn83148 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) {
46731e37bb4Svn83148 uint64_t pa;
46831e37bb4Svn83148
46931e37bb4Svn83148 if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR,
47031e37bb4Svn83148 &pa) == 0)
47131e37bb4Svn83148 ret = ldmsvcs_mem_req_status(lhp, pa);
47231e37bb4Svn83148 else
47331e37bb4Svn83148 ret = EINVAL;
47431e37bb4Svn83148 }
47531e37bb4Svn83148 return (ret);
47631e37bb4Svn83148 }
47731e37bb4Svn83148 }
47831e37bb4Svn83148
47931e37bb4Svn83148
48031e37bb4Svn83148 int
ldom_fmri_retire(ldom_hdl_t * lhp,nvlist_t * nvl)48131e37bb4Svn83148 ldom_fmri_retire(ldom_hdl_t *lhp, nvlist_t *nvl)
48231e37bb4Svn83148 {
48331e37bb4Svn83148 char *name;
484c3b50bc5Srb144127 int ret = ENOTSUP;
48531e37bb4Svn83148
48631e37bb4Svn83148 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0)
48731e37bb4Svn83148 return (EINVAL);
48831e37bb4Svn83148
48931e37bb4Svn83148 /*
49025351652SVuong Nguyen * ldom_ldmd_is_up can only be true if a pri can be obtained from ldmd.
49131e37bb4Svn83148 */
492c3b50bc5Srb144127 if (!ldom_ldmd_is_up) {
493c3b50bc5Srb144127 /* Zeus is unavail; use local routines for status/retire */
494c3b50bc5Srb144127
49531e37bb4Svn83148 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) {
49631e37bb4Svn83148 processorid_t vid;
49731e37bb4Svn83148 uint32_t cpuid;
49831e37bb4Svn83148
499c3b50bc5Srb144127 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid)
500c3b50bc5Srb144127 == 0 && (vid = cpu_phys2virt(lhp, cpuid)) != -1)
50131e37bb4Svn83148 return (p_online(vid, P_FAULTED));
50231e37bb4Svn83148 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) {
503e4b86885SCheng Sean Ye fmd_agent_hdl_t *hdl;
504e4b86885SCheng Sean Ye int err;
505e4b86885SCheng Sean Ye if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL) {
506e4b86885SCheng Sean Ye err = errno;
507e4b86885SCheng Sean Ye } else {
508e4b86885SCheng Sean Ye err = fmd_agent_page_retire(hdl, nvl);
509e4b86885SCheng Sean Ye if (err == FMD_AGENT_RETIRE_DONE)
510e4b86885SCheng Sean Ye err = 0;
511e4b86885SCheng Sean Ye else
512e4b86885SCheng Sean Ye err = fmd_agent_errno(hdl);
513e4b86885SCheng Sean Ye fmd_agent_close(hdl);
514e4b86885SCheng Sean Ye }
515e4b86885SCheng Sean Ye return (err);
51631e37bb4Svn83148 }
51731e37bb4Svn83148
51831e37bb4Svn83148 return (EINVAL);
519c3b50bc5Srb144127 } else {
520c3b50bc5Srb144127 /* Zeus is avail; use Zeus for status/retire */
521c3b50bc5Srb144127
52231e37bb4Svn83148 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) {
52331e37bb4Svn83148 uint32_t cpuid;
52431e37bb4Svn83148
52531e37bb4Svn83148 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID,
52631e37bb4Svn83148 &cpuid) == 0)
52731e37bb4Svn83148 ret = ldmsvcs_cpu_req_offline(lhp, cpuid);
52831e37bb4Svn83148 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) {
52931e37bb4Svn83148 uint64_t pa;
53031e37bb4Svn83148
53131e37bb4Svn83148 if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR,
53231e37bb4Svn83148 &pa) == 0)
53331e37bb4Svn83148 ret = ldmsvcs_mem_req_retire(lhp, pa);
53431e37bb4Svn83148 else
53531e37bb4Svn83148 ret = EINVAL;
53631e37bb4Svn83148 }
53731e37bb4Svn83148 return (ret);
53831e37bb4Svn83148 }
53931e37bb4Svn83148 }
54031e37bb4Svn83148
5415f149bcaScy152378 int
ldom_fmri_unretire(ldom_hdl_t * lhp,nvlist_t * nvl)5425f149bcaScy152378 ldom_fmri_unretire(ldom_hdl_t *lhp, nvlist_t *nvl)
5435f149bcaScy152378 {
5445f149bcaScy152378 char *name;
5455f149bcaScy152378 int ret = ENOTSUP;
5465f149bcaScy152378
5475f149bcaScy152378 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0)
5485f149bcaScy152378 return (EINVAL);
54931e37bb4Svn83148
55031e37bb4Svn83148 /*
55125351652SVuong Nguyen * ldom_ldmd_is_up can only be true if a pri can be obtained from ldmd.
55231e37bb4Svn83148 */
5535f149bcaScy152378 if (!ldom_ldmd_is_up) {
5545f149bcaScy152378 /* Zeus is unavail; use local routines for status/retire */
5555f149bcaScy152378
5565f149bcaScy152378 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) {
5575f149bcaScy152378 processorid_t vid;
5585f149bcaScy152378 uint32_t cpuid;
5595f149bcaScy152378
5605f149bcaScy152378 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid)
5615f149bcaScy152378 == 0 && (vid = cpu_phys2virt(lhp, cpuid)) != -1)
5625f149bcaScy152378 return (p_online(vid, P_ONLINE));
5635f149bcaScy152378 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) {
564e4b86885SCheng Sean Ye fmd_agent_hdl_t *hdl;
565e4b86885SCheng Sean Ye int err;
566e4b86885SCheng Sean Ye if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL) {
567e4b86885SCheng Sean Ye err = errno;
568e4b86885SCheng Sean Ye } else {
569e4b86885SCheng Sean Ye err = fmd_agent_page_unretire(hdl, nvl);
570e4b86885SCheng Sean Ye if (err == FMD_AGENT_RETIRE_DONE)
571e4b86885SCheng Sean Ye err = 0;
572e4b86885SCheng Sean Ye else
573e4b86885SCheng Sean Ye err = fmd_agent_errno(hdl);
574e4b86885SCheng Sean Ye fmd_agent_close(hdl);
575e4b86885SCheng Sean Ye }
576e4b86885SCheng Sean Ye return (err);
5775f149bcaScy152378 }
5785f149bcaScy152378
5795f149bcaScy152378 return (EINVAL);
5805f149bcaScy152378 } else {
5815f149bcaScy152378 /* Zeus is avail; use Zeus for status/retire */
5825f149bcaScy152378
5835f149bcaScy152378 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) {
5845f149bcaScy152378 uint32_t cpuid;
5855f149bcaScy152378
5865f149bcaScy152378 if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID,
5875f149bcaScy152378 &cpuid) == 0)
5885f149bcaScy152378 ret = ldmsvcs_cpu_req_online(lhp, cpuid);
5895f149bcaScy152378 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) {
5905f149bcaScy152378 uint64_t pa;
5915f149bcaScy152378
5925f149bcaScy152378 if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR,
5935f149bcaScy152378 &pa) == 0)
5945f149bcaScy152378 ret = ldmsvcs_mem_req_unretire(lhp, pa);
5955f149bcaScy152378 else
5965f149bcaScy152378 ret = EINVAL;
5975f149bcaScy152378 }
5985f149bcaScy152378 return (ret);
5995f149bcaScy152378 }
6005f149bcaScy152378 }
6015f149bcaScy152378
6025f149bcaScy152378 static int
fmri_blacklist(ldom_hdl_t * lhp,nvlist_t * nvl,int cmd)6035f149bcaScy152378 fmri_blacklist(ldom_hdl_t *lhp, nvlist_t *nvl, int cmd)
60431e37bb4Svn83148 {
60531e37bb4Svn83148 char *name;
60625351652SVuong Nguyen uint32_t type = 0;
60731e37bb4Svn83148
60825351652SVuong Nguyen if ((ldom_get_type(lhp, &type) != 0) ||
60925351652SVuong Nguyen ((type & LDOM_TYPE_LEGACY) == 0))
61031e37bb4Svn83148 return (0);
61131e37bb4Svn83148
61231e37bb4Svn83148 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0)
61331e37bb4Svn83148 return (EINVAL);
61431e37bb4Svn83148
61531e37bb4Svn83148 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) {
61631e37bb4Svn83148 bl_req_t blr;
61731e37bb4Svn83148 char *class;
61831e37bb4Svn83148 int fd, rc, err;
61931e37bb4Svn83148
62031e37bb4Svn83148 if ((nvlist_lookup_string(nvl, FM_CLASS, &class) != 0) ||
62131e37bb4Svn83148 (class == NULL) || (*class == '\0'))
62231e37bb4Svn83148 return (EINVAL);
62331e37bb4Svn83148
62431e37bb4Svn83148 if ((fd = open("/dev/bl", O_RDONLY)) < 0)
62531e37bb4Svn83148 return (EIO);
62631e37bb4Svn83148
62731e37bb4Svn83148 if (nvlist_size(nvl, &blr.bl_fmrisz, NV_ENCODE_NATIVE) != 0 ||
62831e37bb4Svn83148 blr.bl_fmrisz == 0 ||
62931e37bb4Svn83148 (blr.bl_fmri = (caddr_t)lhp->allocp(blr.bl_fmrisz)) ==
63031e37bb4Svn83148 NULL) {
63131e37bb4Svn83148 (void) close(fd);
63231e37bb4Svn83148 return (EINVAL);
63331e37bb4Svn83148 }
63431e37bb4Svn83148
63531e37bb4Svn83148 blr.bl_class = class;
63631e37bb4Svn83148
6375f149bcaScy152378 rc = ioctl(fd, cmd, &blr);
63831e37bb4Svn83148 err = errno;
63931e37bb4Svn83148
64031e37bb4Svn83148 lhp->freep((void *)&blr.bl_fmri, blr.bl_fmrisz);
64131e37bb4Svn83148 (void) close(fd);
64231e37bb4Svn83148
64331e37bb4Svn83148 if (rc < 0 && err != ENOTSUP) {
64431e37bb4Svn83148 errno = err;
64531e37bb4Svn83148 return (-1);
64631e37bb4Svn83148 }
64731e37bb4Svn83148 }
64831e37bb4Svn83148
64931e37bb4Svn83148 return (0);
65031e37bb4Svn83148 }
65131e37bb4Svn83148
6525f149bcaScy152378 /*
6535f149bcaScy152378 * blacklist cpus in a non-LDOMS environment
6545f149bcaScy152378 */
6555f149bcaScy152378 int
ldom_fmri_blacklist(ldom_hdl_t * lhp,nvlist_t * nvl)6565f149bcaScy152378 ldom_fmri_blacklist(ldom_hdl_t *lhp, nvlist_t *nvl)
6575f149bcaScy152378 {
6585f149bcaScy152378 return (fmri_blacklist(lhp, nvl, BLIOC_INSERT));
6595f149bcaScy152378 }
6605f149bcaScy152378
6615f149bcaScy152378 /*
6625f149bcaScy152378 * unblacklist cpus
6635f149bcaScy152378 */
6645f149bcaScy152378 int
ldom_fmri_unblacklist(ldom_hdl_t * lhp,nvlist_t * nvl)6655f149bcaScy152378 ldom_fmri_unblacklist(ldom_hdl_t *lhp, nvlist_t *nvl)
6665f149bcaScy152378 {
6675f149bcaScy152378 return (fmri_blacklist(lhp, nvl, BLIOC_DELETE));
6685f149bcaScy152378 }
6695f149bcaScy152378
67031e37bb4Svn83148
67131e37bb4Svn83148 ssize_t
ldom_get_local_md(ldom_hdl_t * lhp,uint64_t ** buf)67225351652SVuong Nguyen ldom_get_local_md(ldom_hdl_t *lhp, uint64_t **buf)
67325351652SVuong Nguyen {
67425351652SVuong Nguyen return (get_local_core_md(lhp, buf));
67525351652SVuong Nguyen }
67625351652SVuong Nguyen
67725351652SVuong Nguyen ssize_t
ldom_get_core_md(ldom_hdl_t * lhp,uint64_t ** buf)67831e37bb4Svn83148 ldom_get_core_md(ldom_hdl_t *lhp, uint64_t **buf)
67931e37bb4Svn83148 {
680ef884685Srb144127 ssize_t rv; /* return value */
681c3b50bc5Srb144127 uint64_t tok; /* opaque PRI token */
68225351652SVuong Nguyen uint32_t type = 0;
683ef884685Srb144127
684*c95876f5SVuong Nguyen if (ldom_get_type(lhp, &type) != 0) {
68525351652SVuong Nguyen return (-1);
68625351652SVuong Nguyen }
687*c95876f5SVuong Nguyen
68825351652SVuong Nguyen if ((type & LDOM_TYPE_CONTROL) != 0) {
68925351652SVuong Nguyen /* Get the pri from Zeus first. If failed, get it from libpri */
690c3b50bc5Srb144127 if ((rv = ldmsvcs_get_core_md(lhp, buf)) < 1) {
691c3b50bc5Srb144127 (void) pthread_mutex_lock(&ldom_pri_lock);
692c3b50bc5Srb144127 rv = ldom_pri_get(PRI_GET, &tok,
693c3b50bc5Srb144127 buf, lhp->allocp, lhp->freep);
694c3b50bc5Srb144127 (void) pthread_mutex_unlock(&ldom_pri_lock);
695ef884685Srb144127 } else {
696c3b50bc5Srb144127 ldom_ldmd_is_up = 1;
69725351652SVuong Nguyen xmpp_start();
698ef884685Srb144127 }
699c3b50bc5Srb144127 } else {
700*c95876f5SVuong Nguyen /* get the pruned PRI from the libpri */
701*c95876f5SVuong Nguyen (void) pthread_mutex_lock(&ldom_pri_lock);
702*c95876f5SVuong Nguyen rv = ldom_pri_get(PRI_GET, &tok, buf, lhp->allocp, lhp->freep);
703*c95876f5SVuong Nguyen (void) pthread_mutex_unlock(&ldom_pri_lock);
704c3b50bc5Srb144127 }
70531e37bb4Svn83148
706c3b50bc5Srb144127 return (rv);
70731e37bb4Svn83148 }
70831e37bb4Svn83148
70931e37bb4Svn83148 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)71025351652SVuong Nguyen ldom_find_id(ldom_hdl_t *lhp, uint64_t addr, ldom_rsrc_t rsrc,
71125351652SVuong Nguyen uint64_t *virt_addr, char *name, int name_size, uint64_t *did)
71231e37bb4Svn83148 {
71325351652SVuong Nguyen uint32_t type = 0;
71431e37bb4Svn83148
71525351652SVuong Nguyen (void) ldom_get_type(lhp, &type);
71625351652SVuong Nguyen if ((type & LDOM_TYPE_CONTROL) == 0) {
71725351652SVuong Nguyen return (ENOTSUP);
71825351652SVuong Nguyen }
71925351652SVuong Nguyen if (!ldom_ldmd_is_up) {
72025351652SVuong Nguyen return (EAGAIN);
72125351652SVuong Nguyen }
72225351652SVuong Nguyen return (ldmsvcs_io_req_id(lhp, addr, rsrc, virt_addr,
72325351652SVuong Nguyen name, name_size, did));
72425351652SVuong Nguyen }
72525351652SVuong Nguyen
72625351652SVuong Nguyen int
ldom_register_event(ldom_hdl_t * lhp,ldom_reg_cb_t cb,ldom_cb_arg_t data)72725351652SVuong Nguyen ldom_register_event(ldom_hdl_t *lhp, ldom_reg_cb_t cb, ldom_cb_arg_t data)
72825351652SVuong Nguyen {
72925351652SVuong Nguyen uint32_t type = 0;
73025351652SVuong Nguyen
73125351652SVuong Nguyen (void) ldom_get_type(lhp, &type);
73225351652SVuong Nguyen if ((type & LDOM_TYPE_CONTROL) == 0) {
73325351652SVuong Nguyen return (ENOTSUP);
73425351652SVuong Nguyen }
73525351652SVuong Nguyen
73625351652SVuong Nguyen return (xmpp_add_client(lhp, cb, data));
73725351652SVuong Nguyen }
73825351652SVuong Nguyen
73925351652SVuong Nguyen int
ldom_unregister_event(ldom_hdl_t * lhp)74025351652SVuong Nguyen ldom_unregister_event(ldom_hdl_t *lhp)
74125351652SVuong Nguyen {
74225351652SVuong Nguyen uint32_t type = 0;
74325351652SVuong Nguyen
74425351652SVuong Nguyen (void) ldom_get_type(lhp, &type);
74525351652SVuong Nguyen if ((type & LDOM_TYPE_CONTROL) == 0) {
74625351652SVuong Nguyen return (ENOTSUP);
74725351652SVuong Nguyen }
74825351652SVuong Nguyen
74925351652SVuong Nguyen return (xmpp_remove_client(lhp));
75031e37bb4Svn83148 }
75131e37bb4Svn83148
75231e37bb4Svn83148 /*
75325351652SVuong Nguyen * ldom_init()
75425351652SVuong Nguyen * Description:
75525351652SVuong Nguyen * Return a libldom handle to the caller for uniquely identify the session
75625351652SVuong Nguyen * betweem the caller and the libldom.so. The handle is used in
75725351652SVuong Nguyen * subsequent calls into the libldom.so
75825351652SVuong Nguyen *
75925351652SVuong Nguyen * If the caller does not provide a alloc()/free(), the libldom uses its
76025351652SVuong Nguyen * own functions.
76131e37bb4Svn83148 */
76231e37bb4Svn83148 ldom_hdl_t *
ldom_init(void * (* allocp)(size_t size),void (* freep)(void * addr,size_t size))76331e37bb4Svn83148 ldom_init(void *(*allocp)(size_t size),
76431e37bb4Svn83148 void (*freep)(void *addr, size_t size))
76531e37bb4Svn83148 {
76631e37bb4Svn83148 struct ldom_hdl *lhp;
76731e37bb4Svn83148
76825351652SVuong Nguyen if (allocp == NULL && freep == NULL) {
76925351652SVuong Nguyen allocp = ldom_alloc;
77025351652SVuong Nguyen freep = ldom_free;
77125351652SVuong Nguyen } else if (allocp == NULL || freep == NULL) {
77225351652SVuong Nguyen /* missing alloc or free functions */
77325351652SVuong Nguyen return (NULL);
77425351652SVuong Nguyen }
77525351652SVuong Nguyen
776c3b50bc5Srb144127 (void) pthread_mutex_lock(&ldom_pri_lock);
77731e37bb4Svn83148
778c3b50bc5Srb144127 if (ldom_pri_init() < 0) {
779c3b50bc5Srb144127 (void) pthread_mutex_unlock(&ldom_pri_lock);
780ef884685Srb144127 return (NULL);
781ef884685Srb144127 }
782ef884685Srb144127
783c3b50bc5Srb144127 if ((lhp = allocp(sizeof (struct ldom_hdl))) == NULL) {
784c3b50bc5Srb144127 ldom_pri_fini();
785c3b50bc5Srb144127 (void) pthread_mutex_unlock(&ldom_pri_lock);
786c3b50bc5Srb144127 return (NULL);
787c3b50bc5Srb144127 }
788c3b50bc5Srb144127
789c3b50bc5Srb144127 (void) pthread_mutex_unlock(&ldom_pri_lock);
790c3b50bc5Srb144127
79131e37bb4Svn83148 lhp->allocp = allocp;
79231e37bb4Svn83148 lhp->freep = freep;
79331e37bb4Svn83148
79431e37bb4Svn83148 ldmsvcs_init(lhp);
79531e37bb4Svn83148
79631e37bb4Svn83148 return (lhp);
79731e37bb4Svn83148 }
79831e37bb4Svn83148
79931e37bb4Svn83148
80031e37bb4Svn83148 void
ldom_fini(ldom_hdl_t * lhp)80131e37bb4Svn83148 ldom_fini(ldom_hdl_t *lhp)
80231e37bb4Svn83148 {
80331e37bb4Svn83148 if (lhp == NULL)
80431e37bb4Svn83148 return;
80531e37bb4Svn83148
80625351652SVuong Nguyen (void) xmpp_remove_client(lhp);
80731e37bb4Svn83148 ldmsvcs_fini(lhp);
80831e37bb4Svn83148 lhp->freep(lhp, sizeof (struct ldom_hdl));
809ef884685Srb144127
810c3b50bc5Srb144127 (void) pthread_mutex_lock(&ldom_pri_lock);
811c3b50bc5Srb144127
812c3b50bc5Srb144127 ldom_pri_fini();
813c3b50bc5Srb144127
814c3b50bc5Srb144127 (void) pthread_mutex_unlock(&ldom_pri_lock);
81531e37bb4Svn83148 }
81631e37bb4Svn83148
81731e37bb4Svn83148 /* end file */
818