/****************************************************************************** * Client-facing interface for the Xenbus driver. In other words, the * interface between the Xenbus and the device-specific code, be it the * frontend or the backend of that driver. * * Copyright (C) 2005 XenSource Ltd * * 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 <linux/mm.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/spinlock.h> #include <linux/vmalloc.h> #include <linux/export.h> #include <asm/xen/hypervisor.h> #include <xen/page.h> #include <xen/interface/xen.h> #include <xen/interface/event_channel.h> #include <xen/balloon.h> #include <xen/events.h> #include <xen/grant_table.h> #include <xen/xenbus.h> #include <xen/xen.h> #include <xen/features.h> #include "xenbus.h" #define XENBUS_PAGES(_grants) … #define XENBUS_MAX_RING_PAGES … struct xenbus_map_node { … }; struct map_ring_valloc { … }; static DEFINE_SPINLOCK(xenbus_valloc_lock); static LIST_HEAD(xenbus_valloc_pages); struct xenbus_ring_ops { … }; static const struct xenbus_ring_ops *ring_ops __read_mostly; const char *xenbus_strstate(enum xenbus_state state) { … } EXPORT_SYMBOL_GPL(…); /** * xenbus_watch_path - register a watch * @dev: xenbus device * @path: path to watch * @watch: watch to register * @will_handle: events queuing determine callback * @callback: callback to register * * Register a @watch on the given path, using the given xenbus_watch structure * for storage, @will_handle function as the callback to determine if each * event need to be queued, and the given @callback function as the callback. * On success, the given @path will be saved as @watch->node, and remains the * caller's to free. On error, @watch->node will be NULL, the device will * switch to %XenbusStateClosing, and the error will be saved in the store. * * Returns: %0 on success or -errno on error */ int xenbus_watch_path(struct xenbus_device *dev, const char *path, struct xenbus_watch *watch, bool (*will_handle)(struct xenbus_watch *, const char *, const char *), void (*callback)(struct xenbus_watch *, const char *, const char *)) { … } EXPORT_SYMBOL_GPL(…); /** * xenbus_watch_pathfmt - register a watch on a sprintf-formatted path * @dev: xenbus device * @watch: watch to register * @will_handle: events queuing determine callback * @callback: callback to register * @pathfmt: format of path to watch * * Register a watch on the given @path, using the given xenbus_watch * structure for storage, @will_handle function as the callback to determine if * each event need to be queued, and the given @callback function as the * callback. On success, the watched path (@path/@path2) will be saved * as @watch->node, and becomes the caller's to kfree(). * On error, watch->node will be NULL, so the caller has nothing to * free, the device will switch to %XenbusStateClosing, and the error will be * saved in the store. * * Returns: %0 on success or -errno on error */ int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch, bool (*will_handle)(struct xenbus_watch *, const char *, const char *), void (*callback)(struct xenbus_watch *, const char *, const char *), const char *pathfmt, ...) { … } EXPORT_SYMBOL_GPL(…); static void xenbus_switch_fatal(struct xenbus_device *, int, int, const char *, ...); static int __xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state, int depth) { … } /** * xenbus_switch_state - save the new state of a driver * @dev: xenbus device * @state: new state * * Advertise in the store a change of the given driver to the given new_state. * On error, the device will switch to XenbusStateClosing, and the error * will be saved in the store. * * Returns: %0 on success or -errno on error */ int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state) { … } EXPORT_SYMBOL_GPL(…); int xenbus_frontend_closed(struct xenbus_device *dev) { … } EXPORT_SYMBOL_GPL(…); static void xenbus_va_dev_error(struct xenbus_device *dev, int err, const char *fmt, va_list ap) { … } /** * xenbus_dev_error - place an error message into the store * @dev: xenbus device * @err: error to report * @fmt: error message format * * Report the given negative errno into the store, along with the given * formatted message. */ void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...) { … } EXPORT_SYMBOL_GPL(…); /** * xenbus_dev_fatal - put an error messages into the store and then shutdown * @dev: xenbus device * @err: error to report * @fmt: error message format * * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by * xenbus_switch_state(dev, XenbusStateClosing) to schedule an orderly * closedown of this driver and its peer. */ void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...) { … } EXPORT_SYMBOL_GPL(…); /* * Equivalent to xenbus_dev_fatal(dev, err, fmt, args), but helps * avoiding recursion within xenbus_switch_state. */ static void xenbus_switch_fatal(struct xenbus_device *dev, int depth, int err, const char *fmt, ...) { … } /* * xenbus_setup_ring * @dev: xenbus device * @vaddr: pointer to starting virtual address of the ring * @nr_pages: number of pages to be granted * @grefs: grant reference array to be filled in * * Allocate physically contiguous pages for a shared ring buffer and grant it * to the peer of the given device. The ring buffer is initially filled with * zeroes. The virtual address of the ring is stored at @vaddr and the * grant references are stored in the @grefs array. In case of error @vaddr * will be set to NULL and @grefs will be filled with INVALID_GRANT_REF. */ int xenbus_setup_ring(struct xenbus_device *dev, gfp_t gfp, void **vaddr, unsigned int nr_pages, grant_ref_t *grefs) { … } EXPORT_SYMBOL_GPL(…); /* * xenbus_teardown_ring * @vaddr: starting virtual address of the ring * @nr_pages: number of pages * @grefs: grant reference array * * Remove grants for the shared ring buffer and free the associated memory. * On return the grant reference array is filled with INVALID_GRANT_REF. */ void xenbus_teardown_ring(void **vaddr, unsigned int nr_pages, grant_ref_t *grefs) { … } EXPORT_SYMBOL_GPL(…); /* * Allocate an event channel for the given xenbus_device, assigning the newly * created local port to *port. Return 0 on success, or -errno on error. On * error, the device will switch to XenbusStateClosing, and the error will be * saved in the store. */ int xenbus_alloc_evtchn(struct xenbus_device *dev, evtchn_port_t *port) { … } EXPORT_SYMBOL_GPL(…); /* * Free an existing event channel. Returns 0 on success or -errno on error. */ int xenbus_free_evtchn(struct xenbus_device *dev, evtchn_port_t port) { … } EXPORT_SYMBOL_GPL(…); /** * xenbus_map_ring_valloc - allocate & map pages of VA space * @dev: xenbus device * @gnt_refs: grant reference array * @nr_grefs: number of grant references * @vaddr: pointer to address to be filled out by mapping * * Map @nr_grefs pages of memory into this domain from another * domain's grant table. xenbus_map_ring_valloc allocates @nr_grefs * pages of virtual address space, maps the pages to that address, and sets * *vaddr to that address. If an error is returned, device will switch to * XenbusStateClosing and the error message will be saved in XenStore. * * Returns: %0 on success or -errno on error */ int xenbus_map_ring_valloc(struct xenbus_device *dev, grant_ref_t *gnt_refs, unsigned int nr_grefs, void **vaddr) { … } EXPORT_SYMBOL_GPL(…); /* N.B. sizeof(phys_addr_t) doesn't always equal to sizeof(unsigned * long), e.g. 32-on-64. Caller is responsible for preparing the * right array to feed into this function */ static int __xenbus_map_ring(struct xenbus_device *dev, grant_ref_t *gnt_refs, unsigned int nr_grefs, grant_handle_t *handles, struct map_ring_valloc *info, unsigned int flags, bool *leaked) { … } /** * xenbus_unmap_ring - unmap memory from another domain * @dev: xenbus device * @handles: grant handle array * @nr_handles: number of handles in the array * @vaddrs: addresses to unmap * * Unmap memory in this domain that was imported from another domain. * * Returns: %0 on success or GNTST_* on error * (see xen/include/interface/grant_table.h). */ static int xenbus_unmap_ring(struct xenbus_device *dev, grant_handle_t *handles, unsigned int nr_handles, unsigned long *vaddrs) { … } static void xenbus_map_ring_setup_grant_hvm(unsigned long gfn, unsigned int goffset, unsigned int len, void *data) { … } static int xenbus_map_ring_hvm(struct xenbus_device *dev, struct map_ring_valloc *info, grant_ref_t *gnt_ref, unsigned int nr_grefs, void **vaddr) { … } /** * xenbus_unmap_ring_vfree - unmap a page of memory from another domain * @dev: xenbus device * @vaddr: addr to unmap * * Based on Rusty Russell's skeleton driver's unmap_page. * Unmap a page of memory in this domain that was imported from another domain. * Use xenbus_unmap_ring_vfree if you mapped in your memory with * xenbus_map_ring_valloc (it will free the virtual address space). * * Returns: %0 on success or GNTST_* on error * (see xen/include/interface/grant_table.h). */ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) { … } EXPORT_SYMBOL_GPL(…); #ifdef CONFIG_XEN_PV static int map_ring_apply(pte_t *pte, unsigned long addr, void *data) { … } static int xenbus_map_ring_pv(struct xenbus_device *dev, struct map_ring_valloc *info, grant_ref_t *gnt_refs, unsigned int nr_grefs, void **vaddr) { … } static int xenbus_unmap_ring_pv(struct xenbus_device *dev, void *vaddr) { … } static const struct xenbus_ring_ops ring_ops_pv = …; #endif struct unmap_ring_hvm { … }; static void xenbus_unmap_ring_setup_grant_hvm(unsigned long gfn, unsigned int goffset, unsigned int len, void *data) { … } static int xenbus_unmap_ring_hvm(struct xenbus_device *dev, void *vaddr) { … } /** * xenbus_read_driver_state - read state from a store path * @path: path for driver * * Returns: the state of the driver rooted at the given store path, or * XenbusStateUnknown if no state can be read. */ enum xenbus_state xenbus_read_driver_state(const char *path) { … } EXPORT_SYMBOL_GPL(…); static const struct xenbus_ring_ops ring_ops_hvm = …; void __init xenbus_ring_ops_init(void) { … }