diff -r 832aac894efd drivers/xen/Kconfig --- a/drivers/xen/Kconfig Wed Nov 19 13:15:46 2008 +0000 +++ b/drivers/xen/Kconfig Mon Mar 16 00:01:12 2009 -0700 @@ -312,4 +312,7 @@ config XEN_DEVMEM def_bool y +config XEN_XENCOW + def_bool y + endif diff -r 832aac894efd drivers/xen/Makefile --- a/drivers/xen/Makefile Wed Nov 19 13:15:46 2008 +0000 +++ b/drivers/xen/Makefile Mon Mar 16 00:01:12 2009 -0700 @@ -23,3 +23,4 @@ obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL) += sfc_netutil/ obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND) += sfc_netfront/ obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND) += sfc_netback/ +obj-$(CONFIG_XEN_XENCOW) += xencow/ diff -r 832aac894efd drivers/xen/xencow/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/xen/xencow/Makefile Mon Mar 16 00:01:12 2009 -0700 @@ -0,0 +1,2 @@ + +obj-m := xencow.o diff -r 832aac894efd drivers/xen/xencow/common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/xen/xencow/common.h Mon Mar 16 00:01:12 2009 -0700 @@ -0,0 +1,74 @@ +/****************************************************************************** + * common.h + * + * Copyright (c) 2009 University of British Columbia (Patrick Colp) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __XEN_XENCOW_COMMON_H__ +#define __XEN_XENCOW_COMMON_H__ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DPRINTK(_f, _a...) pr_debug("(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a ) + +#define WPRINTK(fmt, args...) printk(KERN_WARNING "xen_cow: " fmt, ##args) + + +#endif /* __XEN_XENCOW_COMMON_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 832aac894efd drivers/xen/xencow/xencow.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/xen/xencow/xencow.c Mon Mar 16 00:01:12 2009 -0700 @@ -0,0 +1,246 @@ +/****************************************************************************** + * xencow.c + * + * Xen Copy-on-Write Kernel Driver - Initialises CoW buffer for userspace + * + * Copyright (c) 2009 University of British Columbia (Patrick Colp) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + + +#include "common.h" + + +static int xencow_major; + + +static void xencow_release_user_pages(struct page *pages[], int num) +{ + int i; + + for ( i = 0; i < num; i++ ) + { + struct page *page = pages[i]; + SetPageUptodate(page); + put_page(page); + } +} + +static int xencow_get_user_pages(unsigned long addr, + int num, + struct page *pages[]) +{ + int ret; + + down_read(¤t->mm->mmap_sem); + ret = get_user_pages(current, current->mm, addr, num, 0, 0, pages, NULL); + up_read(¤t->mm->mmap_sem); + + if ( ret != num ) + { + if ( ret >= 0 ) + { + xencow_release_user_pages(pages, ret); + ret = -E2BIG; + } + + return ret; + } + + return 0; +} + +static inline unsigned long xencow_page_to_mfn(struct page *page) +{ + unsigned long pfn; + unsigned long mfn; + + pfn = page_to_pfn(page); + mfn = pfn_to_mfn(pfn); + + return mfn; +} + +static int xencow_get_page_mfns(unsigned long addr, + int num, + unsigned long mfns[]) +{ + struct page *pages[num]; + unsigned long mfn; + int ret; + int i; + + /* Get user pages */ + ret = xencow_get_user_pages(addr, num, pages); + if ( ret != 0 ) + return ret; + + /* Get MFNs for the pages */ + for ( i = 0; i < num; i++ ) + { + mfn = xencow_page_to_mfn(pages[i]); + if ( mfn == 0 ) + return -EFAULT; + + mfns[i] = mfn; + } + + /* Return user pages */ + xencow_release_user_pages(pages, num); + + return 0; +} + +static int xencow_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + switch ( cmd ) + { + + case XEN_COW_IOCTL_INIT: + { + xencow_init_t *cow_init; + xencow_init_t __user *cow_init_u; + int num_mfns; + int i; + + cow_init_u = (xencow_init_t __user *)arg; + + /* Check access on user init struct */ + ret = -EFAULT; + if ( !access_ok(VERIFY_READ, cow_init_u, sizeof(xencow_init_t)) ) + break; + + /* Get the number of frames in the buffer */ + ret = __get_user(num_mfns, &cow_init_u->num_mfns); + if ( ret != 0 ) + break; + + /* Allocate space */ + ret = -ENOMEM; + cow_init = (xencow_init_t *) + kmalloc(sizeof(xencow_init_t) + + (num_mfns * sizeof(unsigned long)), + GFP_KERNEL); + if ( cow_init == NULL ) + break; + + cow_init->num_mfns = num_mfns; + + /* Get start address of buffer */ + ret = __get_user(cow_init->addr, &cow_init_u->addr); + if ( ret != 0 ) + goto init_out; + + /* Get page buffer MFNs */ + ret = xencow_get_page_mfns(cow_init->addr, + cow_init->num_mfns, + cow_init->mfns); + if ( ret != 0 ) + goto init_out; + + /* Check access on user page buffer MFNs array */ + ret = -EFAULT; + if ( !access_ok(VERIFY_WRITE, &cow_init_u->mfns, + cow_init->num_mfns * sizeof(unsigned long)) ) + goto init_out; + + /* Send page buffer MFNs to user */ + ret = 0; + for ( i = 0; i < cow_init->num_mfns; i++ ) + ret |= __put_user(cow_init->mfns[i], &cow_init_u->mfns[i]); + + init_out: + kfree(cow_init); + } + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +static const struct file_operations xencow_fops = { + .owner = THIS_MODULE, + .ioctl = xencow_ioctl, +}; + +static int __init xencow_init(void) +{ + int ret; + struct class *class; + + if ( !is_running_on_xen() ) + return -ENODEV; + + ret = register_chrdev(0, "xencow", &xencow_fops); + if ( ret < 0 ) + { + WPRINTK("Couldn't register /dev/xen/xencow\n"); + return ret; + } + + xencow_major = ret; + + DPRINTK("Created misc_dev [/dev/xen/xencow%d]\n", xencow_major); + + /* Make sure the xen class exists */ + class = get_xen_class(); + if ( class != NULL ) + class_device_create(class, NULL, MKDEV(xencow_major, 0), + NULL, "xencow0"); + else + /* This is bad, but not fatal */ + WPRINTK("sysfs xen_class not created\n"); + + DPRINTK("XenCoW device successfully created\n"); + + return 0; +} + +static void __exit xencow_exit(void) +{ + int ret; + + ret = unregister_chrdev(xencow_major, "xencow"); + if ( ret < 0 ) + { + WPRINTK("Error: Couldn't unregister /dev/xen/xencow: %d\n", ret); + return; + } + + DPRINTK("XenCoW device successfully removed\n"); +} + +module_init(xencow_init); +module_exit(xencow_exit); + +MODULE_LICENSE("Dual BSD/GPL"); diff -r 832aac894efd include/xen/interface/io/xencow.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/xen/interface/io/xencow.h Mon Mar 16 00:01:12 2009 -0700 @@ -0,0 +1,70 @@ +/***************************************************************************** + * xencow.h + * + * XenCoW Common Structures + * + * Copyright (C) 2009 University of British Columbia (Patrick Colp) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _XEN_PUBLIC_IO_XENCOW_H +#define _XEN_PUBLIC_IO_XENCOW_H + + +#include "ring.h" + + +#define XEN_COW_IOC_MAGIC 'w' +#define XEN_COW_IOCTL_INIT _IO(XEN_COW_IOC_MAGIC, 1) + + +/* Some definitions for the XenCow ring buffer. */ +typedef struct xencow_request_st { + ulong mfn; +} xencow_request_t; + +typedef struct xencow_response_st { + ulong pfn; +} xencow_response_t; + +DEFINE_RING_TYPES(xencow, xencow_request_t, xencow_response_t); + + +/* The structure used to initialise a XenCoW snapshot. */ +typedef struct xencow_init_st { + /* Start address of buffer */ + unsigned long addr; + /* Number of frames in buffer */ + int num_mfns; + /* MFNs of buffer frames */ + unsigned long mfns[]; +} xencow_init_t; + + + +#endif /* _XEN_PUBLIC_IO_XENCOW_H */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */