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
balloon_getinfo(dev_info_t * devi,ddi_info_cmd_t cmd,void * arg,void ** result)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
balloon_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)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
balloon_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)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
balloon_open(dev_t * dev,int flag,int otyp,cred_t * cr)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
balloon_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cr,int * rval_p)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,
156*19397407SSherry Moore nulldev, /* identify */
157*19397407SSherry Moore nulldev, /* probe */
158843e1988Sjohnlev balloon_attach,
159843e1988Sjohnlev balloon_detach,
160*19397407SSherry Moore nodev, /* reset */
161843e1988Sjohnlev &balloon_cb_ops,
162*19397407SSherry Moore 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
_init(void)182843e1988Sjohnlev _init(void)
183843e1988Sjohnlev {
184843e1988Sjohnlev return (mod_install(&modl));
185843e1988Sjohnlev }
186843e1988Sjohnlev
187843e1988Sjohnlev int
_fini(void)188843e1988Sjohnlev _fini(void)
189843e1988Sjohnlev {
190843e1988Sjohnlev return (mod_remove(&modl));
191843e1988Sjohnlev }
192843e1988Sjohnlev
193843e1988Sjohnlev int
_info(struct modinfo * modinfo)194843e1988Sjohnlev _info(struct modinfo *modinfo)
195843e1988Sjohnlev {
196843e1988Sjohnlev return (mod_info(&modl, modinfo));
197843e1988Sjohnlev }
198