xref: /titanic_52/usr/src/uts/i86xpv/io/balloon_drv.c (revision 193974072f41a843678abf5f61979c748687e66b)
1843e1988Sjohnlev /*
2843e1988Sjohnlev  * CDDL HEADER START
3843e1988Sjohnlev  *
4843e1988Sjohnlev  * The contents of this file are subject to the terms of the
5843e1988Sjohnlev  * Common Development and Distribution License (the "License").
6843e1988Sjohnlev  * You may not use this file except in compliance with the License.
7843e1988Sjohnlev  *
8843e1988Sjohnlev  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9843e1988Sjohnlev  * or http://www.opensolaris.org/os/licensing.
10843e1988Sjohnlev  * See the License for the specific language governing permissions
11843e1988Sjohnlev  * and limitations under the License.
12843e1988Sjohnlev  *
13843e1988Sjohnlev  * When distributing Covered Code, include this CDDL HEADER in each
14843e1988Sjohnlev  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15843e1988Sjohnlev  * If applicable, add the following below this CDDL HEADER, with the
16843e1988Sjohnlev  * fields enclosed by brackets "[]" replaced with your own identifying
17843e1988Sjohnlev  * information: Portions Copyright [yyyy] [name of copyright owner]
18843e1988Sjohnlev  *
19843e1988Sjohnlev  * CDDL HEADER END
20843e1988Sjohnlev  */
21843e1988Sjohnlev 
22843e1988Sjohnlev /*
23*19397407SSherry Moore  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24843e1988Sjohnlev  * Use is subject to license terms.
25843e1988Sjohnlev  */
26843e1988Sjohnlev 
27843e1988Sjohnlev 
28843e1988Sjohnlev /*
29843e1988Sjohnlev  * A simple wrapper around the balloon kernel thread to allow userland
30843e1988Sjohnlev  * programs access to the balloon status.
31843e1988Sjohnlev  */
32843e1988Sjohnlev 
33843e1988Sjohnlev #include <sys/types.h>
34843e1988Sjohnlev #include <sys/file.h>
35843e1988Sjohnlev #include <sys/errno.h>
36843e1988Sjohnlev #include <sys/open.h>
37843e1988Sjohnlev #include <sys/cred.h>
38843e1988Sjohnlev #include <sys/conf.h>
39843e1988Sjohnlev #include <sys/stat.h>
40843e1988Sjohnlev #include <sys/modctl.h>
41843e1988Sjohnlev #include <sys/ddi.h>
42843e1988Sjohnlev #include <sys/sunddi.h>
43843e1988Sjohnlev #include <sys/hypervisor.h>
44843e1988Sjohnlev #include <sys/sysmacros.h>
45843e1988Sjohnlev #include <sys/balloon_impl.h>
46843e1988Sjohnlev 
47843e1988Sjohnlev static dev_info_t *balloon_devi;
48843e1988Sjohnlev 
49843e1988Sjohnlev /*ARGSUSED*/
50843e1988Sjohnlev static int
51843e1988Sjohnlev balloon_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result)
52843e1988Sjohnlev {
53843e1988Sjohnlev 	if (getminor((dev_t)arg) != BALLOON_MINOR)
54843e1988Sjohnlev 		return (DDI_FAILURE);
55843e1988Sjohnlev 
56843e1988Sjohnlev 	switch (cmd) {
57843e1988Sjohnlev 	case DDI_INFO_DEVT2DEVINFO:
58843e1988Sjohnlev 		*result = balloon_devi;
59843e1988Sjohnlev 		break;
60843e1988Sjohnlev 	case DDI_INFO_DEVT2INSTANCE:
61843e1988Sjohnlev 		*result = 0;
62843e1988Sjohnlev 		break;
63843e1988Sjohnlev 	default:
64843e1988Sjohnlev 		return (DDI_FAILURE);
65843e1988Sjohnlev 	}
66843e1988Sjohnlev 
67843e1988Sjohnlev 	return (DDI_SUCCESS);
68843e1988Sjohnlev }
69843e1988Sjohnlev 
70843e1988Sjohnlev static int
71843e1988Sjohnlev balloon_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
72843e1988Sjohnlev {
73843e1988Sjohnlev 	if (cmd != DDI_ATTACH)
74843e1988Sjohnlev 		return (DDI_FAILURE);
75843e1988Sjohnlev 
76843e1988Sjohnlev 	if (ddi_create_minor_node(devi, ddi_get_name(devi), S_IFCHR,
77843e1988Sjohnlev 	    ddi_get_instance(devi), DDI_PSEUDO, 0) != DDI_SUCCESS)
78843e1988Sjohnlev 		return (DDI_FAILURE);
79843e1988Sjohnlev 
80843e1988Sjohnlev 	balloon_devi = devi;
81843e1988Sjohnlev 	ddi_report_dev(devi);
82843e1988Sjohnlev 	return (DDI_SUCCESS);
83843e1988Sjohnlev }
84843e1988Sjohnlev 
85843e1988Sjohnlev static int
86843e1988Sjohnlev balloon_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
87843e1988Sjohnlev {
88843e1988Sjohnlev 	if (cmd != DDI_DETACH)
89843e1988Sjohnlev 		return (DDI_FAILURE);
90843e1988Sjohnlev 	ddi_remove_minor_node(devi, NULL);
91843e1988Sjohnlev 	balloon_devi = NULL;
92843e1988Sjohnlev 	return (DDI_SUCCESS);
93843e1988Sjohnlev }
94843e1988Sjohnlev 
95843e1988Sjohnlev /*ARGSUSED1*/
96843e1988Sjohnlev static int
97843e1988Sjohnlev balloon_open(dev_t *dev, int flag, int otyp, cred_t *cr)
98843e1988Sjohnlev {
99843e1988Sjohnlev 	return (getminor(*dev) == BALLOON_MINOR ? 0 : ENXIO);
100843e1988Sjohnlev }
101843e1988Sjohnlev 
102843e1988Sjohnlev /*
103843e1988Sjohnlev  * When asked for one of the balloon values, we simply query the balloon thread.
104843e1988Sjohnlev  */
105843e1988Sjohnlev /*ARGSUSED*/
106843e1988Sjohnlev static int
107843e1988Sjohnlev balloon_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
108843e1988Sjohnlev     int *rval_p)
109843e1988Sjohnlev {
110843e1988Sjohnlev 	int rval = 0;
111843e1988Sjohnlev 	size_t value;
112843e1988Sjohnlev 
113843e1988Sjohnlev 	switch (cmd) {
114843e1988Sjohnlev 	case BLN_IOCTL_CURRENT:
115843e1988Sjohnlev 	case BLN_IOCTL_TARGET:
116843e1988Sjohnlev 	case BLN_IOCTL_LOW:
117843e1988Sjohnlev 	case BLN_IOCTL_HIGH:
118843e1988Sjohnlev 	case BLN_IOCTL_LIMIT:
119843e1988Sjohnlev 		value = balloon_values(cmd);
120843e1988Sjohnlev 		if (ddi_copyout((void *)&value, (void *)arg, sizeof (value),
121843e1988Sjohnlev 		    mode))
122843e1988Sjohnlev 			return (EFAULT);
123843e1988Sjohnlev 		break;
124843e1988Sjohnlev 	default:
125843e1988Sjohnlev 		rval = EINVAL;
126843e1988Sjohnlev 		break;
127843e1988Sjohnlev 	}
128843e1988Sjohnlev 	return (rval);
129843e1988Sjohnlev }
130843e1988Sjohnlev 
131843e1988Sjohnlev static struct cb_ops balloon_cb_ops = {
132843e1988Sjohnlev 	balloon_open,
133843e1988Sjohnlev 	nulldev,	/* close */
134843e1988Sjohnlev 	nodev,		/* strategy */
135843e1988Sjohnlev 	nodev,		/* print */
136843e1988Sjohnlev 	nodev,		/* dump */
137843e1988Sjohnlev 	nodev,		/* read */
138843e1988Sjohnlev 	nodev,		/* write */
139843e1988Sjohnlev 	balloon_ioctl,	/* ioctl */
140843e1988Sjohnlev 	nodev,		/* devmap */
141843e1988Sjohnlev 	nodev,		/* mmap */
142843e1988Sjohnlev 	nodev,		/* segmap */
143843e1988Sjohnlev 	nochpoll,	/* poll */
144843e1988Sjohnlev 	ddi_prop_op,
145843e1988Sjohnlev 	NULL,
146843e1988Sjohnlev 	D_64BIT | D_MP,
147843e1988Sjohnlev 	CB_REV,
148843e1988Sjohnlev 	NULL,
149843e1988Sjohnlev 	NULL
150843e1988Sjohnlev };
151843e1988Sjohnlev 
152843e1988Sjohnlev static struct dev_ops balloon_dv_ops = {
153843e1988Sjohnlev 	DEVO_REV,
154843e1988Sjohnlev 	0,
155843e1988Sjohnlev 	balloon_getinfo,
156843e1988Sjohnlev 	nulldev,		/* identify */
157843e1988Sjohnlev 	nulldev,		/* probe */
158843e1988Sjohnlev 	balloon_attach,
159843e1988Sjohnlev 	balloon_detach,
160843e1988Sjohnlev 	nodev,			/* reset */
161843e1988Sjohnlev 	&balloon_cb_ops,
162843e1988Sjohnlev 	NULL,			/* struct bus_ops */
163*19397407SSherry Moore 	NULL,			/* power */
164*19397407SSherry Moore 	ddi_quiesce_not_needed,		/* quiesce */
165843e1988Sjohnlev };
166843e1988Sjohnlev 
167843e1988Sjohnlev static struct modldrv modldrv = {
168843e1988Sjohnlev 	&mod_driverops,
169*19397407SSherry Moore 	"balloon driver",
170843e1988Sjohnlev 	&balloon_dv_ops
171843e1988Sjohnlev };
172843e1988Sjohnlev 
173843e1988Sjohnlev static struct modlinkage modl = {
174843e1988Sjohnlev 	MODREV_1,
175843e1988Sjohnlev 	{
176843e1988Sjohnlev 		(void *)&modldrv,
177843e1988Sjohnlev 		NULL		/* null termination */
178843e1988Sjohnlev 	}
179843e1988Sjohnlev };
180843e1988Sjohnlev 
181843e1988Sjohnlev int
182843e1988Sjohnlev _init(void)
183843e1988Sjohnlev {
184843e1988Sjohnlev 	return (mod_install(&modl));
185843e1988Sjohnlev }
186843e1988Sjohnlev 
187843e1988Sjohnlev int
188843e1988Sjohnlev _fini(void)
189843e1988Sjohnlev {
190843e1988Sjohnlev 	return (mod_remove(&modl));
191843e1988Sjohnlev }
192843e1988Sjohnlev 
193843e1988Sjohnlev int
194843e1988Sjohnlev _info(struct modinfo *modinfo)
195843e1988Sjohnlev {
196843e1988Sjohnlev 	return (mod_info(&modl, modinfo));
197843e1988Sjohnlev }
198