162306a36Sopenharmony_ci/******************************************************************************
262306a36Sopenharmony_ci * Client-facing interface for the Xenbus driver.  In other words, the
362306a36Sopenharmony_ci * interface between the Xenbus and the device-specific code, be it the
462306a36Sopenharmony_ci * frontend or the backend of that driver.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2005 XenSource Ltd
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or
962306a36Sopenharmony_ci * modify it under the terms of the GNU General Public License version 2
1062306a36Sopenharmony_ci * as published by the Free Software Foundation; or, when distributed
1162306a36Sopenharmony_ci * separately from the Linux kernel or incorporated into other
1262306a36Sopenharmony_ci * software packages, subject to the following license:
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
1562306a36Sopenharmony_ci * of this source file (the "Software"), to deal in the Software without
1662306a36Sopenharmony_ci * restriction, including without limitation the rights to use, copy, modify,
1762306a36Sopenharmony_ci * merge, publish, distribute, sublicense, and/or sell copies of the Software,
1862306a36Sopenharmony_ci * and to permit persons to whom the Software is furnished to do so, subject to
1962306a36Sopenharmony_ci * the following conditions:
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
2262306a36Sopenharmony_ci * all copies or substantial portions of the Software.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2762306a36Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2862306a36Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2962306a36Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
3062306a36Sopenharmony_ci * IN THE SOFTWARE.
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#include <linux/mm.h>
3462306a36Sopenharmony_ci#include <linux/slab.h>
3562306a36Sopenharmony_ci#include <linux/types.h>
3662306a36Sopenharmony_ci#include <linux/spinlock.h>
3762306a36Sopenharmony_ci#include <linux/vmalloc.h>
3862306a36Sopenharmony_ci#include <linux/export.h>
3962306a36Sopenharmony_ci#include <asm/xen/hypervisor.h>
4062306a36Sopenharmony_ci#include <xen/page.h>
4162306a36Sopenharmony_ci#include <xen/interface/xen.h>
4262306a36Sopenharmony_ci#include <xen/interface/event_channel.h>
4362306a36Sopenharmony_ci#include <xen/balloon.h>
4462306a36Sopenharmony_ci#include <xen/events.h>
4562306a36Sopenharmony_ci#include <xen/grant_table.h>
4662306a36Sopenharmony_ci#include <xen/xenbus.h>
4762306a36Sopenharmony_ci#include <xen/xen.h>
4862306a36Sopenharmony_ci#include <xen/features.h>
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#include "xenbus.h"
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define XENBUS_PAGES(_grants)	(DIV_ROUND_UP(_grants, XEN_PFN_PER_PAGE))
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define XENBUS_MAX_RING_PAGES	(XENBUS_PAGES(XENBUS_MAX_RING_GRANTS))
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistruct xenbus_map_node {
5762306a36Sopenharmony_ci	struct list_head next;
5862306a36Sopenharmony_ci	union {
5962306a36Sopenharmony_ci		struct {
6062306a36Sopenharmony_ci			struct vm_struct *area;
6162306a36Sopenharmony_ci		} pv;
6262306a36Sopenharmony_ci		struct {
6362306a36Sopenharmony_ci			struct page *pages[XENBUS_MAX_RING_PAGES];
6462306a36Sopenharmony_ci			unsigned long addrs[XENBUS_MAX_RING_GRANTS];
6562306a36Sopenharmony_ci			void *addr;
6662306a36Sopenharmony_ci		} hvm;
6762306a36Sopenharmony_ci	};
6862306a36Sopenharmony_ci	grant_handle_t handles[XENBUS_MAX_RING_GRANTS];
6962306a36Sopenharmony_ci	unsigned int   nr_handles;
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistruct map_ring_valloc {
7362306a36Sopenharmony_ci	struct xenbus_map_node *node;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	/* Why do we need two arrays? See comment of __xenbus_map_ring */
7662306a36Sopenharmony_ci	unsigned long addrs[XENBUS_MAX_RING_GRANTS];
7762306a36Sopenharmony_ci	phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	struct gnttab_map_grant_ref map[XENBUS_MAX_RING_GRANTS];
8062306a36Sopenharmony_ci	struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS];
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	unsigned int idx;
8362306a36Sopenharmony_ci};
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic DEFINE_SPINLOCK(xenbus_valloc_lock);
8662306a36Sopenharmony_cistatic LIST_HEAD(xenbus_valloc_pages);
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistruct xenbus_ring_ops {
8962306a36Sopenharmony_ci	int (*map)(struct xenbus_device *dev, struct map_ring_valloc *info,
9062306a36Sopenharmony_ci		   grant_ref_t *gnt_refs, unsigned int nr_grefs,
9162306a36Sopenharmony_ci		   void **vaddr);
9262306a36Sopenharmony_ci	int (*unmap)(struct xenbus_device *dev, void *vaddr);
9362306a36Sopenharmony_ci};
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic const struct xenbus_ring_ops *ring_ops __read_mostly;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciconst char *xenbus_strstate(enum xenbus_state state)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	static const char *const name[] = {
10062306a36Sopenharmony_ci		[ XenbusStateUnknown      ] = "Unknown",
10162306a36Sopenharmony_ci		[ XenbusStateInitialising ] = "Initialising",
10262306a36Sopenharmony_ci		[ XenbusStateInitWait     ] = "InitWait",
10362306a36Sopenharmony_ci		[ XenbusStateInitialised  ] = "Initialised",
10462306a36Sopenharmony_ci		[ XenbusStateConnected    ] = "Connected",
10562306a36Sopenharmony_ci		[ XenbusStateClosing      ] = "Closing",
10662306a36Sopenharmony_ci		[ XenbusStateClosed	  ] = "Closed",
10762306a36Sopenharmony_ci		[XenbusStateReconfiguring] = "Reconfiguring",
10862306a36Sopenharmony_ci		[XenbusStateReconfigured] = "Reconfigured",
10962306a36Sopenharmony_ci	};
11062306a36Sopenharmony_ci	return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
11162306a36Sopenharmony_ci}
11262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_strstate);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/**
11562306a36Sopenharmony_ci * xenbus_watch_path - register a watch
11662306a36Sopenharmony_ci * @dev: xenbus device
11762306a36Sopenharmony_ci * @path: path to watch
11862306a36Sopenharmony_ci * @watch: watch to register
11962306a36Sopenharmony_ci * @callback: callback to register
12062306a36Sopenharmony_ci *
12162306a36Sopenharmony_ci * Register a @watch on the given path, using the given xenbus_watch structure
12262306a36Sopenharmony_ci * for storage, and the given @callback function as the callback.  Return 0 on
12362306a36Sopenharmony_ci * success, or -errno on error.  On success, the given @path will be saved as
12462306a36Sopenharmony_ci * @watch->node, and remains the caller's to free.  On error, @watch->node will
12562306a36Sopenharmony_ci * be NULL, the device will switch to %XenbusStateClosing, and the error will
12662306a36Sopenharmony_ci * be saved in the store.
12762306a36Sopenharmony_ci */
12862306a36Sopenharmony_ciint xenbus_watch_path(struct xenbus_device *dev, const char *path,
12962306a36Sopenharmony_ci		      struct xenbus_watch *watch,
13062306a36Sopenharmony_ci		      bool (*will_handle)(struct xenbus_watch *,
13162306a36Sopenharmony_ci					  const char *, const char *),
13262306a36Sopenharmony_ci		      void (*callback)(struct xenbus_watch *,
13362306a36Sopenharmony_ci				       const char *, const char *))
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	int err;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	watch->node = path;
13862306a36Sopenharmony_ci	watch->will_handle = will_handle;
13962306a36Sopenharmony_ci	watch->callback = callback;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	err = register_xenbus_watch(watch);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	if (err) {
14462306a36Sopenharmony_ci		watch->node = NULL;
14562306a36Sopenharmony_ci		watch->will_handle = NULL;
14662306a36Sopenharmony_ci		watch->callback = NULL;
14762306a36Sopenharmony_ci		xenbus_dev_fatal(dev, err, "adding watch on %s", path);
14862306a36Sopenharmony_ci	}
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	return err;
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_watch_path);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci/**
15662306a36Sopenharmony_ci * xenbus_watch_pathfmt - register a watch on a sprintf-formatted path
15762306a36Sopenharmony_ci * @dev: xenbus device
15862306a36Sopenharmony_ci * @watch: watch to register
15962306a36Sopenharmony_ci * @callback: callback to register
16062306a36Sopenharmony_ci * @pathfmt: format of path to watch
16162306a36Sopenharmony_ci *
16262306a36Sopenharmony_ci * Register a watch on the given @path, using the given xenbus_watch
16362306a36Sopenharmony_ci * structure for storage, and the given @callback function as the callback.
16462306a36Sopenharmony_ci * Return 0 on success, or -errno on error.  On success, the watched path
16562306a36Sopenharmony_ci * (@path/@path2) will be saved as @watch->node, and becomes the caller's to
16662306a36Sopenharmony_ci * kfree().  On error, watch->node will be NULL, so the caller has nothing to
16762306a36Sopenharmony_ci * free, the device will switch to %XenbusStateClosing, and the error will be
16862306a36Sopenharmony_ci * saved in the store.
16962306a36Sopenharmony_ci */
17062306a36Sopenharmony_ciint xenbus_watch_pathfmt(struct xenbus_device *dev,
17162306a36Sopenharmony_ci			 struct xenbus_watch *watch,
17262306a36Sopenharmony_ci			 bool (*will_handle)(struct xenbus_watch *,
17362306a36Sopenharmony_ci					const char *, const char *),
17462306a36Sopenharmony_ci			 void (*callback)(struct xenbus_watch *,
17562306a36Sopenharmony_ci					  const char *, const char *),
17662306a36Sopenharmony_ci			 const char *pathfmt, ...)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	int err;
17962306a36Sopenharmony_ci	va_list ap;
18062306a36Sopenharmony_ci	char *path;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	va_start(ap, pathfmt);
18362306a36Sopenharmony_ci	path = kvasprintf(GFP_NOIO | __GFP_HIGH, pathfmt, ap);
18462306a36Sopenharmony_ci	va_end(ap);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	if (!path) {
18762306a36Sopenharmony_ci		xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
18862306a36Sopenharmony_ci		return -ENOMEM;
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci	err = xenbus_watch_path(dev, path, watch, will_handle, callback);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	if (err)
19362306a36Sopenharmony_ci		kfree(path);
19462306a36Sopenharmony_ci	return err;
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_watch_pathfmt);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic void xenbus_switch_fatal(struct xenbus_device *, int, int,
19962306a36Sopenharmony_ci				const char *, ...);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic int
20262306a36Sopenharmony_ci__xenbus_switch_state(struct xenbus_device *dev,
20362306a36Sopenharmony_ci		      enum xenbus_state state, int depth)
20462306a36Sopenharmony_ci{
20562306a36Sopenharmony_ci	/* We check whether the state is currently set to the given value, and
20662306a36Sopenharmony_ci	   if not, then the state is set.  We don't want to unconditionally
20762306a36Sopenharmony_ci	   write the given state, because we don't want to fire watches
20862306a36Sopenharmony_ci	   unnecessarily.  Furthermore, if the node has gone, we don't write
20962306a36Sopenharmony_ci	   to it, as the device will be tearing down, and we don't want to
21062306a36Sopenharmony_ci	   resurrect that directory.
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	   Note that, because of this cached value of our state, this
21362306a36Sopenharmony_ci	   function will not take a caller's Xenstore transaction
21462306a36Sopenharmony_ci	   (something it was trying to in the past) because dev->state
21562306a36Sopenharmony_ci	   would not get reset if the transaction was aborted.
21662306a36Sopenharmony_ci	 */
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	struct xenbus_transaction xbt;
21962306a36Sopenharmony_ci	int current_state;
22062306a36Sopenharmony_ci	int err, abort;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	if (state == dev->state)
22362306a36Sopenharmony_ci		return 0;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ciagain:
22662306a36Sopenharmony_ci	abort = 1;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	err = xenbus_transaction_start(&xbt);
22962306a36Sopenharmony_ci	if (err) {
23062306a36Sopenharmony_ci		xenbus_switch_fatal(dev, depth, err, "starting transaction");
23162306a36Sopenharmony_ci		return 0;
23262306a36Sopenharmony_ci	}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	err = xenbus_scanf(xbt, dev->nodename, "state", "%d", &current_state);
23562306a36Sopenharmony_ci	if (err != 1)
23662306a36Sopenharmony_ci		goto abort;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
23962306a36Sopenharmony_ci	if (err) {
24062306a36Sopenharmony_ci		xenbus_switch_fatal(dev, depth, err, "writing new state");
24162306a36Sopenharmony_ci		goto abort;
24262306a36Sopenharmony_ci	}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	abort = 0;
24562306a36Sopenharmony_ciabort:
24662306a36Sopenharmony_ci	err = xenbus_transaction_end(xbt, abort);
24762306a36Sopenharmony_ci	if (err) {
24862306a36Sopenharmony_ci		if (err == -EAGAIN && !abort)
24962306a36Sopenharmony_ci			goto again;
25062306a36Sopenharmony_ci		xenbus_switch_fatal(dev, depth, err, "ending transaction");
25162306a36Sopenharmony_ci	} else
25262306a36Sopenharmony_ci		dev->state = state;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	return 0;
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci/**
25862306a36Sopenharmony_ci * xenbus_switch_state
25962306a36Sopenharmony_ci * @dev: xenbus device
26062306a36Sopenharmony_ci * @state: new state
26162306a36Sopenharmony_ci *
26262306a36Sopenharmony_ci * Advertise in the store a change of the given driver to the given new_state.
26362306a36Sopenharmony_ci * Return 0 on success, or -errno on error.  On error, the device will switch
26462306a36Sopenharmony_ci * to XenbusStateClosing, and the error will be saved in the store.
26562306a36Sopenharmony_ci */
26662306a36Sopenharmony_ciint xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	return __xenbus_switch_state(dev, state, 0);
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_switch_state);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ciint xenbus_frontend_closed(struct xenbus_device *dev)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	xenbus_switch_state(dev, XenbusStateClosed);
27662306a36Sopenharmony_ci	complete(&dev->down);
27762306a36Sopenharmony_ci	return 0;
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_frontend_closed);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_cistatic void xenbus_va_dev_error(struct xenbus_device *dev, int err,
28262306a36Sopenharmony_ci				const char *fmt, va_list ap)
28362306a36Sopenharmony_ci{
28462306a36Sopenharmony_ci	unsigned int len;
28562306a36Sopenharmony_ci	char *printf_buffer;
28662306a36Sopenharmony_ci	char *path_buffer;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci#define PRINTF_BUFFER_SIZE 4096
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
29162306a36Sopenharmony_ci	if (!printf_buffer)
29262306a36Sopenharmony_ci		return;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	len = sprintf(printf_buffer, "%i ", -err);
29562306a36Sopenharmony_ci	vsnprintf(printf_buffer + len, PRINTF_BUFFER_SIZE - len, fmt, ap);
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	dev_err(&dev->dev, "%s\n", printf_buffer);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	path_buffer = kasprintf(GFP_KERNEL, "error/%s", dev->nodename);
30062306a36Sopenharmony_ci	if (path_buffer)
30162306a36Sopenharmony_ci		xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	kfree(printf_buffer);
30462306a36Sopenharmony_ci	kfree(path_buffer);
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci/**
30862306a36Sopenharmony_ci * xenbus_dev_error
30962306a36Sopenharmony_ci * @dev: xenbus device
31062306a36Sopenharmony_ci * @err: error to report
31162306a36Sopenharmony_ci * @fmt: error message format
31262306a36Sopenharmony_ci *
31362306a36Sopenharmony_ci * Report the given negative errno into the store, along with the given
31462306a36Sopenharmony_ci * formatted message.
31562306a36Sopenharmony_ci */
31662306a36Sopenharmony_civoid xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	va_list ap;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	va_start(ap, fmt);
32162306a36Sopenharmony_ci	xenbus_va_dev_error(dev, err, fmt, ap);
32262306a36Sopenharmony_ci	va_end(ap);
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_dev_error);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci/**
32762306a36Sopenharmony_ci * xenbus_dev_fatal
32862306a36Sopenharmony_ci * @dev: xenbus device
32962306a36Sopenharmony_ci * @err: error to report
33062306a36Sopenharmony_ci * @fmt: error message format
33162306a36Sopenharmony_ci *
33262306a36Sopenharmony_ci * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by
33362306a36Sopenharmony_ci * xenbus_switch_state(dev, XenbusStateClosing) to schedule an orderly
33462306a36Sopenharmony_ci * closedown of this driver and its peer.
33562306a36Sopenharmony_ci */
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_civoid xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...)
33862306a36Sopenharmony_ci{
33962306a36Sopenharmony_ci	va_list ap;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	va_start(ap, fmt);
34262306a36Sopenharmony_ci	xenbus_va_dev_error(dev, err, fmt, ap);
34362306a36Sopenharmony_ci	va_end(ap);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	xenbus_switch_state(dev, XenbusStateClosing);
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_dev_fatal);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci/**
35062306a36Sopenharmony_ci * Equivalent to xenbus_dev_fatal(dev, err, fmt, args), but helps
35162306a36Sopenharmony_ci * avoiding recursion within xenbus_switch_state.
35262306a36Sopenharmony_ci */
35362306a36Sopenharmony_cistatic void xenbus_switch_fatal(struct xenbus_device *dev, int depth, int err,
35462306a36Sopenharmony_ci				const char *fmt, ...)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	va_list ap;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	va_start(ap, fmt);
35962306a36Sopenharmony_ci	xenbus_va_dev_error(dev, err, fmt, ap);
36062306a36Sopenharmony_ci	va_end(ap);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	if (!depth)
36362306a36Sopenharmony_ci		__xenbus_switch_state(dev, XenbusStateClosing, 1);
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci/*
36762306a36Sopenharmony_ci * xenbus_setup_ring
36862306a36Sopenharmony_ci * @dev: xenbus device
36962306a36Sopenharmony_ci * @vaddr: pointer to starting virtual address of the ring
37062306a36Sopenharmony_ci * @nr_pages: number of pages to be granted
37162306a36Sopenharmony_ci * @grefs: grant reference array to be filled in
37262306a36Sopenharmony_ci *
37362306a36Sopenharmony_ci * Allocate physically contiguous pages for a shared ring buffer and grant it
37462306a36Sopenharmony_ci * to the peer of the given device. The ring buffer is initially filled with
37562306a36Sopenharmony_ci * zeroes. The virtual address of the ring is stored at @vaddr and the
37662306a36Sopenharmony_ci * grant references are stored in the @grefs array. In case of error @vaddr
37762306a36Sopenharmony_ci * will be set to NULL and @grefs will be filled with INVALID_GRANT_REF.
37862306a36Sopenharmony_ci */
37962306a36Sopenharmony_ciint xenbus_setup_ring(struct xenbus_device *dev, gfp_t gfp, void **vaddr,
38062306a36Sopenharmony_ci		      unsigned int nr_pages, grant_ref_t *grefs)
38162306a36Sopenharmony_ci{
38262306a36Sopenharmony_ci	unsigned long ring_size = nr_pages * XEN_PAGE_SIZE;
38362306a36Sopenharmony_ci	grant_ref_t gref_head;
38462306a36Sopenharmony_ci	unsigned int i;
38562306a36Sopenharmony_ci	void *addr;
38662306a36Sopenharmony_ci	int ret;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	addr = *vaddr = alloc_pages_exact(ring_size, gfp | __GFP_ZERO);
38962306a36Sopenharmony_ci	if (!*vaddr) {
39062306a36Sopenharmony_ci		ret = -ENOMEM;
39162306a36Sopenharmony_ci		goto err;
39262306a36Sopenharmony_ci	}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	ret = gnttab_alloc_grant_references(nr_pages, &gref_head);
39562306a36Sopenharmony_ci	if (ret) {
39662306a36Sopenharmony_ci		xenbus_dev_fatal(dev, ret, "granting access to %u ring pages",
39762306a36Sopenharmony_ci				 nr_pages);
39862306a36Sopenharmony_ci		goto err;
39962306a36Sopenharmony_ci	}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	for (i = 0; i < nr_pages; i++) {
40262306a36Sopenharmony_ci		unsigned long gfn;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci		if (is_vmalloc_addr(*vaddr))
40562306a36Sopenharmony_ci			gfn = pfn_to_gfn(vmalloc_to_pfn(addr));
40662306a36Sopenharmony_ci		else
40762306a36Sopenharmony_ci			gfn = virt_to_gfn(addr);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci		grefs[i] = gnttab_claim_grant_reference(&gref_head);
41062306a36Sopenharmony_ci		gnttab_grant_foreign_access_ref(grefs[i], dev->otherend_id,
41162306a36Sopenharmony_ci						gfn, 0);
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci		addr += XEN_PAGE_SIZE;
41462306a36Sopenharmony_ci	}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	return 0;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci err:
41962306a36Sopenharmony_ci	if (*vaddr)
42062306a36Sopenharmony_ci		free_pages_exact(*vaddr, ring_size);
42162306a36Sopenharmony_ci	for (i = 0; i < nr_pages; i++)
42262306a36Sopenharmony_ci		grefs[i] = INVALID_GRANT_REF;
42362306a36Sopenharmony_ci	*vaddr = NULL;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	return ret;
42662306a36Sopenharmony_ci}
42762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_setup_ring);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci/*
43062306a36Sopenharmony_ci * xenbus_teardown_ring
43162306a36Sopenharmony_ci * @vaddr: starting virtual address of the ring
43262306a36Sopenharmony_ci * @nr_pages: number of pages
43362306a36Sopenharmony_ci * @grefs: grant reference array
43462306a36Sopenharmony_ci *
43562306a36Sopenharmony_ci * Remove grants for the shared ring buffer and free the associated memory.
43662306a36Sopenharmony_ci * On return the grant reference array is filled with INVALID_GRANT_REF.
43762306a36Sopenharmony_ci */
43862306a36Sopenharmony_civoid xenbus_teardown_ring(void **vaddr, unsigned int nr_pages,
43962306a36Sopenharmony_ci			  grant_ref_t *grefs)
44062306a36Sopenharmony_ci{
44162306a36Sopenharmony_ci	unsigned int i;
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	for (i = 0; i < nr_pages; i++) {
44462306a36Sopenharmony_ci		if (grefs[i] != INVALID_GRANT_REF) {
44562306a36Sopenharmony_ci			gnttab_end_foreign_access(grefs[i], NULL);
44662306a36Sopenharmony_ci			grefs[i] = INVALID_GRANT_REF;
44762306a36Sopenharmony_ci		}
44862306a36Sopenharmony_ci	}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	if (*vaddr)
45162306a36Sopenharmony_ci		free_pages_exact(*vaddr, nr_pages * XEN_PAGE_SIZE);
45262306a36Sopenharmony_ci	*vaddr = NULL;
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_teardown_ring);
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci/**
45762306a36Sopenharmony_ci * Allocate an event channel for the given xenbus_device, assigning the newly
45862306a36Sopenharmony_ci * created local port to *port.  Return 0 on success, or -errno on error.  On
45962306a36Sopenharmony_ci * error, the device will switch to XenbusStateClosing, and the error will be
46062306a36Sopenharmony_ci * saved in the store.
46162306a36Sopenharmony_ci */
46262306a36Sopenharmony_ciint xenbus_alloc_evtchn(struct xenbus_device *dev, evtchn_port_t *port)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	struct evtchn_alloc_unbound alloc_unbound;
46562306a36Sopenharmony_ci	int err;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	alloc_unbound.dom = DOMID_SELF;
46862306a36Sopenharmony_ci	alloc_unbound.remote_dom = dev->otherend_id;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
47162306a36Sopenharmony_ci					  &alloc_unbound);
47262306a36Sopenharmony_ci	if (err)
47362306a36Sopenharmony_ci		xenbus_dev_fatal(dev, err, "allocating event channel");
47462306a36Sopenharmony_ci	else
47562306a36Sopenharmony_ci		*port = alloc_unbound.port;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	return err;
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci/**
48362306a36Sopenharmony_ci * Free an existing event channel. Returns 0 on success or -errno on error.
48462306a36Sopenharmony_ci */
48562306a36Sopenharmony_ciint xenbus_free_evtchn(struct xenbus_device *dev, evtchn_port_t port)
48662306a36Sopenharmony_ci{
48762306a36Sopenharmony_ci	struct evtchn_close close;
48862306a36Sopenharmony_ci	int err;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	close.port = port;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
49362306a36Sopenharmony_ci	if (err)
49462306a36Sopenharmony_ci		xenbus_dev_error(dev, err, "freeing event channel %u", port);
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	return err;
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_free_evtchn);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci/**
50262306a36Sopenharmony_ci * xenbus_map_ring_valloc
50362306a36Sopenharmony_ci * @dev: xenbus device
50462306a36Sopenharmony_ci * @gnt_refs: grant reference array
50562306a36Sopenharmony_ci * @nr_grefs: number of grant references
50662306a36Sopenharmony_ci * @vaddr: pointer to address to be filled out by mapping
50762306a36Sopenharmony_ci *
50862306a36Sopenharmony_ci * Map @nr_grefs pages of memory into this domain from another
50962306a36Sopenharmony_ci * domain's grant table.  xenbus_map_ring_valloc allocates @nr_grefs
51062306a36Sopenharmony_ci * pages of virtual address space, maps the pages to that address, and
51162306a36Sopenharmony_ci * sets *vaddr to that address.  Returns 0 on success, and -errno on
51262306a36Sopenharmony_ci * error. If an error is returned, device will switch to
51362306a36Sopenharmony_ci * XenbusStateClosing and the error message will be saved in XenStore.
51462306a36Sopenharmony_ci */
51562306a36Sopenharmony_ciint xenbus_map_ring_valloc(struct xenbus_device *dev, grant_ref_t *gnt_refs,
51662306a36Sopenharmony_ci			   unsigned int nr_grefs, void **vaddr)
51762306a36Sopenharmony_ci{
51862306a36Sopenharmony_ci	int err;
51962306a36Sopenharmony_ci	struct map_ring_valloc *info;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	*vaddr = NULL;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	if (nr_grefs > XENBUS_MAX_RING_GRANTS)
52462306a36Sopenharmony_ci		return -EINVAL;
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	info = kzalloc(sizeof(*info), GFP_KERNEL);
52762306a36Sopenharmony_ci	if (!info)
52862306a36Sopenharmony_ci		return -ENOMEM;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	info->node = kzalloc(sizeof(*info->node), GFP_KERNEL);
53162306a36Sopenharmony_ci	if (!info->node)
53262306a36Sopenharmony_ci		err = -ENOMEM;
53362306a36Sopenharmony_ci	else
53462306a36Sopenharmony_ci		err = ring_ops->map(dev, info, gnt_refs, nr_grefs, vaddr);
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	kfree(info->node);
53762306a36Sopenharmony_ci	kfree(info);
53862306a36Sopenharmony_ci	return err;
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci/* N.B. sizeof(phys_addr_t) doesn't always equal to sizeof(unsigned
54362306a36Sopenharmony_ci * long), e.g. 32-on-64.  Caller is responsible for preparing the
54462306a36Sopenharmony_ci * right array to feed into this function */
54562306a36Sopenharmony_cistatic int __xenbus_map_ring(struct xenbus_device *dev,
54662306a36Sopenharmony_ci			     grant_ref_t *gnt_refs,
54762306a36Sopenharmony_ci			     unsigned int nr_grefs,
54862306a36Sopenharmony_ci			     grant_handle_t *handles,
54962306a36Sopenharmony_ci			     struct map_ring_valloc *info,
55062306a36Sopenharmony_ci			     unsigned int flags,
55162306a36Sopenharmony_ci			     bool *leaked)
55262306a36Sopenharmony_ci{
55362306a36Sopenharmony_ci	int i, j;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	if (nr_grefs > XENBUS_MAX_RING_GRANTS)
55662306a36Sopenharmony_ci		return -EINVAL;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	for (i = 0; i < nr_grefs; i++) {
55962306a36Sopenharmony_ci		gnttab_set_map_op(&info->map[i], info->phys_addrs[i], flags,
56062306a36Sopenharmony_ci				  gnt_refs[i], dev->otherend_id);
56162306a36Sopenharmony_ci		handles[i] = INVALID_GRANT_HANDLE;
56262306a36Sopenharmony_ci	}
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	gnttab_batch_map(info->map, i);
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	for (i = 0; i < nr_grefs; i++) {
56762306a36Sopenharmony_ci		if (info->map[i].status != GNTST_okay) {
56862306a36Sopenharmony_ci			xenbus_dev_fatal(dev, info->map[i].status,
56962306a36Sopenharmony_ci					 "mapping in shared page %d from domain %d",
57062306a36Sopenharmony_ci					 gnt_refs[i], dev->otherend_id);
57162306a36Sopenharmony_ci			goto fail;
57262306a36Sopenharmony_ci		} else
57362306a36Sopenharmony_ci			handles[i] = info->map[i].handle;
57462306a36Sopenharmony_ci	}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	return 0;
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci fail:
57962306a36Sopenharmony_ci	for (i = j = 0; i < nr_grefs; i++) {
58062306a36Sopenharmony_ci		if (handles[i] != INVALID_GRANT_HANDLE) {
58162306a36Sopenharmony_ci			gnttab_set_unmap_op(&info->unmap[j],
58262306a36Sopenharmony_ci					    info->phys_addrs[i],
58362306a36Sopenharmony_ci					    GNTMAP_host_map, handles[i]);
58462306a36Sopenharmony_ci			j++;
58562306a36Sopenharmony_ci		}
58662306a36Sopenharmony_ci	}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, info->unmap, j));
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	*leaked = false;
59162306a36Sopenharmony_ci	for (i = 0; i < j; i++) {
59262306a36Sopenharmony_ci		if (info->unmap[i].status != GNTST_okay) {
59362306a36Sopenharmony_ci			*leaked = true;
59462306a36Sopenharmony_ci			break;
59562306a36Sopenharmony_ci		}
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	return -ENOENT;
59962306a36Sopenharmony_ci}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci/**
60262306a36Sopenharmony_ci * xenbus_unmap_ring
60362306a36Sopenharmony_ci * @dev: xenbus device
60462306a36Sopenharmony_ci * @handles: grant handle array
60562306a36Sopenharmony_ci * @nr_handles: number of handles in the array
60662306a36Sopenharmony_ci * @vaddrs: addresses to unmap
60762306a36Sopenharmony_ci *
60862306a36Sopenharmony_ci * Unmap memory in this domain that was imported from another domain.
60962306a36Sopenharmony_ci * Returns 0 on success and returns GNTST_* on error
61062306a36Sopenharmony_ci * (see xen/include/interface/grant_table.h).
61162306a36Sopenharmony_ci */
61262306a36Sopenharmony_cistatic int xenbus_unmap_ring(struct xenbus_device *dev, grant_handle_t *handles,
61362306a36Sopenharmony_ci			     unsigned int nr_handles, unsigned long *vaddrs)
61462306a36Sopenharmony_ci{
61562306a36Sopenharmony_ci	struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS];
61662306a36Sopenharmony_ci	int i;
61762306a36Sopenharmony_ci	int err;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	if (nr_handles > XENBUS_MAX_RING_GRANTS)
62062306a36Sopenharmony_ci		return -EINVAL;
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	for (i = 0; i < nr_handles; i++)
62362306a36Sopenharmony_ci		gnttab_set_unmap_op(&unmap[i], vaddrs[i],
62462306a36Sopenharmony_ci				    GNTMAP_host_map, handles[i]);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i));
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	err = GNTST_okay;
62962306a36Sopenharmony_ci	for (i = 0; i < nr_handles; i++) {
63062306a36Sopenharmony_ci		if (unmap[i].status != GNTST_okay) {
63162306a36Sopenharmony_ci			xenbus_dev_error(dev, unmap[i].status,
63262306a36Sopenharmony_ci					 "unmapping page at handle %d error %d",
63362306a36Sopenharmony_ci					 handles[i], unmap[i].status);
63462306a36Sopenharmony_ci			err = unmap[i].status;
63562306a36Sopenharmony_ci			break;
63662306a36Sopenharmony_ci		}
63762306a36Sopenharmony_ci	}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	return err;
64062306a36Sopenharmony_ci}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_cistatic void xenbus_map_ring_setup_grant_hvm(unsigned long gfn,
64362306a36Sopenharmony_ci					    unsigned int goffset,
64462306a36Sopenharmony_ci					    unsigned int len,
64562306a36Sopenharmony_ci					    void *data)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	struct map_ring_valloc *info = data;
64862306a36Sopenharmony_ci	unsigned long vaddr = (unsigned long)gfn_to_virt(gfn);
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	info->phys_addrs[info->idx] = vaddr;
65162306a36Sopenharmony_ci	info->addrs[info->idx] = vaddr;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	info->idx++;
65462306a36Sopenharmony_ci}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_cistatic int xenbus_map_ring_hvm(struct xenbus_device *dev,
65762306a36Sopenharmony_ci			       struct map_ring_valloc *info,
65862306a36Sopenharmony_ci			       grant_ref_t *gnt_ref,
65962306a36Sopenharmony_ci			       unsigned int nr_grefs,
66062306a36Sopenharmony_ci			       void **vaddr)
66162306a36Sopenharmony_ci{
66262306a36Sopenharmony_ci	struct xenbus_map_node *node = info->node;
66362306a36Sopenharmony_ci	int err;
66462306a36Sopenharmony_ci	void *addr;
66562306a36Sopenharmony_ci	bool leaked = false;
66662306a36Sopenharmony_ci	unsigned int nr_pages = XENBUS_PAGES(nr_grefs);
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	err = xen_alloc_unpopulated_pages(nr_pages, node->hvm.pages);
66962306a36Sopenharmony_ci	if (err)
67062306a36Sopenharmony_ci		goto out_err;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	gnttab_foreach_grant(node->hvm.pages, nr_grefs,
67362306a36Sopenharmony_ci			     xenbus_map_ring_setup_grant_hvm,
67462306a36Sopenharmony_ci			     info);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	err = __xenbus_map_ring(dev, gnt_ref, nr_grefs, node->handles,
67762306a36Sopenharmony_ci				info, GNTMAP_host_map, &leaked);
67862306a36Sopenharmony_ci	node->nr_handles = nr_grefs;
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	if (err)
68162306a36Sopenharmony_ci		goto out_free_ballooned_pages;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	addr = vmap(node->hvm.pages, nr_pages, VM_MAP | VM_IOREMAP,
68462306a36Sopenharmony_ci		    PAGE_KERNEL);
68562306a36Sopenharmony_ci	if (!addr) {
68662306a36Sopenharmony_ci		err = -ENOMEM;
68762306a36Sopenharmony_ci		goto out_xenbus_unmap_ring;
68862306a36Sopenharmony_ci	}
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	node->hvm.addr = addr;
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	spin_lock(&xenbus_valloc_lock);
69362306a36Sopenharmony_ci	list_add(&node->next, &xenbus_valloc_pages);
69462306a36Sopenharmony_ci	spin_unlock(&xenbus_valloc_lock);
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	*vaddr = addr;
69762306a36Sopenharmony_ci	info->node = NULL;
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	return 0;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci out_xenbus_unmap_ring:
70262306a36Sopenharmony_ci	if (!leaked)
70362306a36Sopenharmony_ci		xenbus_unmap_ring(dev, node->handles, nr_grefs, info->addrs);
70462306a36Sopenharmony_ci	else
70562306a36Sopenharmony_ci		pr_alert("leaking %p size %u page(s)",
70662306a36Sopenharmony_ci			 addr, nr_pages);
70762306a36Sopenharmony_ci out_free_ballooned_pages:
70862306a36Sopenharmony_ci	if (!leaked)
70962306a36Sopenharmony_ci		xen_free_unpopulated_pages(nr_pages, node->hvm.pages);
71062306a36Sopenharmony_ci out_err:
71162306a36Sopenharmony_ci	return err;
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci/**
71562306a36Sopenharmony_ci * xenbus_unmap_ring_vfree
71662306a36Sopenharmony_ci * @dev: xenbus device
71762306a36Sopenharmony_ci * @vaddr: addr to unmap
71862306a36Sopenharmony_ci *
71962306a36Sopenharmony_ci * Based on Rusty Russell's skeleton driver's unmap_page.
72062306a36Sopenharmony_ci * Unmap a page of memory in this domain that was imported from another domain.
72162306a36Sopenharmony_ci * Use xenbus_unmap_ring_vfree if you mapped in your memory with
72262306a36Sopenharmony_ci * xenbus_map_ring_valloc (it will free the virtual address space).
72362306a36Sopenharmony_ci * Returns 0 on success and returns GNTST_* on error
72462306a36Sopenharmony_ci * (see xen/include/interface/grant_table.h).
72562306a36Sopenharmony_ci */
72662306a36Sopenharmony_ciint xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
72762306a36Sopenharmony_ci{
72862306a36Sopenharmony_ci	return ring_ops->unmap(dev, vaddr);
72962306a36Sopenharmony_ci}
73062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci#ifdef CONFIG_XEN_PV
73362306a36Sopenharmony_cistatic int map_ring_apply(pte_t *pte, unsigned long addr, void *data)
73462306a36Sopenharmony_ci{
73562306a36Sopenharmony_ci	struct map_ring_valloc *info = data;
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	info->phys_addrs[info->idx++] = arbitrary_virt_to_machine(pte).maddr;
73862306a36Sopenharmony_ci	return 0;
73962306a36Sopenharmony_ci}
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_cistatic int xenbus_map_ring_pv(struct xenbus_device *dev,
74262306a36Sopenharmony_ci			      struct map_ring_valloc *info,
74362306a36Sopenharmony_ci			      grant_ref_t *gnt_refs,
74462306a36Sopenharmony_ci			      unsigned int nr_grefs,
74562306a36Sopenharmony_ci			      void **vaddr)
74662306a36Sopenharmony_ci{
74762306a36Sopenharmony_ci	struct xenbus_map_node *node = info->node;
74862306a36Sopenharmony_ci	struct vm_struct *area;
74962306a36Sopenharmony_ci	bool leaked = false;
75062306a36Sopenharmony_ci	int err = -ENOMEM;
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	area = get_vm_area(XEN_PAGE_SIZE * nr_grefs, VM_IOREMAP);
75362306a36Sopenharmony_ci	if (!area)
75462306a36Sopenharmony_ci		return -ENOMEM;
75562306a36Sopenharmony_ci	if (apply_to_page_range(&init_mm, (unsigned long)area->addr,
75662306a36Sopenharmony_ci				XEN_PAGE_SIZE * nr_grefs, map_ring_apply, info))
75762306a36Sopenharmony_ci		goto failed;
75862306a36Sopenharmony_ci	err = __xenbus_map_ring(dev, gnt_refs, nr_grefs, node->handles,
75962306a36Sopenharmony_ci				info, GNTMAP_host_map | GNTMAP_contains_pte,
76062306a36Sopenharmony_ci				&leaked);
76162306a36Sopenharmony_ci	if (err)
76262306a36Sopenharmony_ci		goto failed;
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	node->nr_handles = nr_grefs;
76562306a36Sopenharmony_ci	node->pv.area = area;
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci	spin_lock(&xenbus_valloc_lock);
76862306a36Sopenharmony_ci	list_add(&node->next, &xenbus_valloc_pages);
76962306a36Sopenharmony_ci	spin_unlock(&xenbus_valloc_lock);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	*vaddr = area->addr;
77262306a36Sopenharmony_ci	info->node = NULL;
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	return 0;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_cifailed:
77762306a36Sopenharmony_ci	if (!leaked)
77862306a36Sopenharmony_ci		free_vm_area(area);
77962306a36Sopenharmony_ci	else
78062306a36Sopenharmony_ci		pr_alert("leaking VM area %p size %u page(s)", area, nr_grefs);
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	return err;
78362306a36Sopenharmony_ci}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_cistatic int xenbus_unmap_ring_pv(struct xenbus_device *dev, void *vaddr)
78662306a36Sopenharmony_ci{
78762306a36Sopenharmony_ci	struct xenbus_map_node *node;
78862306a36Sopenharmony_ci	struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS];
78962306a36Sopenharmony_ci	unsigned int level;
79062306a36Sopenharmony_ci	int i;
79162306a36Sopenharmony_ci	bool leaked = false;
79262306a36Sopenharmony_ci	int err;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	spin_lock(&xenbus_valloc_lock);
79562306a36Sopenharmony_ci	list_for_each_entry(node, &xenbus_valloc_pages, next) {
79662306a36Sopenharmony_ci		if (node->pv.area->addr == vaddr) {
79762306a36Sopenharmony_ci			list_del(&node->next);
79862306a36Sopenharmony_ci			goto found;
79962306a36Sopenharmony_ci		}
80062306a36Sopenharmony_ci	}
80162306a36Sopenharmony_ci	node = NULL;
80262306a36Sopenharmony_ci found:
80362306a36Sopenharmony_ci	spin_unlock(&xenbus_valloc_lock);
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	if (!node) {
80662306a36Sopenharmony_ci		xenbus_dev_error(dev, -ENOENT,
80762306a36Sopenharmony_ci				 "can't find mapped virtual address %p", vaddr);
80862306a36Sopenharmony_ci		return GNTST_bad_virt_addr;
80962306a36Sopenharmony_ci	}
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	for (i = 0; i < node->nr_handles; i++) {
81262306a36Sopenharmony_ci		unsigned long addr;
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci		memset(&unmap[i], 0, sizeof(unmap[i]));
81562306a36Sopenharmony_ci		addr = (unsigned long)vaddr + (XEN_PAGE_SIZE * i);
81662306a36Sopenharmony_ci		unmap[i].host_addr = arbitrary_virt_to_machine(
81762306a36Sopenharmony_ci			lookup_address(addr, &level)).maddr;
81862306a36Sopenharmony_ci		unmap[i].dev_bus_addr = 0;
81962306a36Sopenharmony_ci		unmap[i].handle = node->handles[i];
82062306a36Sopenharmony_ci	}
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i));
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	err = GNTST_okay;
82562306a36Sopenharmony_ci	leaked = false;
82662306a36Sopenharmony_ci	for (i = 0; i < node->nr_handles; i++) {
82762306a36Sopenharmony_ci		if (unmap[i].status != GNTST_okay) {
82862306a36Sopenharmony_ci			leaked = true;
82962306a36Sopenharmony_ci			xenbus_dev_error(dev, unmap[i].status,
83062306a36Sopenharmony_ci					 "unmapping page at handle %d error %d",
83162306a36Sopenharmony_ci					 node->handles[i], unmap[i].status);
83262306a36Sopenharmony_ci			err = unmap[i].status;
83362306a36Sopenharmony_ci			break;
83462306a36Sopenharmony_ci		}
83562306a36Sopenharmony_ci	}
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	if (!leaked)
83862306a36Sopenharmony_ci		free_vm_area(node->pv.area);
83962306a36Sopenharmony_ci	else
84062306a36Sopenharmony_ci		pr_alert("leaking VM area %p size %u page(s)",
84162306a36Sopenharmony_ci			 node->pv.area, node->nr_handles);
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	kfree(node);
84462306a36Sopenharmony_ci	return err;
84562306a36Sopenharmony_ci}
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_cistatic const struct xenbus_ring_ops ring_ops_pv = {
84862306a36Sopenharmony_ci	.map = xenbus_map_ring_pv,
84962306a36Sopenharmony_ci	.unmap = xenbus_unmap_ring_pv,
85062306a36Sopenharmony_ci};
85162306a36Sopenharmony_ci#endif
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_cistruct unmap_ring_hvm
85462306a36Sopenharmony_ci{
85562306a36Sopenharmony_ci	unsigned int idx;
85662306a36Sopenharmony_ci	unsigned long addrs[XENBUS_MAX_RING_GRANTS];
85762306a36Sopenharmony_ci};
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_cistatic void xenbus_unmap_ring_setup_grant_hvm(unsigned long gfn,
86062306a36Sopenharmony_ci					      unsigned int goffset,
86162306a36Sopenharmony_ci					      unsigned int len,
86262306a36Sopenharmony_ci					      void *data)
86362306a36Sopenharmony_ci{
86462306a36Sopenharmony_ci	struct unmap_ring_hvm *info = data;
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	info->addrs[info->idx] = (unsigned long)gfn_to_virt(gfn);
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	info->idx++;
86962306a36Sopenharmony_ci}
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_cistatic int xenbus_unmap_ring_hvm(struct xenbus_device *dev, void *vaddr)
87262306a36Sopenharmony_ci{
87362306a36Sopenharmony_ci	int rv;
87462306a36Sopenharmony_ci	struct xenbus_map_node *node;
87562306a36Sopenharmony_ci	void *addr;
87662306a36Sopenharmony_ci	struct unmap_ring_hvm info = {
87762306a36Sopenharmony_ci		.idx = 0,
87862306a36Sopenharmony_ci	};
87962306a36Sopenharmony_ci	unsigned int nr_pages;
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ci	spin_lock(&xenbus_valloc_lock);
88262306a36Sopenharmony_ci	list_for_each_entry(node, &xenbus_valloc_pages, next) {
88362306a36Sopenharmony_ci		addr = node->hvm.addr;
88462306a36Sopenharmony_ci		if (addr == vaddr) {
88562306a36Sopenharmony_ci			list_del(&node->next);
88662306a36Sopenharmony_ci			goto found;
88762306a36Sopenharmony_ci		}
88862306a36Sopenharmony_ci	}
88962306a36Sopenharmony_ci	node = addr = NULL;
89062306a36Sopenharmony_ci found:
89162306a36Sopenharmony_ci	spin_unlock(&xenbus_valloc_lock);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	if (!node) {
89462306a36Sopenharmony_ci		xenbus_dev_error(dev, -ENOENT,
89562306a36Sopenharmony_ci				 "can't find mapped virtual address %p", vaddr);
89662306a36Sopenharmony_ci		return GNTST_bad_virt_addr;
89762306a36Sopenharmony_ci	}
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci	nr_pages = XENBUS_PAGES(node->nr_handles);
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	gnttab_foreach_grant(node->hvm.pages, node->nr_handles,
90262306a36Sopenharmony_ci			     xenbus_unmap_ring_setup_grant_hvm,
90362306a36Sopenharmony_ci			     &info);
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	rv = xenbus_unmap_ring(dev, node->handles, node->nr_handles,
90662306a36Sopenharmony_ci			       info.addrs);
90762306a36Sopenharmony_ci	if (!rv) {
90862306a36Sopenharmony_ci		vunmap(vaddr);
90962306a36Sopenharmony_ci		xen_free_unpopulated_pages(nr_pages, node->hvm.pages);
91062306a36Sopenharmony_ci	}
91162306a36Sopenharmony_ci	else
91262306a36Sopenharmony_ci		WARN(1, "Leaking %p, size %u page(s)\n", vaddr, nr_pages);
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	kfree(node);
91562306a36Sopenharmony_ci	return rv;
91662306a36Sopenharmony_ci}
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci/**
91962306a36Sopenharmony_ci * xenbus_read_driver_state
92062306a36Sopenharmony_ci * @path: path for driver
92162306a36Sopenharmony_ci *
92262306a36Sopenharmony_ci * Return the state of the driver rooted at the given store path, or
92362306a36Sopenharmony_ci * XenbusStateUnknown if no state can be read.
92462306a36Sopenharmony_ci */
92562306a36Sopenharmony_cienum xenbus_state xenbus_read_driver_state(const char *path)
92662306a36Sopenharmony_ci{
92762306a36Sopenharmony_ci	enum xenbus_state result;
92862306a36Sopenharmony_ci	int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
92962306a36Sopenharmony_ci	if (err)
93062306a36Sopenharmony_ci		result = XenbusStateUnknown;
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	return result;
93362306a36Sopenharmony_ci}
93462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(xenbus_read_driver_state);
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_cistatic const struct xenbus_ring_ops ring_ops_hvm = {
93762306a36Sopenharmony_ci	.map = xenbus_map_ring_hvm,
93862306a36Sopenharmony_ci	.unmap = xenbus_unmap_ring_hvm,
93962306a36Sopenharmony_ci};
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_civoid __init xenbus_ring_ops_init(void)
94262306a36Sopenharmony_ci{
94362306a36Sopenharmony_ci#ifdef CONFIG_XEN_PV
94462306a36Sopenharmony_ci	if (!xen_feature(XENFEAT_auto_translated_physmap))
94562306a36Sopenharmony_ci		ring_ops = &ring_ops_pv;
94662306a36Sopenharmony_ci	else
94762306a36Sopenharmony_ci#endif
94862306a36Sopenharmony_ci		ring_ops = &ring_ops_hvm;
94962306a36Sopenharmony_ci}
950