ldom.c revision c94f2192ecbda893748b026d615083d4e5190a4c
/*
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <libnvpair.h>
#include <dlfcn.h>
#include <link.h>
#include <sys/processor.h>
#include <sys/systeminfo.h>
#include <fm/fmd_fmri.h>
#include "ldom.h"
#include "ldmsvcs_utils.h"
#define MD_STR_PLATFORM "platform"
#define MD_STR_DOM_ENABLE "domaining-enabled"
static void *ldom_dl_hp = (void *)NULL;
static const char *ldom_dl_path = "libpri.so.1";
static int (*ldom_pri_init)(void) = (int (*)(void))NULL;
static void (*ldom_pri_fini)(void) = (void (*)(void))NULL;
static void
ldom_pri_config(void)
{
return;
return;
return;
}
static void
ldom_pri_unconfig(void)
{
if (ldom_dl_hp == NULL)
return;
ldom_pri_init = (int (*)(void))NULL;
ldom_pri_fini = (void (*)(void))NULL;
(void) dlclose(ldom_dl_hp);
ldom_dl_hp = (void *)NULL;
}
static ssize_t
{
int fh;
if (ldom_pri_get != NULL)
return (ssize);
return (-1);
return (-1);
}
return (-1);
}
}
static int
{
int rc = 1;
int num_nodes;
listp) > 0 &&
/* found the property */
rc = 0;
}
}
}
return (rc);
}
static int
{
static int major_version = -1;
static int service_ldom = -1;
static int busy_init = 0;
(void) pthread_mutex_lock(&mt);
while (busy_init == 1)
(void) pthread_mutex_unlock(&mt);
return (0);
}
/*
* get to this point if major_version and service_ldom have not yet
* been determined
*/
busy_init = 1;
(void) pthread_mutex_unlock(&mt);
/*
* set defaults which correspond to the case of "LDOMS not
* available". note that these can (and will) also apply to
* non-sun4v machines.
*/
major_version = 0;
service_ldom = 0;
domain_enable = 0;
&domain_enable) == 0 &&
domain_enable != 0) {
/*
* Domaining is enable and ldmd is not in config mode
* so this is a ldom env.
*/
major_version = 1;
if ((ier = ldmsvcs_check_channel()) == 0) {
/*
* control ldom
* ldmfma channel between FMA and ldmd only exists
* on the control domain.
*/
service_ldom = 1;
} else if (ier == 1) {
/*
* guest ldom
* non-control ldom such as guest and io service ldom
*/
service_ldom = 0;
}
}
(void) pthread_mutex_lock(&mt);
busy_init = 0;
(void) pthread_mutex_unlock(&mt);
(void) pthread_cond_broadcast(&cv);
return (rc);
}
/*
* search the machine description for a "pid" entry (physical cpuid) and
* return the corresponding "id" entry (virtual cpuid)
*/
static processorid_t
{
char isa[MAXNAMELEN];
return ((processorid_t)cpuid);
/*
* convert the physical cpuid to a virtual cpuid
*/
return (-1);
return (-1);
}
vid = -1;
for (i = 0; i < ncpus; i++) {
break;
}
}
return (vid);
}
/*
* if checking for status of a retired page:
* 0 - page is retired
* EAGAIN - page is scheduled for retirement
* EIO - page not scheduled for retirement
* EINVAL - error
*
* if retiring a page:
* 0 - success in retiring page
* EIO - page is already retired
* EAGAIN - page is scheduled for retirement
* EINVAL - error
*
* the original decoder for ioctl() return values is
*/
static int
{
char *fmribuf;
return (EINVAL);
return (EINVAL);
return (EINVAL);
}
NV_ENCODE_NATIVE, 0)) != 0) {
return (EINVAL);
}
if (rc < 0) {
}
return (rc);
}
int
{
char *name;
int ret;
return (EINVAL);
switch (ldom_major_version(lhp)) {
case 0:
/*
* version == 0 means LDOMS support is not available
*/
&cpuid) == 0 &&
return (os_mem_page_retire(lhp,
}
return (EINVAL);
/*NOTREACHED*/
break;
case 1:
/* LDOMS 1.0 */
&cpuid) == 0)
&pa) == 0)
else
} else {
}
return (ret);
/*NOTREACHED*/
break;
default:
break;
}
return (ENOTSUP);
}
int
{
char *name;
int ret;
return (EINVAL);
switch (ldom_major_version(lhp)) {
case 0:
/*
* version == 0 means LDOMS support is not available
*/
&cpuid) == 0 &&
return (os_mem_page_retire(lhp,
}
return (EINVAL);
/*NOTREACHED*/
break;
case 1:
/* LDOMS 1.0 */
&cpuid) == 0)
&pa) == 0)
else
} else {
}
return (ret);
/*NOTREACHED*/
break;
default:
break;
}
return (ENOTSUP);
}
/*
* blacklist cpus in a non-LDOMS environment
*/
int
{
char *name;
if (ldom_major_version(lhp) != 0)
return (0);
return (EINVAL);
char *class;
return (EINVAL);
return (EIO);
NULL) {
return (EINVAL);
}
return (-1);
}
}
return (0);
}
{
switch (ldom_major_version(lhp)) {
case 0:
/*NOTREACHED*/
break;
case 1:
/* LDOMS 1.0 */
return (rv);
} else {
}
/*NOTREACHED*/
break;
default:
break;
}
return (-1);
}
/*
* version 0 means no LDOMS
*/
int
{
return (-1);
if (ldom_getinfo(lhp) == 0)
return (lhp->major_version);
else
return (0);
}
/*
* in the absence of ldoms we are on a single OS instance which is the
* equivalent of the service ldom
*/
int
{
return (-1);
if (ldom_getinfo(lhp) == 0)
return (lhp->service_ldom);
else
return (1);
}
{
if (ldom_pri_init != NULL)
if ((*ldom_pri_init)() < 0)
return (NULL);
if (ldom_pri_fini != NULL)
(*ldom_pri_fini)();
return (NULL);
}
return (lhp);
}
void
{
return;
if (ldom_pri_fini != NULL)
(*ldom_pri_fini)();
}
/* end file */