xref: /illumos-gate/usr/src/uts/i86xpv/io/balloon_drv.c (revision 843e19887f64dde75055cf8842fc4db2171eff45)
1*843e1988Sjohnlev /*
2*843e1988Sjohnlev  * CDDL HEADER START
3*843e1988Sjohnlev  *
4*843e1988Sjohnlev  * The contents of this file are subject to the terms of the
5*843e1988Sjohnlev  * Common Development and Distribution License (the "License").
6*843e1988Sjohnlev  * You may not use this file except in compliance with the License.
7*843e1988Sjohnlev  *
8*843e1988Sjohnlev  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*843e1988Sjohnlev  * or http://www.opensolaris.org/os/licensing.
10*843e1988Sjohnlev  * See the License for the specific language governing permissions
11*843e1988Sjohnlev  * and limitations under the License.
12*843e1988Sjohnlev  *
13*843e1988Sjohnlev  * When distributing Covered Code, include this CDDL HEADER in each
14*843e1988Sjohnlev  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*843e1988Sjohnlev  * If applicable, add the following below this CDDL HEADER, with the
16*843e1988Sjohnlev  * fields enclosed by brackets "[]" replaced with your own identifying
17*843e1988Sjohnlev  * information: Portions Copyright [yyyy] [name of copyright owner]
18*843e1988Sjohnlev  *
19*843e1988Sjohnlev  * CDDL HEADER END
20*843e1988Sjohnlev  */
21*843e1988Sjohnlev 
22*843e1988Sjohnlev /*
23*843e1988Sjohnlev  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24*843e1988Sjohnlev  * Use is subject to license terms.
25*843e1988Sjohnlev  */
26*843e1988Sjohnlev 
27*843e1988Sjohnlev #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*843e1988Sjohnlev 
29*843e1988Sjohnlev /*
30*843e1988Sjohnlev  * A simple wrapper around the balloon kernel thread to allow userland
31*843e1988Sjohnlev  * programs access to the balloon status.
32*843e1988Sjohnlev  */
33*843e1988Sjohnlev 
34*843e1988Sjohnlev #include <sys/types.h>
35*843e1988Sjohnlev #include <sys/file.h>
36*843e1988Sjohnlev #include <sys/errno.h>
37*843e1988Sjohnlev #include <sys/open.h>
38*843e1988Sjohnlev #include <sys/cred.h>
39*843e1988Sjohnlev #include <sys/conf.h>
40*843e1988Sjohnlev #include <sys/stat.h>
41*843e1988Sjohnlev #include <sys/modctl.h>
42*843e1988Sjohnlev #include <sys/ddi.h>
43*843e1988Sjohnlev #include <sys/sunddi.h>
44*843e1988Sjohnlev #include <sys/hypervisor.h>
45*843e1988Sjohnlev #include <sys/sysmacros.h>
46*843e1988Sjohnlev #include <sys/balloon_impl.h>
47*843e1988Sjohnlev 
48*843e1988Sjohnlev static dev_info_t *balloon_devi;
49*843e1988Sjohnlev 
50*843e1988Sjohnlev /*ARGSUSED*/
51*843e1988Sjohnlev static int
52*843e1988Sjohnlev balloon_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result)
53*843e1988Sjohnlev {
54*843e1988Sjohnlev 	if (getminor((dev_t)arg) != BALLOON_MINOR)
55*843e1988Sjohnlev 		return (DDI_FAILURE);
56*843e1988Sjohnlev 
57*843e1988Sjohnlev 	switch (cmd) {
58*843e1988Sjohnlev 	case DDI_INFO_DEVT2DEVINFO:
59*843e1988Sjohnlev 		*result = balloon_devi;
60*843e1988Sjohnlev 		break;
61*843e1988Sjohnlev 	case DDI_INFO_DEVT2INSTANCE:
62*843e1988Sjohnlev 		*result = 0;
63*843e1988Sjohnlev 		break;
64*843e1988Sjohnlev 	default:
65*843e1988Sjohnlev 		return (DDI_FAILURE);
66*843e1988Sjohnlev 	}
67*843e1988Sjohnlev 
68*843e1988Sjohnlev 	return (DDI_SUCCESS);
69*843e1988Sjohnlev }
70*843e1988Sjohnlev 
71*843e1988Sjohnlev static int
72*843e1988Sjohnlev balloon_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
73*843e1988Sjohnlev {
74*843e1988Sjohnlev 	if (cmd != DDI_ATTACH)
75*843e1988Sjohnlev 		return (DDI_FAILURE);
76*843e1988Sjohnlev 
77*843e1988Sjohnlev 	if (ddi_create_minor_node(devi, ddi_get_name(devi), S_IFCHR,
78*843e1988Sjohnlev 	    ddi_get_instance(devi), DDI_PSEUDO, 0) != DDI_SUCCESS)
79*843e1988Sjohnlev 		return (DDI_FAILURE);
80*843e1988Sjohnlev 
81*843e1988Sjohnlev 	balloon_devi = devi;
82*843e1988Sjohnlev 	ddi_report_dev(devi);
83*843e1988Sjohnlev 	return (DDI_SUCCESS);
84*843e1988Sjohnlev }
85*843e1988Sjohnlev 
86*843e1988Sjohnlev static int
87*843e1988Sjohnlev balloon_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
88*843e1988Sjohnlev {
89*843e1988Sjohnlev 	if (cmd != DDI_DETACH)
90*843e1988Sjohnlev 		return (DDI_FAILURE);
91*843e1988Sjohnlev 	ddi_remove_minor_node(devi, NULL);
92*843e1988Sjohnlev 	balloon_devi = NULL;
93*843e1988Sjohnlev 	return (DDI_SUCCESS);
94*843e1988Sjohnlev }
95*843e1988Sjohnlev 
96*843e1988Sjohnlev /*ARGSUSED1*/
97*843e1988Sjohnlev static int
98*843e1988Sjohnlev balloon_open(dev_t *dev, int flag, int otyp, cred_t *cr)
99*843e1988Sjohnlev {
100*843e1988Sjohnlev 	return (getminor(*dev) == BALLOON_MINOR ? 0 : ENXIO);
101*843e1988Sjohnlev }
102*843e1988Sjohnlev 
103*843e1988Sjohnlev /*
104*843e1988Sjohnlev  * When asked for one of the balloon values, we simply query the balloon thread.
105*843e1988Sjohnlev  */
106*843e1988Sjohnlev /*ARGSUSED*/
107*843e1988Sjohnlev static int
108*843e1988Sjohnlev balloon_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
109*843e1988Sjohnlev     int *rval_p)
110*843e1988Sjohnlev {
111*843e1988Sjohnlev 	int rval = 0;
112*843e1988Sjohnlev 	size_t value;
113*843e1988Sjohnlev 
114*843e1988Sjohnlev 	switch (cmd) {
115*843e1988Sjohnlev 	case BLN_IOCTL_CURRENT:
116*843e1988Sjohnlev 	case BLN_IOCTL_TARGET:
117*843e1988Sjohnlev 	case BLN_IOCTL_LOW:
118*843e1988Sjohnlev 	case BLN_IOCTL_HIGH:
119*843e1988Sjohnlev 	case BLN_IOCTL_LIMIT:
120*843e1988Sjohnlev 		value = balloon_values(cmd);
121*843e1988Sjohnlev 		if (ddi_copyout((void *)&value, (void *)arg, sizeof (value),
122*843e1988Sjohnlev 		    mode))
123*843e1988Sjohnlev 			return (EFAULT);
124*843e1988Sjohnlev 		break;
125*843e1988Sjohnlev 	default:
126*843e1988Sjohnlev 		rval = EINVAL;
127*843e1988Sjohnlev 		break;
128*843e1988Sjohnlev 	}
129*843e1988Sjohnlev 	return (rval);
130*843e1988Sjohnlev }
131*843e1988Sjohnlev 
132*843e1988Sjohnlev static struct cb_ops balloon_cb_ops = {
133*843e1988Sjohnlev 	balloon_open,
134*843e1988Sjohnlev 	nulldev,	/* close */
135*843e1988Sjohnlev 	nodev,		/* strategy */
136*843e1988Sjohnlev 	nodev,		/* print */
137*843e1988Sjohnlev 	nodev,		/* dump */
138*843e1988Sjohnlev 	nodev,		/* read */
139*843e1988Sjohnlev 	nodev,		/* write */
140*843e1988Sjohnlev 	balloon_ioctl,	/* ioctl */
141*843e1988Sjohnlev 	nodev,		/* devmap */
142*843e1988Sjohnlev 	nodev,		/* mmap */
143*843e1988Sjohnlev 	nodev,		/* segmap */
144*843e1988Sjohnlev 	nochpoll,	/* poll */
145*843e1988Sjohnlev 	ddi_prop_op,
146*843e1988Sjohnlev 	NULL,
147*843e1988Sjohnlev 	D_64BIT | D_MP,
148*843e1988Sjohnlev 	CB_REV,
149*843e1988Sjohnlev 	NULL,
150*843e1988Sjohnlev 	NULL
151*843e1988Sjohnlev };
152*843e1988Sjohnlev 
153*843e1988Sjohnlev static struct dev_ops balloon_dv_ops = {
154*843e1988Sjohnlev 	DEVO_REV,
155*843e1988Sjohnlev 	0,
156*843e1988Sjohnlev 	balloon_getinfo,
157*843e1988Sjohnlev 	nulldev,	/* identify */
158*843e1988Sjohnlev 	nulldev,	/* probe */
159*843e1988Sjohnlev 	balloon_attach,
160*843e1988Sjohnlev 	balloon_detach,
161*843e1988Sjohnlev 	nodev,		/* reset */
162*843e1988Sjohnlev 	&balloon_cb_ops,
163*843e1988Sjohnlev 	NULL,		/* struct bus_ops */
164*843e1988Sjohnlev 	NULL		/* power */
165*843e1988Sjohnlev };
166*843e1988Sjohnlev 
167*843e1988Sjohnlev static struct modldrv modldrv = {
168*843e1988Sjohnlev 	&mod_driverops,
169*843e1988Sjohnlev 	"balloon driver 1.1",
170*843e1988Sjohnlev 	&balloon_dv_ops
171*843e1988Sjohnlev };
172*843e1988Sjohnlev 
173*843e1988Sjohnlev static struct modlinkage modl = {
174*843e1988Sjohnlev 	MODREV_1,
175*843e1988Sjohnlev 	{
176*843e1988Sjohnlev 		(void *)&modldrv,
177*843e1988Sjohnlev 		NULL		/* null termination */
178*843e1988Sjohnlev 	}
179*843e1988Sjohnlev };
180*843e1988Sjohnlev 
181*843e1988Sjohnlev int
182*843e1988Sjohnlev _init(void)
183*843e1988Sjohnlev {
184*843e1988Sjohnlev 	return (mod_install(&modl));
185*843e1988Sjohnlev }
186*843e1988Sjohnlev 
187*843e1988Sjohnlev int
188*843e1988Sjohnlev _fini(void)
189*843e1988Sjohnlev {
190*843e1988Sjohnlev 	return (mod_remove(&modl));
191*843e1988Sjohnlev }
192*843e1988Sjohnlev 
193*843e1988Sjohnlev int
194*843e1988Sjohnlev _info(struct modinfo *modinfo)
195*843e1988Sjohnlev {
196*843e1988Sjohnlev 	return (mod_info(&modl, modinfo));
197*843e1988Sjohnlev }
198