xref: /illumos-gate/usr/src/uts/i86xpv/io/domcaps.c (revision 19397407)
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