/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <libnvpair.h>
#include <dlfcn.h>
#include <link.h>
#include <assert.h>
#include <sys/processor.h>
#include <sys/systeminfo.h>
#include <fm/fmd_fmri.h>
#include <fm/fmd_agent.h>
#include "ldom.h"
#include "ldom_alloc.h"
#include "ldmsvcs_utils.h"
#include "ldom_xmpp_client.h"
static void
ldom_pri_config(void)
{
return;
return;
return;
}
static void
ldom_pri_unconfig(void)
{
if (ldom_dl_hp == NULL)
return;
ldom_pri_fp_init = (int (*)(void))NULL;
ldom_pri_fp_fini = (void (*)(void))NULL;
(void) dlclose(ldom_dl_hp);
ldom_dl_hp = (void *)NULL;
}
/*
* ldom_pri_lock is assumed already held by anyone accessing ldom_pri_ref_cnt
*/
static int
ldom_pri_init(void)
{
if (ldom_pri_ref_cnt == 0) {
/*
* ldom_pri_init() is called before we know whether we
* have LDOMS FW or not; defer calling pri_init() via
* ldom_pri_fp_init until the first time we try to
* actually get a PRI
*/
}
assert(ldom_pri_ref_cnt > 0);
return (0);
}
static void
ldom_pri_fini(void)
{
assert(ldom_pri_ref_cnt > 0);
if (ldom_pri_ref_cnt == 0) {
(*ldom_pri_fp_fini)();
ldom_pri_init_done = 0;
}
}
}
static ssize_t
{
assert(ldom_pri_ref_cnt > 0);
if ((*ldom_pri_fp_init)() < 0)
return (-1);
ldom_pri_init_done = 1;
}
if (ldom_pri_fp_get != NULL)
else
return (-1);
}
static ssize_t
{
int fh;
return (-1);
return (-1);
}
return (-1);
}
}
static int
{
int num_nodes;
/* found the property */
rc = 0;
}
}
}
return (rc);
}
/*
* search the machine description for a "pid" entry (physical cpuid) and
* return the corresponding "id" entry (virtual cpuid).
* return -1 if not found.
* if the pid property does not exist in a cpu node, assume pid = id.
*/
static processorid_t
{
return ((processorid_t)cpuid);
/*
* convert the physical cpuid to a virtual cpuid
*/
return (-1);
return (-1);
}
vid = -1;
for (i = 0; i < ncpus; i++) {
/* if pid does not exist, assume pid=id */
/* Found the entry */
break;
}
}
return (vid);
}
static int
{
char *p;
*type = 0;
/* legacy system */
&domain_capable) != 0) {
*type = LDOM_TYPE_LEGACY;
return (0);
}
/*
* LDOMS capable FW is installed; it should be ok to
* try to communicate with ldmd
*/
if ((rc = ldmsvcs_check_channel()) == 0) {
/*
* control ldom
* ldmfma channel between FMA and ldmd only exists
* on the control domain.
*/
*type |= LDOM_TYPE_CONTROL;
} else if (rc == -1) {
return (rc);
}
/*
* root domain and io domain
*/
return (-1);
return (-1);
}
return (-1);
}
/* Search for the root complex and niu nodes */
listp);
== 0) &&
*type |= LDOM_TYPE_ROOT;
break;
}
}
*type |= LDOM_TYPE_IO;
break;
}
}
return (0);
}
int
{
static int busy_init = 0;
int rc = 0;
(void) pthread_mutex_lock(&mt);
while (busy_init == 1)
if (VALID_LDOM_TYPE(ltype) != 0) {
(void) pthread_mutex_unlock(&mt);
return (0);
}
/*
* get to this point if the ldom_type has not yet been determined
*/
busy_init = 1;
(void) pthread_mutex_unlock(&mt);
if (rc == 0) {
}
(void) pthread_mutex_lock(&mt);
busy_init = 0;
(void) pthread_mutex_unlock(&mt);
(void) pthread_cond_broadcast(&cv);
return (rc);
}
int
{
char *name;
return (EINVAL);
/*
* ldom_ldmd_is_up can only be true if a pri can be obtained from ldmd.
*/
if (!ldom_ldmd_is_up) {
int err;
} else {
if (err == FMD_AGENT_RETIRE_DONE)
err = 0;
else
}
return (err);
}
return (EINVAL);
} else {
&cpuid) == 0)
&pa) == 0)
else
}
return (ret);
}
}
int
{
char *name;
return (EINVAL);
/*
* ldom_ldmd_is_up can only be true if a pri can be obtained from ldmd.
*/
if (!ldom_ldmd_is_up) {
int err;
} else {
if (err == FMD_AGENT_RETIRE_DONE)
err = 0;
else
}
return (err);
}
return (EINVAL);
} else {
&cpuid) == 0)
&pa) == 0)
else
}
return (ret);
}
}
int
{
char *name;
return (EINVAL);
/*
* ldom_ldmd_is_up can only be true if a pri can be obtained from ldmd.
*/
if (!ldom_ldmd_is_up) {
int err;
} else {
if (err == FMD_AGENT_RETIRE_DONE)
err = 0;
else
}
return (err);
}
return (EINVAL);
} else {
&cpuid) == 0)
&pa) == 0)
else
}
return (ret);
}
}
static int
{
char *name;
((type & LDOM_TYPE_LEGACY) == 0))
return (0);
return (EINVAL);
char *class;
return (EINVAL);
return (EIO);
NULL) {
return (EINVAL);
}
return (-1);
}
}
return (0);
}
/*
* blacklist cpus in a non-LDOMS environment
*/
int
{
}
/*
* unblacklist cpus
*/
int
{
}
{
}
{
return (-1);
}
if ((type & LDOM_TYPE_CONTROL) != 0) {
/* Get the pri from Zeus first. If failed, get it from libpri */
(void) pthread_mutex_lock(&ldom_pri_lock);
(void) pthread_mutex_unlock(&ldom_pri_lock);
} else {
ldom_ldmd_is_up = 1;
xmpp_start();
}
} else {
/* get the pruned PRI from the libpri */
(void) pthread_mutex_lock(&ldom_pri_lock);
(void) pthread_mutex_unlock(&ldom_pri_lock);
}
return (rv);
}
int
{
if ((type & LDOM_TYPE_CONTROL) == 0) {
return (ENOTSUP);
}
if (!ldom_ldmd_is_up) {
return (EAGAIN);
}
}
int
{
if ((type & LDOM_TYPE_CONTROL) == 0) {
return (ENOTSUP);
}
}
int
{
if ((type & LDOM_TYPE_CONTROL) == 0) {
return (ENOTSUP);
}
return (xmpp_remove_client(lhp));
}
/*
* ldom_init()
* Description:
* Return a libldom handle to the caller for uniquely identify the session
* betweem the caller and the libldom.so. The handle is used in
* subsequent calls into the libldom.so
*
* If the caller does not provide a alloc()/free(), the libldom uses its
* own functions.
*/
{
allocp = ldom_alloc;
/* missing alloc or free functions */
return (NULL);
}
(void) pthread_mutex_lock(&ldom_pri_lock);
if (ldom_pri_init() < 0) {
(void) pthread_mutex_unlock(&ldom_pri_lock);
return (NULL);
}
(void) pthread_mutex_unlock(&ldom_pri_lock);
return (NULL);
}
(void) pthread_mutex_unlock(&ldom_pri_lock);
return (lhp);
}
void
{
return;
(void) xmpp_remove_client(lhp);
(void) pthread_mutex_lock(&ldom_pri_lock);
(void) pthread_mutex_unlock(&ldom_pri_lock);
}
/* end file */