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 /*
23613b2871SRichard Bean * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24843e1988Sjohnlev * Use is subject to license terms.
25843e1988Sjohnlev */
26843e1988Sjohnlev
27843e1988Sjohnlev /*
28843e1988Sjohnlev * This rather uninspiring device enables userland to discover if
29843e1988Sjohnlev * the current kernel is actually a dom0 or other domain e.g. domU.
30843e1988Sjohnlev */
31843e1988Sjohnlev
32843e1988Sjohnlev #include <sys/types.h>
33843e1988Sjohnlev #include <sys/file.h>
34843e1988Sjohnlev #include <sys/errno.h>
35843e1988Sjohnlev #include <sys/open.h>
36843e1988Sjohnlev #include <sys/cred.h>
37843e1988Sjohnlev #include <sys/conf.h>
38843e1988Sjohnlev #include <sys/stat.h>
39843e1988Sjohnlev #include <sys/modctl.h>
40843e1988Sjohnlev #include <sys/ddi.h>
41843e1988Sjohnlev #include <sys/sunddi.h>
42843e1988Sjohnlev #include <sys/hypervisor.h>
43843e1988Sjohnlev #include <sys/sysmacros.h>
44843e1988Sjohnlev
45843e1988Sjohnlev #include <sys/domcaps_impl.h>
46843e1988Sjohnlev
47843e1988Sjohnlev static dev_info_t *domcaps_devi;
48843e1988Sjohnlev
49843e1988Sjohnlev /*ARGSUSED*/
50843e1988Sjohnlev static int
domcaps_getinfo(dev_info_t * devi,ddi_info_cmd_t cmd,void * arg,void ** result)51843e1988Sjohnlev domcaps_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result)
52843e1988Sjohnlev {
53843e1988Sjohnlev if (getminor((dev_t)arg) != DOMCAPS_MINOR)
54843e1988Sjohnlev return (DDI_FAILURE);
55843e1988Sjohnlev
56843e1988Sjohnlev switch (cmd) {
57843e1988Sjohnlev case DDI_INFO_DEVT2DEVINFO:
58843e1988Sjohnlev *result = domcaps_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
domcaps_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)71843e1988Sjohnlev domcaps_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 domcaps_devi = devi;
81843e1988Sjohnlev ddi_report_dev(devi);
82843e1988Sjohnlev return (DDI_SUCCESS);
83843e1988Sjohnlev }
84843e1988Sjohnlev
85843e1988Sjohnlev static int
domcaps_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)86843e1988Sjohnlev domcaps_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 domcaps_devi = NULL;
92843e1988Sjohnlev return (DDI_SUCCESS);
93843e1988Sjohnlev }
94843e1988Sjohnlev
95843e1988Sjohnlev /*ARGSUSED1*/
96843e1988Sjohnlev static int
domcaps_open(dev_t * dev,int flag,int otyp,cred_t * cr)97843e1988Sjohnlev domcaps_open(dev_t *dev, int flag, int otyp, cred_t *cr)
98843e1988Sjohnlev {
99843e1988Sjohnlev return (getminor(*dev) == DOMCAPS_MINOR ? 0 : ENXIO);
100843e1988Sjohnlev }
101843e1988Sjohnlev
102843e1988Sjohnlev /*ARGSUSED*/
103843e1988Sjohnlev static int
domcaps_read(dev_t dev,uio_t * uio,cred_t * cr)104843e1988Sjohnlev domcaps_read(dev_t dev, uio_t *uio, cred_t *cr)
105843e1988Sjohnlev {
106843e1988Sjohnlev if (DOMAIN_IS_INITDOMAIN(xen_info)) {
107843e1988Sjohnlev static char data[] = "control_d\n";
108843e1988Sjohnlev size_t nbytes;
109843e1988Sjohnlev
110843e1988Sjohnlev if (uio->uio_loffset > sizeof (data))
111843e1988Sjohnlev return (0);
112843e1988Sjohnlev nbytes = MIN(uio->uio_resid, sizeof (data) - uio->uio_loffset);
113843e1988Sjohnlev
114843e1988Sjohnlev return (uiomove(data + uio->uio_loffset, nbytes,
115843e1988Sjohnlev UIO_READ, uio));
116843e1988Sjohnlev }
117843e1988Sjohnlev
118843e1988Sjohnlev return (0);
119843e1988Sjohnlev }
120843e1988Sjohnlev
121843e1988Sjohnlev static struct cb_ops domcaps_cb_ops = {
122843e1988Sjohnlev domcaps_open,
123843e1988Sjohnlev nulldev, /* close */
124843e1988Sjohnlev nodev, /* strategy */
125843e1988Sjohnlev nodev, /* print */
126843e1988Sjohnlev nodev, /* dump */
127843e1988Sjohnlev domcaps_read,
128843e1988Sjohnlev nodev, /* write */
129843e1988Sjohnlev nodev, /* ioctl */
130843e1988Sjohnlev nodev, /* devmap */
131843e1988Sjohnlev nodev, /* mmap */
132843e1988Sjohnlev nodev, /* segmap */
133843e1988Sjohnlev nochpoll, /* poll */
134843e1988Sjohnlev ddi_prop_op,
135843e1988Sjohnlev NULL,
136843e1988Sjohnlev D_64BIT | D_MP,
137843e1988Sjohnlev CB_REV,
138843e1988Sjohnlev NULL,
139843e1988Sjohnlev NULL
140843e1988Sjohnlev };
141843e1988Sjohnlev
142843e1988Sjohnlev static struct dev_ops domcaps_dv_ops = {
143843e1988Sjohnlev DEVO_REV,
144843e1988Sjohnlev 0,
145843e1988Sjohnlev domcaps_getinfo,
146*19397407SSherry Moore nulldev, /* identify */
147*19397407SSherry Moore nulldev, /* probe */
148843e1988Sjohnlev domcaps_attach,
149843e1988Sjohnlev domcaps_detach,
150*19397407SSherry Moore nodev, /* reset */
151843e1988Sjohnlev &domcaps_cb_ops,
152*19397407SSherry Moore NULL, /* struct bus_ops */
153*19397407SSherry Moore NULL, /* power */
154*19397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */
155843e1988Sjohnlev };
156843e1988Sjohnlev
157843e1988Sjohnlev static struct modldrv modldrv = {
158843e1988Sjohnlev &mod_driverops,
159613b2871SRichard Bean "hypervisor capabilities driver",
160843e1988Sjohnlev &domcaps_dv_ops
161843e1988Sjohnlev };
162843e1988Sjohnlev
163843e1988Sjohnlev static struct modlinkage modl = {
164843e1988Sjohnlev MODREV_1,
165843e1988Sjohnlev {
166843e1988Sjohnlev (void *)&modldrv,
167843e1988Sjohnlev NULL /* null termination */
168843e1988Sjohnlev }
169843e1988Sjohnlev };
170843e1988Sjohnlev
171843e1988Sjohnlev int
_init(void)172843e1988Sjohnlev _init(void)
173843e1988Sjohnlev {
174843e1988Sjohnlev return (mod_install(&modl));
175843e1988Sjohnlev }
176843e1988Sjohnlev
177843e1988Sjohnlev int
_fini(void)178843e1988Sjohnlev _fini(void)
179843e1988Sjohnlev {
180843e1988Sjohnlev return (mod_remove(&modl));
181843e1988Sjohnlev }
182843e1988Sjohnlev
183843e1988Sjohnlev int
_info(struct modinfo * modinfo)184843e1988Sjohnlev _info(struct modinfo *modinfo)
185843e1988Sjohnlev {
186843e1988Sjohnlev return (mod_info(&modl, modinfo));
187843e1988Sjohnlev }
188