xenstore_dev.c revision 181624
1181624Skmacy/*
2181624Skmacy * xenbus_dev.c
3181624Skmacy *
4181624Skmacy * Driver giving user-space access to the kernel's xenbus connection
5181624Skmacy * to xenstore.
6181624Skmacy *
7181624Skmacy * Copyright (c) 2005, Christian Limpach
8181624Skmacy * Copyright (c) 2005, Rusty Russell, IBM Corporation
9181624Skmacy *
10181624Skmacy * This file may be distributed separately from the Linux kernel, or
11181624Skmacy * incorporated into other software packages, subject to the following license:
12181624Skmacy *
13181624Skmacy * Permission is hereby granted, free of charge, to any person obtaining a copy
14181624Skmacy * of this source file (the "Software"), to deal in the Software without
15181624Skmacy * restriction, including without limitation the rights to use, copy, modify,
16181624Skmacy * merge, publish, distribute, sublicense, and/or sell copies of the Software,
17181624Skmacy * and to permit persons to whom the Software is furnished to do so, subject to
18181624Skmacy * the following conditions:
19181624Skmacy *
20181624Skmacy * The above copyright notice and this permission notice shall be included in
21181624Skmacy * all copies or substantial portions of the Software.
22181624Skmacy *
23181624Skmacy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24181624Skmacy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25181624Skmacy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26181624Skmacy * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27181624Skmacy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28181624Skmacy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29181624Skmacy * IN THE SOFTWARE.
30181624Skmacy */
31181624Skmacy
32181624Skmacy
33181624Skmacy#include <sys/cdefs.h>
34181624Skmacy__FBSDID("$FreeBSD: head/sys/xen/xenbus/xenbus_dev.c 181624 2008-08-12 07:36:56Z kmacy $");
35181624Skmacy
36181624Skmacy#include <sys/types.h>
37181624Skmacy#include <sys/cdefs.h>
38181624Skmacy#include <sys/errno.h>
39181624Skmacy#include <sys/uio.h>
40181624Skmacy#include <sys/param.h>
41181624Skmacy#include <sys/systm.h>
42181624Skmacy#include <sys/proc.h>
43181624Skmacy#include <sys/kernel.h>
44181624Skmacy#include <sys/malloc.h>
45181624Skmacy#include <sys/conf.h>
46181624Skmacy
47181624Skmacy
48181624Skmacy#include <machine/xen/hypervisor.h>
49181624Skmacy#include <machine/xen/xenbus.h>
50181624Skmacy#include <machine/xen/hypervisor.h>
51181624Skmacy#include <xen/xenbus/xenbus_comms.h>
52181624Skmacy
53181624Skmacy
54181624Skmacy
55181624Skmacy
56181624Skmacy#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK)
57181624Skmacy#define BUG_ON        PANIC_IF
58181624Skmacy#define semaphore     sema
59181624Skmacy#define rw_semaphore  sema
60181624Skmacy#define spin_lock     mtx_lock
61181624Skmacy#define spin_unlock   mtx_unlock
62181624Skmacy#define DEFINE_SPINLOCK(lock) struct mtx lock
63181624Skmacy#define DECLARE_MUTEX(lock) struct sema lock
64181624Skmacy#define u32           uint32_t
65181624Skmacy#define simple_strtoul strtoul
66181624Skmacy
67181624Skmacystruct xenbus_dev_transaction {
68181624Skmacy	LIST_ENTRY(xenbus_dev_transaction) list;
69181624Skmacy	struct xenbus_transaction handle;
70181624Skmacy};
71181624Skmacy
72181624Skmacystruct xenbus_dev_data {
73181624Skmacy	/* In-progress transaction. */
74181624Skmacy	LIST_HEAD(xdd_list_head, xenbus_dev_transaction) transactions;
75181624Skmacy
76181624Skmacy	/* Partial request. */
77181624Skmacy	unsigned int len;
78181624Skmacy	union {
79181624Skmacy		struct xsd_sockmsg msg;
80181624Skmacy		char buffer[PAGE_SIZE];
81181624Skmacy	} u;
82181624Skmacy
83181624Skmacy	/* Response queue. */
84181624Skmacy#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1))
85181624Skmacy	char read_buffer[PAGE_SIZE];
86181624Skmacy	unsigned int read_cons, read_prod;
87181624Skmacy	int read_waitq;
88181624Skmacy};
89181624Skmacy#if 0
90181624Skmacystatic struct proc_dir_entry *xenbus_dev_intf;
91181624Skmacy#endif
92181624Skmacystatic int
93181624Skmacyxenbus_dev_read(struct cdev *dev, struct uio *uio, int ioflag)
94181624Skmacy{
95181624Skmacy	int i = 0;
96181624Skmacy	struct xenbus_dev_data *u = dev->si_drv1;
97181624Skmacy
98181624Skmacy	if (wait_event_interruptible(&u->read_waitq,
99181624Skmacy				     u->read_prod != u->read_cons))
100181624Skmacy		return EINTR;
101181624Skmacy
102181624Skmacy	for (i = 0; i < uio->uio_iov[0].iov_len; i++) {
103181624Skmacy		if (u->read_cons == u->read_prod)
104181624Skmacy			break;
105181624Skmacy		copyout(&u->read_buffer[MASK_READ_IDX(u->read_cons)], (char *)uio->uio_iov[0].iov_base+i, 1);
106181624Skmacy		u->read_cons++;
107181624Skmacy		uio->uio_resid--;
108181624Skmacy	}
109181624Skmacy	return 0;
110181624Skmacy}
111181624Skmacy
112181624Skmacystatic void queue_reply(struct xenbus_dev_data *u,
113181624Skmacy			char *data, unsigned int len)
114181624Skmacy{
115181624Skmacy	int i;
116181624Skmacy
117181624Skmacy	for (i = 0; i < len; i++, u->read_prod++)
118181624Skmacy		u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
119181624Skmacy
120181624Skmacy	BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
121181624Skmacy
122181624Skmacy	wakeup(&u->read_waitq);
123181624Skmacy}
124181624Skmacy
125181624Skmacystatic int
126181624Skmacyxenbus_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
127181624Skmacy{
128181624Skmacy	int err = 0;
129181624Skmacy	struct xenbus_dev_data *u = dev->si_drv1;
130181624Skmacy	struct xenbus_dev_transaction *trans;
131181624Skmacy	void *reply;
132181624Skmacy	int len = uio->uio_iov[0].iov_len;
133181624Skmacy
134181624Skmacy	if ((len + u->len) > sizeof(u->u.buffer))
135181624Skmacy		return EINVAL;
136181624Skmacy
137181624Skmacy	if (copyin(u->u.buffer + u->len, uio->uio_iov[0].iov_base, len) != 0)
138181624Skmacy		return EFAULT;
139181624Skmacy
140181624Skmacy	u->len += len;
141181624Skmacy	if (u->len < (sizeof(u->u.msg) + u->u.msg.len))
142181624Skmacy		return len;
143181624Skmacy
144181624Skmacy	switch (u->u.msg.type) {
145181624Skmacy	case XS_TRANSACTION_START:
146181624Skmacy	case XS_TRANSACTION_END:
147181624Skmacy	case XS_DIRECTORY:
148181624Skmacy	case XS_READ:
149181624Skmacy	case XS_GET_PERMS:
150181624Skmacy	case XS_RELEASE:
151181624Skmacy	case XS_GET_DOMAIN_PATH:
152181624Skmacy	case XS_WRITE:
153181624Skmacy	case XS_MKDIR:
154181624Skmacy	case XS_RM:
155181624Skmacy	case XS_SET_PERMS:
156181624Skmacy		reply = xenbus_dev_request_and_reply(&u->u.msg);
157181624Skmacy		if (IS_ERR(reply)) {
158181624Skmacy			err = PTR_ERR(reply);
159181624Skmacy		} else {
160181624Skmacy			if (u->u.msg.type == XS_TRANSACTION_START) {
161181624Skmacy				trans = kmalloc(sizeof(*trans), GFP_KERNEL);
162181624Skmacy				trans->handle.id = simple_strtoul(reply, NULL, 0);
163181624Skmacy				LIST_INSERT_HEAD(&u->transactions, trans, list);
164181624Skmacy			} else if (u->u.msg.type == XS_TRANSACTION_END) {
165181624Skmacy				LIST_FOREACH(trans, &u->transactions,
166181624Skmacy					     list)
167181624Skmacy					if (trans->handle.id ==
168181624Skmacy					    u->u.msg.tx_id)
169181624Skmacy						break;
170181624Skmacy#if 0 /* XXX does this mean the list is empty? */
171181624Skmacy				BUG_ON(&trans->list == &u->transactions);
172181624Skmacy#endif
173181624Skmacy				LIST_REMOVE(trans, list);
174181624Skmacy				kfree(trans);
175181624Skmacy			}
176181624Skmacy			queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
177181624Skmacy			queue_reply(u, (char *)reply, u->u.msg.len);
178181624Skmacy			kfree(reply);
179181624Skmacy		}
180181624Skmacy		break;
181181624Skmacy
182181624Skmacy	default:
183181624Skmacy		err = EINVAL;
184181624Skmacy		break;
185181624Skmacy	}
186181624Skmacy
187181624Skmacy	if (err == 0) {
188181624Skmacy		u->len = 0;
189181624Skmacy		err = len;
190181624Skmacy	}
191181624Skmacy
192181624Skmacy	return err;
193181624Skmacy}
194181624Skmacy
195181624Skmacystatic int xenbus_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
196181624Skmacy{
197181624Skmacy	struct xenbus_dev_data *u;
198181624Skmacy
199181624Skmacy	if (xen_start_info->store_evtchn == 0)
200181624Skmacy		return ENOENT;
201181624Skmacy#if 0 /* XXX figure out if equiv needed */
202181624Skmacy	nonseekable_open(inode, filp);
203181624Skmacy#endif
204181624Skmacy	u = kmalloc(sizeof(*u), GFP_KERNEL);
205181624Skmacy	if (u == NULL)
206181624Skmacy		return ENOMEM;
207181624Skmacy
208181624Skmacy	memset(u, 0, sizeof(*u));
209181624Skmacy	LIST_INIT(&u->transactions);
210181624Skmacy
211181624Skmacy        dev->si_drv1 = u;
212181624Skmacy
213181624Skmacy	return 0;
214181624Skmacy}
215181624Skmacy
216181624Skmacystatic int xenbus_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
217181624Skmacy{
218181624Skmacy	struct xenbus_dev_data *u = dev->si_drv1;
219181624Skmacy	struct xenbus_dev_transaction *trans, *tmp;
220181624Skmacy
221181624Skmacy	LIST_FOREACH_SAFE(trans, &u->transactions, list, tmp) {
222181624Skmacy		xenbus_transaction_end(trans->handle, 1);
223181624Skmacy		LIST_REMOVE(trans, list);
224181624Skmacy		kfree(trans);
225181624Skmacy	}
226181624Skmacy
227181624Skmacy	kfree(u);
228181624Skmacy	return 0;
229181624Skmacy}
230181624Skmacy
231181624Skmacystatic struct cdevsw xenbus_dev_cdevsw = {
232181624Skmacy	.d_version = D_VERSION,
233181624Skmacy	.d_read = xenbus_dev_read,
234181624Skmacy	.d_write = xenbus_dev_write,
235181624Skmacy	.d_open = xenbus_dev_open,
236181624Skmacy	.d_close = xenbus_dev_close,
237181624Skmacy	.d_name = "xenbus_dev",
238181624Skmacy};
239181624Skmacy
240181624Skmacystatic int
241181624Skmacyxenbus_dev_sysinit(void)
242181624Skmacy{
243181624Skmacy	make_dev(&xenbus_dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0400, "xenbus");
244181624Skmacy
245181624Skmacy	return 0;
246181624Skmacy}
247181624SkmacySYSINIT(xenbus_dev_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, xenbus_dev_sysinit, NULL);
248181624Skmacy/* SYSINIT NEEDED XXX */
249181624Skmacy
250181624Skmacy
251181624Skmacy
252181624Skmacy/*
253181624Skmacy * Local variables:
254181624Skmacy *  c-file-style: "linux"
255181624Skmacy *  indent-tabs-mode: t
256181624Skmacy *  c-indent-level: 8
257181624Skmacy *  c-basic-offset: 8
258181624Skmacy *  tab-width: 8
259181624Skmacy * End:
260181624Skmacy */
261