/*
* 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
*/
/*
*/
#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 *str;
*type = 0;
/* legacy system */
&val) != 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);
}
/*
* get the local MD
*/
return (-1);
return (-1);
}
return (-1);
}
/*
* root complex node
* Search for an iodevice node which has a device-type prop of pciex.
* If the node also has an additional property virtual-root-complex,
* it is a VROOT domain which has a PCIe assignment by direct I/O
* (i.e. SDIO) or SR-IOV. Otherwise it is a root domain.
*/
listp);
*type |= LDOM_TYPE_VROOT;
} else {
*type |= LDOM_TYPE_ROOT;
}
break;
}
}
/*
* ldom which has a NIU (network interface unit) node assigned
*/
*type |= LDOM_TYPE_NIU;
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 this is a Control Domain and we have not seen Zeus up yet,
* check if Zeus is up by trying to get a PRI from it.
*/
ldom_ldmd_is_up = 1;
xmpp_start();
/* Free the PRI buffer since we don't need it. */
}
}
/*
* Always get the PRI from libpri in order to avoid
* race conditions with ldom_waitget_core_md().
*/
(void) pthread_mutex_lock(&ldom_pri_lock);
if (rv >= 0) {
}
(void) pthread_mutex_unlock(&ldom_pri_lock);
return (rv);
}
{
return (-1);
/*
* Make sure we've called pri_get() successfully at
* least once before calling it with the wait flag.
*/
(void) pthread_mutex_lock(&ldom_pri_lock);
if (ldom_pri_get_cnt == 0) {
if (rv >= 0) {
} else {
(void) pthread_mutex_unlock(&ldom_pri_lock);
return (rv);
}
/* Free the PRI buffer since we don't need it. */
if (rv > 0)
}
(void) pthread_mutex_unlock(&ldom_pri_lock);
/*
* Now wait for a PRI update.
* This call will block until a PRI with a token different
* from the one passed in is available.
*/
if (rv >= 0) {
(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 */