/*
* 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.
*/
/*
*
* Driver giving user-space access to the kernel's xenbus connection
* to xenstore.
*
* Copyright (c) 2005, Christian Limpach
* Copyright (c) 2005, Rusty Russell, IBM Corporation
*
* This file may be distributed separately from the Linux kernel, or
* incorporated into other software packages, subject to the following license:
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this source file (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify,
* and to permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <sys/sysmacros.h>
#ifdef XPV_HVM_DRIVER
#include <sys/xpv_support.h>
#endif
#include <sys/hypervisor.h>
#ifdef DEBUG
#else
#endif /* ifdef DEBUG */
/* Some handy macros */
static int xenbusdrv_debug = 0;
struct xenbus_dev_transaction {
};
/* Soft state data structure for xenbus driver */
struct xenbus_dev_data {
/* In-progress transaction. */
/* Partial request. */
unsigned int len;
union {
} u;
/* Response queue. */
int xenstore_inst;
};
static void *xenbusdrv_statep;
uint_t);
const char *);
/* Solaris driver framework */
xenbusdrv_open, /* cb_open */
xenbusdrv_close, /* cb_close */
nodev, /* cb_strategy */
nodev, /* cb_print */
nodev, /* cb_dump */
xenbusdrv_read, /* cb_read */
xenbusdrv_write, /* cb_write */
xenbusdrv_ioctl, /* cb_ioctl */
xenbusdrv_devmap, /* cb_devmap */
NULL, /* cb_mmap */
xenbusdrv_segmap, /* cb_segmap */
nochpoll, /* cb_chpoll */
ddi_prop_op, /* cb_prop_op */
0, /* cb_stream */
};
DEVO_REV, /* devo_rev */
0, /* devo_refcnt */
xenbusdrv_info, /* devo_getinfo */
nulldev, /* devo_identify */
nulldev, /* devo_probe */
xenbusdrv_attach, /* devo_attach */
xenbusdrv_detach, /* devo_detach */
nodev, /* devo_reset */
&xenbusdrv_cb_ops, /* devo_cb_ops */
NULL, /* devo_bus_ops */
NULL, /* devo_power */
ddi_quiesce_not_needed, /* devo_quiesce */
};
&mod_driverops, /* Type of module. This one is a driver */
"virtual bus driver", /* Name of the module. */
&xenbusdrv_dev_ops /* driver ops */
};
&modldrv,
};
int
_init(void)
{
int e;
if (e)
return (e);
e = mod_install(&modlinkage);
if (e)
return (e);
}
int
_fini(void)
{
int e;
e = mod_remove(&modlinkage);
if (e)
return (e);
return (0);
}
int
{
}
/* ARGSUSED */
static int
{
int retval;
switch (cmd) {
case DDI_INFO_DEVT2DEVINFO:
} else {
*result = (void *)xenbusdrv_dip;
}
break;
case DDI_INFO_DEVT2INSTANCE:
*result = (void *)0;
break;
default:
}
return (retval);
}
static int
{
int error;
switch (cmd) {
case DDI_ATTACH:
break;
case DDI_RESUME:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
/* DDI_ATTACH */
/*
* only one instance - but we clone using the open routine
*/
if (ddi_get_instance(dip) > 0)
return (DDI_FAILURE);
NULL);
DDI_PSEUDO, NULL);
if (error != DDI_SUCCESS)
goto fail;
/*
* save dip for getinfo
*/
xenbusdrv_dip = dip;
#ifndef XPV_HVM_DRIVER
if (DOMAIN_IS_INITDOMAIN(xen_info))
xs_dom0_init();
#endif
return (DDI_SUCCESS);
fail:
return (error);
}
static int
{
/*
* again, only one instance
*/
if (ddi_get_instance(dip) > 0)
return (DDI_FAILURE);
switch (cmd) {
case DDI_DETACH:
return (DDI_SUCCESS);
case DDI_SUSPEND:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
}
/* ARGSUSED */
static int
{
return (ENXIO);
/*
* only allow open on minor = 0 - the clone device
*/
if (minor != 0)
return (ENXIO);
/*
* find a free slot and grab it
*/
if (xenbusdrv_clone_tab[minor] == 0) {
break;
}
}
if (minor == XENBUSDRV_NCLONES)
return (EAGAIN);
/* Allocate softstate structure */
xenbusdrv_clone_tab[minor] = 0;
return (EAGAIN);
}
/* ... and init it */
/* clone driver */
minor));
return (0);
}
/* ARGSUSED */
static int
{
return (ENXIO);
#ifdef notyet
/*
* XXPV - would like to be able to notify xenstore down here, but
* as the daemon is currently written, it doesn't leave the device
* open after initial setup, so we have no way of knowing if it has
* gone away.
*/
if (xbs->xenstore_inst)
#endif
/* free pending transaction */
while (trans = (struct xenbus_dev_transaction *)
}
/*
* free clone tab slot
*/
xenbusdrv_clone_tab[minor] = 0;
minor));
return (0);
}
/* ARGSUSED */
static int
{
int idx;
if (secpolicy_xvm_control(cr))
return (EPERM);
/* check if we have something to read */
return (EINTR);
}
}
return (ret);
}
/*
* prepare data for xenbusdrv_read()
*/
static int
const char *reply)
{
int i;
int remaining;
return (EOVERFLOW);
}
((char *)msg)[i];
}
reply[i];
}
return (0);
}
/* ARGSUSED */
static int
{
void *reply;
int rc = 0;
if (secpolicy_xvm_control(cr))
return (EPERM);
goto out;
}
goto out;
}
return (0);
}
case XS_TRANSACTION_START:
case XS_TRANSACTION_END:
case XS_DIRECTORY:
case XS_READ:
case XS_GET_PERMS:
case XS_RELEASE:
case XS_GET_DOMAIN_PATH:
case XS_WRITE:
case XS_MKDIR:
case XS_RM:
case XS_SET_PERMS:
/* send the request to xenstore and get feedback */
if (rc) {
"xenbus_dev_request_and_reply failed"));
goto out;
}
/* try to find out the ending transaction */
for (trans = (struct xenbus_dev_transaction *)
trans = (struct xenbus_dev_transaction *)
break;
/* free it, if we find it */
}
/* prepare data for xenbusdrv_read() to get */
break;
default:
}
out:
return (rc);
}
/*ARGSUSED*/
static int
{
int err;
return (-1);
if (!DOMAIN_IS_INITDOMAIN(xen_info))
return (-1);
if (err)
return (err);
return (0);
}
static int
{
if (secpolicy_xvm_control(cr))
return (EPERM);
}
/*ARGSUSED*/
static int
int *rvalp)
{
if (secpolicy_xvm_control(cr))
return (EPERM);
switch (cmd) {
break;
case IOCTL_XENBUS_NOTIFY_UP:
break;
default:
return (EINVAL);
}
return (0);
}