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