xref: /onnv-gate/usr/src/uts/i86xpv/io/balloon_drv.c (revision 7656:2621e50fdf4a)
15084Sjohnlev /*
25084Sjohnlev  * CDDL HEADER START
35084Sjohnlev  *
45084Sjohnlev  * The contents of this file are subject to the terms of the
55084Sjohnlev  * Common Development and Distribution License (the "License").
65084Sjohnlev  * You may not use this file except in compliance with the License.
75084Sjohnlev  *
85084Sjohnlev  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95084Sjohnlev  * or http://www.opensolaris.org/os/licensing.
105084Sjohnlev  * See the License for the specific language governing permissions
115084Sjohnlev  * and limitations under the License.
125084Sjohnlev  *
135084Sjohnlev  * When distributing Covered Code, include this CDDL HEADER in each
145084Sjohnlev  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155084Sjohnlev  * If applicable, add the following below this CDDL HEADER, with the
165084Sjohnlev  * fields enclosed by brackets "[]" replaced with your own identifying
175084Sjohnlev  * information: Portions Copyright [yyyy] [name of copyright owner]
185084Sjohnlev  *
195084Sjohnlev  * CDDL HEADER END
205084Sjohnlev  */
215084Sjohnlev 
225084Sjohnlev /*
23*7656SSherry.Moore@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
245084Sjohnlev  * Use is subject to license terms.
255084Sjohnlev  */
265084Sjohnlev 
275084Sjohnlev 
285084Sjohnlev /*
295084Sjohnlev  * A simple wrapper around the balloon kernel thread to allow userland
305084Sjohnlev  * programs access to the balloon status.
315084Sjohnlev  */
325084Sjohnlev 
335084Sjohnlev #include <sys/types.h>
345084Sjohnlev #include <sys/file.h>
355084Sjohnlev #include <sys/errno.h>
365084Sjohnlev #include <sys/open.h>
375084Sjohnlev #include <sys/cred.h>
385084Sjohnlev #include <sys/conf.h>
395084Sjohnlev #include <sys/stat.h>
405084Sjohnlev #include <sys/modctl.h>
415084Sjohnlev #include <sys/ddi.h>
425084Sjohnlev #include <sys/sunddi.h>
435084Sjohnlev #include <sys/hypervisor.h>
445084Sjohnlev #include <sys/sysmacros.h>
455084Sjohnlev #include <sys/balloon_impl.h>
465084Sjohnlev 
475084Sjohnlev static dev_info_t *balloon_devi;
485084Sjohnlev 
495084Sjohnlev /*ARGSUSED*/
505084Sjohnlev static int
balloon_getinfo(dev_info_t * devi,ddi_info_cmd_t cmd,void * arg,void ** result)515084Sjohnlev balloon_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result)
525084Sjohnlev {
535084Sjohnlev 	if (getminor((dev_t)arg) != BALLOON_MINOR)
545084Sjohnlev 		return (DDI_FAILURE);
555084Sjohnlev 
565084Sjohnlev 	switch (cmd) {
575084Sjohnlev 	case DDI_INFO_DEVT2DEVINFO:
585084Sjohnlev 		*result = balloon_devi;
595084Sjohnlev 		break;
605084Sjohnlev 	case DDI_INFO_DEVT2INSTANCE:
615084Sjohnlev 		*result = 0;
625084Sjohnlev 		break;
635084Sjohnlev 	default:
645084Sjohnlev 		return (DDI_FAILURE);
655084Sjohnlev 	}
665084Sjohnlev 
675084Sjohnlev 	return (DDI_SUCCESS);
685084Sjohnlev }
695084Sjohnlev 
705084Sjohnlev static int
balloon_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)715084Sjohnlev balloon_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
725084Sjohnlev {
735084Sjohnlev 	if (cmd != DDI_ATTACH)
745084Sjohnlev 		return (DDI_FAILURE);
755084Sjohnlev 
765084Sjohnlev 	if (ddi_create_minor_node(devi, ddi_get_name(devi), S_IFCHR,
775084Sjohnlev 	    ddi_get_instance(devi), DDI_PSEUDO, 0) != DDI_SUCCESS)
785084Sjohnlev 		return (DDI_FAILURE);
795084Sjohnlev 
805084Sjohnlev 	balloon_devi = devi;
815084Sjohnlev 	ddi_report_dev(devi);
825084Sjohnlev 	return (DDI_SUCCESS);
835084Sjohnlev }
845084Sjohnlev 
855084Sjohnlev static int
balloon_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)865084Sjohnlev balloon_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
875084Sjohnlev {
885084Sjohnlev 	if (cmd != DDI_DETACH)
895084Sjohnlev 		return (DDI_FAILURE);
905084Sjohnlev 	ddi_remove_minor_node(devi, NULL);
915084Sjohnlev 	balloon_devi = NULL;
925084Sjohnlev 	return (DDI_SUCCESS);
935084Sjohnlev }
945084Sjohnlev 
955084Sjohnlev /*ARGSUSED1*/
965084Sjohnlev static int
balloon_open(dev_t * dev,int flag,int otyp,cred_t * cr)975084Sjohnlev balloon_open(dev_t *dev, int flag, int otyp, cred_t *cr)
985084Sjohnlev {
995084Sjohnlev 	return (getminor(*dev) == BALLOON_MINOR ? 0 : ENXIO);
1005084Sjohnlev }
1015084Sjohnlev 
1025084Sjohnlev /*
1035084Sjohnlev  * When asked for one of the balloon values, we simply query the balloon thread.
1045084Sjohnlev  */
1055084Sjohnlev /*ARGSUSED*/
1065084Sjohnlev static int
balloon_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cr,int * rval_p)1075084Sjohnlev balloon_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
1085084Sjohnlev     int *rval_p)
1095084Sjohnlev {
1105084Sjohnlev 	int rval = 0;
1115084Sjohnlev 	size_t value;
1125084Sjohnlev 
1135084Sjohnlev 	switch (cmd) {
1145084Sjohnlev 	case BLN_IOCTL_CURRENT:
1155084Sjohnlev 	case BLN_IOCTL_TARGET:
1165084Sjohnlev 	case BLN_IOCTL_LOW:
1175084Sjohnlev 	case BLN_IOCTL_HIGH:
1185084Sjohnlev 	case BLN_IOCTL_LIMIT:
1195084Sjohnlev 		value = balloon_values(cmd);
1205084Sjohnlev 		if (ddi_copyout((void *)&value, (void *)arg, sizeof (value),
1215084Sjohnlev 		    mode))
1225084Sjohnlev 			return (EFAULT);
1235084Sjohnlev 		break;
1245084Sjohnlev 	default:
1255084Sjohnlev 		rval = EINVAL;
1265084Sjohnlev 		break;
1275084Sjohnlev 	}
1285084Sjohnlev 	return (rval);
1295084Sjohnlev }
1305084Sjohnlev 
1315084Sjohnlev static struct cb_ops balloon_cb_ops = {
1325084Sjohnlev 	balloon_open,
1335084Sjohnlev 	nulldev,	/* close */
1345084Sjohnlev 	nodev,		/* strategy */
1355084Sjohnlev 	nodev,		/* print */
1365084Sjohnlev 	nodev,		/* dump */
1375084Sjohnlev 	nodev,		/* read */
1385084Sjohnlev 	nodev,		/* write */
1395084Sjohnlev 	balloon_ioctl,	/* ioctl */
1405084Sjohnlev 	nodev,		/* devmap */
1415084Sjohnlev 	nodev,		/* mmap */
1425084Sjohnlev 	nodev,		/* segmap */
1435084Sjohnlev 	nochpoll,	/* poll */
1445084Sjohnlev 	ddi_prop_op,
1455084Sjohnlev 	NULL,
1465084Sjohnlev 	D_64BIT | D_MP,
1475084Sjohnlev 	CB_REV,
1485084Sjohnlev 	NULL,
1495084Sjohnlev 	NULL
1505084Sjohnlev };
1515084Sjohnlev 
1525084Sjohnlev static struct dev_ops balloon_dv_ops = {
1535084Sjohnlev 	DEVO_REV,
1545084Sjohnlev 	0,
1555084Sjohnlev 	balloon_getinfo,
156*7656SSherry.Moore@Sun.COM 	nulldev,		/* identify */
157*7656SSherry.Moore@Sun.COM 	nulldev,		/* probe */
1585084Sjohnlev 	balloon_attach,
1595084Sjohnlev 	balloon_detach,
160*7656SSherry.Moore@Sun.COM 	nodev,			/* reset */
1615084Sjohnlev 	&balloon_cb_ops,
162*7656SSherry.Moore@Sun.COM 	NULL,			/* struct bus_ops */
163*7656SSherry.Moore@Sun.COM 	NULL,			/* power */
164*7656SSherry.Moore@Sun.COM 	ddi_quiesce_not_needed,		/* quiesce */
1655084Sjohnlev };
1665084Sjohnlev 
1675084Sjohnlev static struct modldrv modldrv = {
1685084Sjohnlev 	&mod_driverops,
169*7656SSherry.Moore@Sun.COM 	"balloon driver",
1705084Sjohnlev 	&balloon_dv_ops
1715084Sjohnlev };
1725084Sjohnlev 
1735084Sjohnlev static struct modlinkage modl = {
1745084Sjohnlev 	MODREV_1,
1755084Sjohnlev 	{
1765084Sjohnlev 		(void *)&modldrv,
1775084Sjohnlev 		NULL		/* null termination */
1785084Sjohnlev 	}
1795084Sjohnlev };
1805084Sjohnlev 
1815084Sjohnlev int
_init(void)1825084Sjohnlev _init(void)
1835084Sjohnlev {
1845084Sjohnlev 	return (mod_install(&modl));
1855084Sjohnlev }
1865084Sjohnlev 
1875084Sjohnlev int
_fini(void)1885084Sjohnlev _fini(void)
1895084Sjohnlev {
1905084Sjohnlev 	return (mod_remove(&modl));
1915084Sjohnlev }
1925084Sjohnlev 
1935084Sjohnlev int
_info(struct modinfo * modinfo)1945084Sjohnlev _info(struct modinfo *modinfo)
1955084Sjohnlev {
1965084Sjohnlev 	return (mod_info(&modl, modinfo));
1975084Sjohnlev }
198