/****************************************************************************** * gntalloc.c * * Device for creating grant references (in user-space) that may be shared * with other domains. * * 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 */ /* * This driver exists to allow userspace programs in Linux to allocate kernel * memory that will later be shared with another domain. Without this device, * Linux userspace programs cannot create grant references. * * How this stuff works: * X -> granting a page to Y * Y -> mapping the grant from X * * 1. X uses the gntalloc device to allocate a page of kernel memory, P. * 2. X creates an entry in the grant table that says domid(Y) can access P. * This is done without a hypercall unless the grant table needs expansion. * 3. X gives the grant reference identifier, GREF, to Y. * 4. Y maps the page, either directly into kernel memory for use in a backend * driver, or via a the gntdev device to map into the address space of an * application running in Y. This is the first point at which Xen does any * tracking of the page. * 5. A program in X mmap()s a segment of the gntalloc device that corresponds * to the shared page, and can now communicate with Y over the shared page. * * * NOTE TO USERSPACE LIBRARIES: * The grant allocation and mmap()ing are, naturally, two separate operations. * You set up the sharing by calling the create ioctl() and then the mmap(). * Teardown requires munmap() and either close() or ioctl(). * * WARNING: Since Xen does not allow a guest to forcibly end the use of a grant * reference, this device can be used to consume kernel memory by leaving grant * references mapped by another domain when an application exits. Therefore, * there is a global limit on the number of pages that can be allocated. When * all references to the page are unmapped, it will be freed during the next * grant operation. */ #define pr_fmt(fmt) … #include <linux/atomic.h> #include <linux/module.h> #include <linux/miscdevice.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/mm.h> #include <linux/uaccess.h> #include <linux/types.h> #include <linux/list.h> #include <linux/highmem.h> #include <xen/xen.h> #include <xen/page.h> #include <xen/grant_table.h> #include <xen/gntalloc.h> #include <xen/events.h> static int limit = …; module_param(limit, int, 0644); MODULE_PARM_DESC(…) …; static LIST_HEAD(gref_list); static DEFINE_MUTEX(gref_mutex); static int gref_size; struct notify_info { … }; /* Metadata on a grant reference. */ struct gntalloc_gref { … }; struct gntalloc_file_private_data { … }; struct gntalloc_vma_private_data { … }; static void __del_gref(struct gntalloc_gref *gref); static void do_cleanup(void) { … } static int add_grefs(struct ioctl_gntalloc_alloc_gref *op, uint32_t *gref_ids, struct gntalloc_file_private_data *priv) { … } static void __del_gref(struct gntalloc_gref *gref) { … } /* finds contiguous grant references in a file, returns the first */ static struct gntalloc_gref *find_grefs(struct gntalloc_file_private_data *priv, uint64_t index, uint32_t count) { … } /* * ------------------------------------- * File operations. * ------------------------------------- */ static int gntalloc_open(struct inode *inode, struct file *filp) { … } static int gntalloc_release(struct inode *inode, struct file *filp) { … } static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv, struct ioctl_gntalloc_alloc_gref __user *arg) { … } static long gntalloc_ioctl_dealloc(struct gntalloc_file_private_data *priv, void __user *arg) { … } static long gntalloc_ioctl_unmap_notify(struct gntalloc_file_private_data *priv, void __user *arg) { … } static long gntalloc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { … } static void gntalloc_vma_open(struct vm_area_struct *vma) { … } static void gntalloc_vma_close(struct vm_area_struct *vma) { … } static const struct vm_operations_struct gntalloc_vmops = …; static int gntalloc_mmap(struct file *filp, struct vm_area_struct *vma) { … } static const struct file_operations gntalloc_fops = …; /* * ------------------------------------- * Module creation/destruction. * ------------------------------------- */ static struct miscdevice gntalloc_miscdev = …; static int __init gntalloc_init(void) { … } static void __exit gntalloc_exit(void) { … } module_init(…) …; module_exit(gntalloc_exit); MODULE_LICENSE(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …;