1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * This rather uninspiring device enables userland to discover if
29 * the current kernel is actually a dom0 or other domain e.g. domU.
30 */
31
32#include <sys/types.h>
33#include <sys/file.h>
34#include <sys/errno.h>
35#include <sys/open.h>
36#include <sys/cred.h>
37#include <sys/conf.h>
38#include <sys/stat.h>
39#include <sys/modctl.h>
40#include <sys/ddi.h>
41#include <sys/sunddi.h>
42#include <sys/hypervisor.h>
43#include <sys/sysmacros.h>
44
45#include <sys/domcaps_impl.h>
46
47static dev_info_t *domcaps_devi;
48
49/*ARGSUSED*/
50static int
51domcaps_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result)
52{
53	if (getminor((dev_t)arg) != DOMCAPS_MINOR)
54		return (DDI_FAILURE);
55
56	switch (cmd) {
57	case DDI_INFO_DEVT2DEVINFO:
58		*result = domcaps_devi;
59		break;
60	case DDI_INFO_DEVT2INSTANCE:
61		*result = 0;
62		break;
63	default:
64		return (DDI_FAILURE);
65	}
66
67	return (DDI_SUCCESS);
68}
69
70static int
71domcaps_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
72{
73	if (cmd != DDI_ATTACH)
74		return (DDI_FAILURE);
75
76	if (ddi_create_minor_node(devi, ddi_get_name(devi), S_IFCHR,
77	    ddi_get_instance(devi), DDI_PSEUDO, 0) != DDI_SUCCESS)
78		return (DDI_FAILURE);
79
80	domcaps_devi = devi;
81	ddi_report_dev(devi);
82	return (DDI_SUCCESS);
83}
84
85static int
86domcaps_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
87{
88	if (cmd != DDI_DETACH)
89		return (DDI_FAILURE);
90	ddi_remove_minor_node(devi, NULL);
91	domcaps_devi = NULL;
92	return (DDI_SUCCESS);
93}
94
95/*ARGSUSED1*/
96static int
97domcaps_open(dev_t *dev, int flag, int otyp, cred_t *cr)
98{
99	return (getminor(*dev) == DOMCAPS_MINOR ? 0 : ENXIO);
100}
101
102/*ARGSUSED*/
103static int
104domcaps_read(dev_t dev, uio_t *uio, cred_t *cr)
105{
106	if (DOMAIN_IS_INITDOMAIN(xen_info)) {
107		static char data[] = "control_d\n";
108		size_t nbytes;
109
110		if (uio->uio_loffset > sizeof (data))
111			return (0);
112		nbytes = MIN(uio->uio_resid, sizeof (data) - uio->uio_loffset);
113
114		return (uiomove(data + uio->uio_loffset, nbytes,
115		    UIO_READ, uio));
116	}
117
118	return (0);
119}
120
121static struct cb_ops domcaps_cb_ops = {
122	domcaps_open,
123	nulldev,	/* close */
124	nodev,		/* strategy */
125	nodev,		/* print */
126	nodev,		/* dump */
127	domcaps_read,
128	nodev,		/* write */
129	nodev,		/* ioctl */
130	nodev,		/* devmap */
131	nodev,		/* mmap */
132	nodev,		/* segmap */
133	nochpoll,	/* poll */
134	ddi_prop_op,
135	NULL,
136	D_64BIT | D_MP,
137	CB_REV,
138	NULL,
139	NULL
140};
141
142static struct dev_ops domcaps_dv_ops = {
143	DEVO_REV,
144	0,
145	domcaps_getinfo,
146	nulldev,		/* identify */
147	nulldev,		/* probe */
148	domcaps_attach,
149	domcaps_detach,
150	nodev,			/* reset */
151	&domcaps_cb_ops,
152	NULL,			/* struct bus_ops */
153	NULL,			/* power */
154	ddi_quiesce_not_needed,		/* quiesce */
155};
156
157static struct modldrv modldrv = {
158	&mod_driverops,
159	"hypervisor capabilities driver",
160	&domcaps_dv_ops
161};
162
163static struct modlinkage modl = {
164	MODREV_1,
165	{
166		(void *)&modldrv,
167		NULL		/* null termination */
168	}
169};
170
171int
172_init(void)
173{
174	return (mod_install(&modl));
175}
176
177int
178_fini(void)
179{
180	return (mod_remove(&modl));
181}
182
183int
184_info(struct modinfo *modinfo)
185{
186	return (mod_info(&modl, modinfo));
187}
188