xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Ankur Arora <ankur.a.arora@oracle.com>
To: linux-kernel@vger.kernel.org, xen-devel@lists.xenproject.org
Cc: jgross@suse.com, sstabellini@kernel.org, konrad.wilk@oracle.com,
	ankur.a.arora@oracle.com, pbonzini@redhat.com,
	boris.ostrovsky@oracle.com, joao.m.martins@oracle.com
Subject: [RFC PATCH 12/16] xen/xenbus: support xenbus frontend/backend with xenhost_t
Date: Thu,  9 May 2019 10:25:36 -0700	[thread overview]
Message-ID: <20190509172540.12398-13-ankur.a.arora__16996.6459668771$1557422812$gmane$org@oracle.com> (raw)
In-Reply-To: <20190509172540.12398-1-ankur.a.arora@oracle.com>

As part of xenbus init, both frontend, backend interfaces need to talk
on the correct xenbus. This might be a local xenstore (backend) or might
be a XS_PV/XS_HVM interface (frontend) which needs to talk over xenbus
with the remote xenstored. We bootstrap all of these with evtchn/gfn
parameters from (*setup_xs)().

Given this we can do appropriate device discovery (in case of frontend)
and device connectivity for the backend.
Once done, we stash the xenhost_t * in xen_bus_type, xenbus_device or
xenbus_watch and then the frontend and backend devices implicitly use
the correct interface.

The rest of patch is just changing the interfaces where needed.

Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com>
---
 drivers/block/xen-blkback/blkback.c        |  10 +-
 drivers/net/xen-netfront.c                 |  14 +-
 drivers/pci/xen-pcifront.c                 |   4 +-
 drivers/xen/cpu_hotplug.c                  |   4 +-
 drivers/xen/manage.c                       |  28 +--
 drivers/xen/xen-balloon.c                  |   8 +-
 drivers/xen/xenbus/xenbus.h                |  45 ++--
 drivers/xen/xenbus/xenbus_client.c         |  32 +--
 drivers/xen/xenbus/xenbus_comms.c          | 121 +++++-----
 drivers/xen/xenbus/xenbus_dev_backend.c    |  30 ++-
 drivers/xen/xenbus/xenbus_dev_frontend.c   |  22 +-
 drivers/xen/xenbus/xenbus_probe.c          | 246 +++++++++++++--------
 drivers/xen/xenbus/xenbus_probe_backend.c  |  19 +-
 drivers/xen/xenbus/xenbus_probe_frontend.c |  65 +++---
 drivers/xen/xenbus/xenbus_xs.c             | 188 +++++++++-------
 include/xen/xen-ops.h                      |   3 +
 include/xen/xenbus.h                       |  54 +++--
 include/xen/xenhost.h                      |  20 ++
 18 files changed, 536 insertions(+), 377 deletions(-)

diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index fd1e19f1a49f..7ad4423c24b8 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -541,12 +541,12 @@ static void xen_vbd_resize(struct xen_blkif *blkif)
 	pr_info("VBD Resize: new size %llu\n", new_size);
 	vbd->size = new_size;
 again:
-	err = xenbus_transaction_start(&xbt);
+	err = xenbus_transaction_start(dev->xh, &xbt);
 	if (err) {
 		pr_warn("Error starting transaction\n");
 		return;
 	}
-	err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
+	err = xenbus_printf(dev->xh, xbt, dev->nodename, "sectors", "%llu",
 			    (unsigned long long)vbd_sz(vbd));
 	if (err) {
 		pr_warn("Error writing new size\n");
@@ -557,20 +557,20 @@ static void xen_vbd_resize(struct xen_blkif *blkif)
 	 * the front-end. If the current state is "connected" the
 	 * front-end will get the new size information online.
 	 */
-	err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state);
+	err = xenbus_printf(dev->xh, xbt, dev->nodename, "state", "%d", dev->state);
 	if (err) {
 		pr_warn("Error writing the state\n");
 		goto abort;
 	}
 
-	err = xenbus_transaction_end(xbt, 0);
+	err = xenbus_transaction_end(dev->xh, xbt, 0);
 	if (err == -EAGAIN)
 		goto again;
 	if (err)
 		pr_warn("Error ending transaction\n");
 	return;
 abort:
-	xenbus_transaction_end(xbt, 1);
+	xenbus_transaction_end(dev->xh, xbt, 1);
 }
 
 /*
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 1cd0a2d2ba54..ee28e8b85406 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1336,9 +1336,9 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
 
 	xenbus_switch_state(dev, XenbusStateInitialising);
 	wait_event(module_wq,
-		   xenbus_read_driver_state(dev->otherend) !=
+		   xenbus_read_driver_state(dev, dev->otherend) !=
 		   XenbusStateClosed &&
-		   xenbus_read_driver_state(dev->otherend) !=
+		   xenbus_read_driver_state(dev, dev->otherend) !=
 		   XenbusStateUnknown);
 	return netdev;
 
@@ -2145,19 +2145,19 @@ static int xennet_remove(struct xenbus_device *dev)
 
 	dev_dbg(&dev->dev, "%s\n", dev->nodename);
 
-	if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) {
+	if (xenbus_read_driver_state(dev, dev->otherend) != XenbusStateClosed) {
 		xenbus_switch_state(dev, XenbusStateClosing);
 		wait_event(module_wq,
-			   xenbus_read_driver_state(dev->otherend) ==
+			   xenbus_read_driver_state(dev, dev->otherend) ==
 			   XenbusStateClosing ||
-			   xenbus_read_driver_state(dev->otherend) ==
+			   xenbus_read_driver_state(dev, dev->otherend) ==
 			   XenbusStateUnknown);
 
 		xenbus_switch_state(dev, XenbusStateClosed);
 		wait_event(module_wq,
-			   xenbus_read_driver_state(dev->otherend) ==
+			   xenbus_read_driver_state(dev, dev->otherend) ==
 			   XenbusStateClosed ||
-			   xenbus_read_driver_state(dev->otherend) ==
+			   xenbus_read_driver_state(dev, dev->otherend) ==
 			   XenbusStateUnknown);
 	}
 
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index f894290e8b3a..4c7ef1e09ed7 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -860,7 +860,7 @@ static int pcifront_try_connect(struct pcifront_device *pdev)
 
 
 	/* Only connect once */
-	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
 	    XenbusStateInitialised)
 		goto out;
 
@@ -871,7 +871,7 @@ static int pcifront_try_connect(struct pcifront_device *pdev)
 		goto out;
 	}
 
-	err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
+	err = xenbus_scanf(pdev->xdev->xh, XBT_NIL, pdev->xdev->otherend,
 			   "root_num", "%d", &num_roots);
 	if (err == -ENOENT) {
 		xenbus_dev_error(pdev->xdev, err,
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c
index b1357aa4bc55..afeb94446d34 100644
--- a/drivers/xen/cpu_hotplug.c
+++ b/drivers/xen/cpu_hotplug.c
@@ -37,7 +37,7 @@ static int vcpu_online(unsigned int cpu)
 	char dir[16], state[16];
 
 	sprintf(dir, "cpu/%u", cpu);
-	err = xenbus_scanf(XBT_NIL, dir, "availability", "%15s", state);
+	err = xenbus_scanf(xh_default, XBT_NIL, dir, "availability", "%15s", state);
 	if (err != 1) {
 		if (!xen_initial_domain())
 			pr_err("Unable to read cpu state\n");
@@ -90,7 +90,7 @@ static int setup_cpu_watcher(struct notifier_block *notifier,
 		.node = "cpu",
 		.callback = handle_vcpu_hotplug_event};
 
-	(void)register_xenbus_watch(&cpu_watch);
+	(void)register_xenbus_watch(xh_default, &cpu_watch);
 
 	for_each_possible_cpu(cpu) {
 		if (vcpu_online(cpu) == 0) {
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 5bb01a62f214..9a69d955dd5c 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -227,14 +227,14 @@ static void shutdown_handler(struct xenbus_watch *watch,
 		return;
 
  again:
-	err = xenbus_transaction_start(&xbt);
+	err = xenbus_transaction_start(xh_default, &xbt);
 	if (err)
 		return;
 
-	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
+	str = (char *)xenbus_read(xh_default, xbt, "control", "shutdown", NULL);
 	/* Ignore read errors and empty reads. */
 	if (XENBUS_IS_ERR_READ(str)) {
-		xenbus_transaction_end(xbt, 1);
+		xenbus_transaction_end(xh_default, xbt, 1);
 		return;
 	}
 
@@ -245,9 +245,9 @@ static void shutdown_handler(struct xenbus_watch *watch,
 
 	/* Only acknowledge commands which we are prepared to handle. */
 	if (idx < ARRAY_SIZE(shutdown_handlers))
-		xenbus_write(xbt, "control", "shutdown", "");
+		xenbus_write(xh_default, xbt, "control", "shutdown", "");
 
-	err = xenbus_transaction_end(xbt, 0);
+	err = xenbus_transaction_end(xh_default, xbt, 0);
 	if (err == -EAGAIN) {
 		kfree(str);
 		goto again;
@@ -272,10 +272,10 @@ static void sysrq_handler(struct xenbus_watch *watch, const char *path,
 	int err;
 
  again:
-	err = xenbus_transaction_start(&xbt);
+	err = xenbus_transaction_start(xh_default, &xbt);
 	if (err)
 		return;
-	err = xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key);
+	err = xenbus_scanf(xh_default, xbt, "control", "sysrq", "%c", &sysrq_key);
 	if (err < 0) {
 		/*
 		 * The Xenstore watch fires directly after registering it and
@@ -287,21 +287,21 @@ static void sysrq_handler(struct xenbus_watch *watch, const char *path,
 		if (err != -ENOENT && err != -ERANGE)
 			pr_err("Error %d reading sysrq code in control/sysrq\n",
 			       err);
-		xenbus_transaction_end(xbt, 1);
+		xenbus_transaction_end(xh_default, xbt, 1);
 		return;
 	}
 
 	if (sysrq_key != '\0') {
-		err = xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
+		err = xenbus_printf(xh_default, xbt, "control", "sysrq", "%c", '\0');
 		if (err) {
 			pr_err("%s: Error %d writing sysrq in control/sysrq\n",
 			       __func__, err);
-			xenbus_transaction_end(xbt, 1);
+			xenbus_transaction_end(xh_default, xbt, 1);
 			return;
 		}
 	}
 
-	err = xenbus_transaction_end(xbt, 0);
+	err = xenbus_transaction_end(xh_default, xbt, 0);
 	if (err == -EAGAIN)
 		goto again;
 
@@ -331,7 +331,7 @@ static int setup_shutdown_watcher(void)
 #define FEATURE_PATH_SIZE (SHUTDOWN_CMD_SIZE + sizeof("feature-"))
 	char node[FEATURE_PATH_SIZE];
 
-	err = register_xenbus_watch(&shutdown_watch);
+	err = register_xenbus_watch(xh_default, &shutdown_watch);
 	if (err) {
 		pr_err("Failed to set shutdown watcher\n");
 		return err;
@@ -339,7 +339,7 @@ static int setup_shutdown_watcher(void)
 
 
 #ifdef CONFIG_MAGIC_SYSRQ
-	err = register_xenbus_watch(&sysrq_watch);
+	err = register_xenbus_watch(xh_default, &sysrq_watch);
 	if (err) {
 		pr_err("Failed to set sysrq watcher\n");
 		return err;
@@ -351,7 +351,7 @@ static int setup_shutdown_watcher(void)
 			continue;
 		snprintf(node, FEATURE_PATH_SIZE, "feature-%s",
 			 shutdown_handlers[idx].command);
-		err = xenbus_printf(XBT_NIL, "control", node, "%u", 1);
+		err = xenbus_printf(xh_default, XBT_NIL, "control", node, "%u", 1);
 		if (err) {
 			pr_err("%s: Error %d writing %s\n", __func__,
 				err, node);
diff --git a/drivers/xen/xen-balloon.c b/drivers/xen/xen-balloon.c
index 2acbfe104e46..d34d9b1af7a8 100644
--- a/drivers/xen/xen-balloon.c
+++ b/drivers/xen/xen-balloon.c
@@ -63,7 +63,7 @@ static void watch_target(struct xenbus_watch *watch,
 	static bool watch_fired;
 	static long target_diff;
 
-	err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
+	err = xenbus_scanf(xh_default, XBT_NIL, "memory", "target", "%llu", &new_target);
 	if (err != 1) {
 		/* This is ok (for domain0 at least) - so just return */
 		return;
@@ -77,9 +77,9 @@ static void watch_target(struct xenbus_watch *watch,
 	if (!watch_fired) {
 		watch_fired = true;
 
-		if ((xenbus_scanf(XBT_NIL, "memory", "static-max",
+		if ((xenbus_scanf(xh_default, XBT_NIL, "memory", "static-max",
 				  "%llu", &static_max) == 1) ||
-		    (xenbus_scanf(XBT_NIL, "memory", "memory_static_max",
+		    (xenbus_scanf(xh_default, XBT_NIL, "memory", "memory_static_max",
 				  "%llu", &static_max) == 1))
 			static_max >>= PAGE_SHIFT - 10;
 		else
@@ -103,7 +103,7 @@ static int balloon_init_watcher(struct notifier_block *notifier,
 {
 	int err;
 
-	err = register_xenbus_watch(&target_watch);
+	err = register_xenbus_watch(xh_default, &target_watch);
 	if (err)
 		pr_err("Failed to set balloon watcher\n");
 
diff --git a/drivers/xen/xenbus/xenbus.h b/drivers/xen/xenbus/xenbus.h
index 092981171df1..183c6e40bdaa 100644
--- a/drivers/xen/xenbus/xenbus.h
+++ b/drivers/xen/xenbus/xenbus.h
@@ -39,9 +39,11 @@
 #define XEN_BUS_ID_SIZE			20
 
 struct xen_bus_type {
+	xenhost_t *xh;
 	char *root;
 	unsigned int levels;
-	int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename);
+	int (*get_bus_id)(struct xen_bus_type *bus, char bus_id[XEN_BUS_ID_SIZE],
+			  const char *nodename);
 	int (*probe)(struct xen_bus_type *bus, const char *type,
 		     const char *dir);
 	void (*otherend_changed)(struct xenbus_watch *watch, const char *path,
@@ -49,13 +51,30 @@ struct xen_bus_type {
 	struct bus_type bus;
 };
 
-enum xenstore_init {
-	XS_UNKNOWN,
-	XS_PV,
-	XS_HVM,
-	XS_LOCAL,
+struct xenstore_private {
+	/* xenbus_comms.c */
+	struct work_struct probe_work;
+	struct wait_queue_head xb_waitq;
+	struct list_head xb_write_list;
+	struct task_struct *xenbus_task;
+	struct list_head reply_list;
+	int xenbus_irq;
+
+	/* xenbus_probe.c */
+	struct xenstore_domain_interface *store_interface;
+	struct blocking_notifier_head xenstore_chain;
+
+	enum xenstore_init domain_type;
+	xen_pfn_t store_gfn;
+	uint32_t store_evtchn;
+	int xenstored_ready;
+
+	/*  xenbus_xs.c */
+	struct list_head watches; /* xenhost local so we don't mix them up. */
 };
 
+#define xs_priv(xh) ((struct xenstore_private *) (xh)->xenstore_private)
+
 struct xs_watch_event {
 	struct list_head list;
 	unsigned int len;
@@ -87,18 +106,14 @@ struct xb_req_data {
 	void *par;
 };
 
-extern enum xenstore_init xen_store_domain_type;
 extern const struct attribute_group *xenbus_dev_groups[];
 extern struct mutex xs_response_mutex;
-extern struct list_head xs_reply_list;
-extern struct list_head xb_write_list;
-extern wait_queue_head_t xb_waitq;
 extern struct mutex xb_write_mutex;
 
-int xs_init(void);
-int xb_init_comms(void);
-void xb_deinit_comms(void);
-int xs_watch_msg(struct xs_watch_event *event);
+int xs_init(xenhost_t *xh);
+int xb_init_comms(xenhost_t *xh);
+void xb_deinit_comms(xenhost_t *xh);
+int xs_watch_msg(xenhost_t *xh, struct xs_watch_event *event);
 void xs_request_exit(struct xb_req_data *req);
 
 int xenbus_match(struct device *_dev, struct device_driver *_drv);
@@ -130,7 +145,7 @@ int xenbus_read_otherend_details(struct xenbus_device *xendev,
 
 void xenbus_ring_ops_init(void);
 
-int xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void *par);
+int xenbus_dev_request_and_reply(xenhost_t *xh, struct xsd_sockmsg *msg, void *par);
 void xenbus_dev_queue_reply(struct xb_req_data *req);
 
 #endif
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 5748fbaf0238..e4f8ecb9490a 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -122,7 +122,7 @@ int xenbus_watch_path(struct xenbus_device *dev, const char *path,
 	watch->node = path;
 	watch->callback = callback;
 
-	err = register_xenbus_watch(watch);
+	err = register_xenbus_watch(dev->xh, watch);
 
 	if (err) {
 		watch->node = NULL;
@@ -206,17 +206,17 @@ __xenbus_switch_state(struct xenbus_device *dev,
 again:
 	abort = 1;
 
-	err = xenbus_transaction_start(&xbt);
+	err = xenbus_transaction_start(dev->xh, &xbt);
 	if (err) {
 		xenbus_switch_fatal(dev, depth, err, "starting transaction");
 		return 0;
 	}
 
-	err = xenbus_scanf(xbt, dev->nodename, "state", "%d", &current_state);
+	err = xenbus_scanf(dev->xh, xbt, dev->nodename, "state", "%d", &current_state);
 	if (err != 1)
 		goto abort;
 
-	err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
+	err = xenbus_printf(dev->xh, xbt, dev->nodename, "state", "%d", state);
 	if (err) {
 		xenbus_switch_fatal(dev, depth, err, "writing new state");
 		goto abort;
@@ -224,7 +224,7 @@ __xenbus_switch_state(struct xenbus_device *dev,
 
 	abort = 0;
 abort:
-	err = xenbus_transaction_end(xbt, abort);
+	err = xenbus_transaction_end(dev->xh, xbt, abort);
 	if (err) {
 		if (err == -EAGAIN && !abort)
 			goto again;
@@ -279,7 +279,7 @@ static void xenbus_va_dev_error(struct xenbus_device *dev, int err,
 
 	path_buffer = kasprintf(GFP_KERNEL, "error/%s", dev->nodename);
 	if (path_buffer)
-		xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer);
+		xenbus_write(dev->xh, XBT_NIL, path_buffer, "error", printf_buffer);
 
 	kfree(printf_buffer);
 	kfree(path_buffer);
@@ -363,7 +363,7 @@ int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr,
 	int i, j;
 
 	for (i = 0; i < nr_pages; i++) {
-		err = gnttab_grant_foreign_access(dev->otherend_id,
+		err = gnttab_grant_foreign_access(dev->xh, dev->otherend_id,
 						  virt_to_gfn(vaddr), 0);
 		if (err < 0) {
 			xenbus_dev_fatal(dev, err,
@@ -379,7 +379,7 @@ int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr,
 
 fail:
 	for (j = 0; j < i; j++)
-		gnttab_end_foreign_access_ref(grefs[j], 0);
+		gnttab_end_foreign_access_ref(dev->xh, grefs[j], 0);
 	return err;
 }
 EXPORT_SYMBOL_GPL(xenbus_grant_ring);
@@ -399,7 +399,7 @@ int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
 	alloc_unbound.dom = DOMID_SELF;
 	alloc_unbound.remote_dom = dev->otherend_id;
 
-	err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+	err = hypervisor_event_channel_op(dev->xh, EVTCHNOP_alloc_unbound,
 					  &alloc_unbound);
 	if (err)
 		xenbus_dev_fatal(dev, err, "allocating event channel");
@@ -421,7 +421,7 @@ int xenbus_free_evtchn(struct xenbus_device *dev, int port)
 
 	close.port = port;
 
-	err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+	err = hypervisor_event_channel_op(dev->xh, EVTCHNOP_close, &close);
 	if (err)
 		xenbus_dev_error(dev, err, "freeing event channel %d", port);
 
@@ -478,7 +478,7 @@ static int __xenbus_map_ring(struct xenbus_device *dev,
 		handles[i] = INVALID_GRANT_HANDLE;
 	}
 
-	gnttab_batch_map(map, i);
+	gnttab_batch_map(dev->xh, map, i);
 
 	for (i = 0; i < nr_grefs; i++) {
 		if (map[i].status != GNTST_okay) {
@@ -503,7 +503,7 @@ static int __xenbus_map_ring(struct xenbus_device *dev,
 		}
 	}
 
-	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, j))
+	if (hypervisor_grant_table_op(dev->xh, GNTTABOP_unmap_grant_ref, unmap, j))
 		BUG();
 
 	*leaked = false;
@@ -761,7 +761,7 @@ static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr)
 		unmap[i].handle = node->handles[i];
 	}
 
-	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i))
+	if (hypervisor_grant_table_op(dev->xh, GNTTABOP_unmap_grant_ref, unmap, i))
 		BUG();
 
 	err = GNTST_okay;
@@ -884,7 +884,7 @@ int xenbus_unmap_ring(struct xenbus_device *dev,
 		gnttab_set_unmap_op(&unmap[i], vaddrs[i],
 				    GNTMAP_host_map, handles[i]);
 
-	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i))
+	if (hypervisor_grant_table_op(dev->xh, GNTTABOP_unmap_grant_ref, unmap, i))
 		BUG();
 
 	err = GNTST_okay;
@@ -910,10 +910,10 @@ EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
  * Return 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)
+enum xenbus_state xenbus_read_driver_state(struct xenbus_device *dev, const char *path)
 {
 	enum xenbus_state result;
-	int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
+	int err = xenbus_gather(dev->xh, XBT_NIL, path, "state", "%d", &result, NULL);
 	if (err)
 		result = XenbusStateUnknown;
 
diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c
index acbc366c1717..2494ae1a0a7e 100644
--- a/drivers/xen/xenbus/xenbus_comms.c
+++ b/drivers/xen/xenbus/xenbus_comms.c
@@ -43,31 +43,21 @@
 #include <xen/page.h>
 #include "xenbus.h"
 
-/* A list of replies. Currently only one will ever be outstanding. */
-LIST_HEAD(xs_reply_list);
-
-/* A list of write requests. */
-LIST_HEAD(xb_write_list);
-DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
 DEFINE_MUTEX(xb_write_mutex);
 
 /* Protect xenbus reader thread against save/restore. */
 DEFINE_MUTEX(xs_response_mutex);
 
-static int xenbus_irq;
-static struct task_struct *xenbus_task;
-
-static DECLARE_WORK(probe_work, xenbus_probe);
-
-
-static irqreturn_t wake_waiting(int irq, void *unused)
+static irqreturn_t wake_waiting(int irq, void *_xs)
 {
-	if (unlikely(xenstored_ready == 0)) {
-		xenstored_ready = 1;
-		schedule_work(&probe_work);
+	struct xenstore_private *xs = (struct xenstore_private *) _xs;
+
+	if (unlikely(xs->xenstored_ready == 0)) {
+			xs->xenstored_ready = 1;
+			schedule_work(&xs->probe_work);
 	}
 
-	wake_up(&xb_waitq);
+	wake_up(&xs->xb_waitq);
 	return IRQ_HANDLED;
 }
 
@@ -96,24 +86,26 @@ static const void *get_input_chunk(XENSTORE_RING_IDX cons,
 	return buf + MASK_XENSTORE_IDX(cons);
 }
 
-static int xb_data_to_write(void)
+static int xb_data_to_write(struct xenstore_private *xs)
 {
-	struct xenstore_domain_interface *intf = xen_store_interface;
+	struct xenstore_domain_interface *intf = xs->store_interface;
 
 	return (intf->req_prod - intf->req_cons) != XENSTORE_RING_SIZE &&
-		!list_empty(&xb_write_list);
+		!list_empty(&xs->xb_write_list);
 }
 
 /**
  * xb_write - low level write
+ * @xh: xenhost to send to
  * @data: buffer to send
  * @len: length of buffer
  *
  * Returns number of bytes written or -err.
  */
-static int xb_write(const void *data, unsigned int len)
+static int xb_write(xenhost_t *xh, const void *data, unsigned int len)
 {
-	struct xenstore_domain_interface *intf = xen_store_interface;
+	struct xenstore_private *xs = xs_priv(xh);
+	struct xenstore_domain_interface *intf = xs->store_interface;
 	XENSTORE_RING_IDX cons, prod;
 	unsigned int bytes = 0;
 
@@ -128,7 +120,7 @@ static int xb_write(const void *data, unsigned int len)
 			intf->req_cons = intf->req_prod = 0;
 			return -EIO;
 		}
-		if (!xb_data_to_write())
+		if (!xb_data_to_write(xs))
 			return bytes;
 
 		/* Must write data /after/ reading the consumer index. */
@@ -151,21 +143,22 @@ static int xb_write(const void *data, unsigned int len)
 
 		/* Implies mb(): other side will see the updated producer. */
 		if (prod <= intf->req_cons)
-			notify_remote_via_evtchn(xh_default, xen_store_evtchn);
+			notify_remote_via_evtchn(xh, xs->store_evtchn);
 	}
 
 	return bytes;
 }
 
-static int xb_data_to_read(void)
+static int xb_data_to_read(struct xenstore_private *xs)
 {
-	struct xenstore_domain_interface *intf = xen_store_interface;
+	struct xenstore_domain_interface *intf = xs->store_interface;
 	return (intf->rsp_cons != intf->rsp_prod);
 }
 
-static int xb_read(void *data, unsigned int len)
+static int xb_read(xenhost_t *xh, void *data, unsigned int len)
 {
-	struct xenstore_domain_interface *intf = xen_store_interface;
+	struct xenstore_private *xs = xs_priv(xh);
+	struct xenstore_domain_interface *intf = xs->store_interface;
 	XENSTORE_RING_IDX cons, prod;
 	unsigned int bytes = 0;
 
@@ -204,14 +197,15 @@ static int xb_read(void *data, unsigned int len)
 
 		/* Implies mb(): other side will see the updated consumer. */
 		if (intf->rsp_prod - cons >= XENSTORE_RING_SIZE)
-			notify_remote_via_evtchn(xh_default, xen_store_evtchn);
+			notify_remote_via_evtchn(xh, xs->store_evtchn);
 	}
 
 	return bytes;
 }
 
-static int process_msg(void)
+static int process_msg(xenhost_t *xh)
 {
+	struct xenstore_private *xs = xs_priv(xh);
 	static struct {
 		struct xsd_sockmsg msg;
 		char *body;
@@ -242,7 +236,7 @@ static int process_msg(void)
 		 */
 		mutex_lock(&xs_response_mutex);
 
-		if (!xb_data_to_read()) {
+		if (!xb_data_to_read(xh->xenstore_private)) {
 			/* We raced with save/restore: pending data 'gone'. */
 			mutex_unlock(&xs_response_mutex);
 			state.in_msg = false;
@@ -252,7 +246,7 @@ static int process_msg(void)
 
 	if (state.in_hdr) {
 		if (state.read != sizeof(state.msg)) {
-			err = xb_read((void *)&state.msg + state.read,
+			err = xb_read(xh, (void *)&state.msg + state.read,
 				      sizeof(state.msg) - state.read);
 			if (err < 0)
 				goto out;
@@ -281,7 +275,7 @@ static int process_msg(void)
 		state.read = 0;
 	}
 
-	err = xb_read(state.body + state.read, state.msg.len - state.read);
+	err = xb_read(xh, state.body + state.read, state.msg.len - state.read);
 	if (err < 0)
 		goto out;
 
@@ -293,11 +287,11 @@ static int process_msg(void)
 
 	if (state.msg.type == XS_WATCH_EVENT) {
 		state.watch->len = state.msg.len;
-		err = xs_watch_msg(state.watch);
+		err = xs_watch_msg(xh, state.watch);
 	} else {
 		err = -ENOENT;
 		mutex_lock(&xb_write_mutex);
-		list_for_each_entry(req, &xs_reply_list, list) {
+		list_for_each_entry(req, &xs->reply_list, list) {
 			if (req->msg.req_id == state.msg.req_id) {
 				list_del(&req->list);
 				err = 0;
@@ -333,8 +327,9 @@ static int process_msg(void)
 	return err;
 }
 
-static int process_writes(void)
+static int process_writes(xenhost_t *xh)
 {
+	struct xenstore_private *xs = xs_priv(xh);
 	static struct {
 		struct xb_req_data *req;
 		int idx;
@@ -344,13 +339,13 @@ static int process_writes(void)
 	unsigned int len;
 	int err = 0;
 
-	if (!xb_data_to_write())
+	if (!xb_data_to_write(xs))
 		return 0;
 
 	mutex_lock(&xb_write_mutex);
 
 	if (!state.req) {
-		state.req = list_first_entry(&xb_write_list,
+		state.req = list_first_entry(&xs->xb_write_list,
 					     struct xb_req_data, list);
 		state.idx = -1;
 		state.written = 0;
@@ -367,7 +362,7 @@ static int process_writes(void)
 			base = state.req->vec[state.idx].iov_base;
 			len = state.req->vec[state.idx].iov_len;
 		}
-		err = xb_write(base + state.written, len - state.written);
+		err = xb_write(xh, base + state.written, len - state.written);
 		if (err < 0)
 			goto out_err;
 		state.written += err;
@@ -380,7 +375,7 @@ static int process_writes(void)
 
 	list_del(&state.req->list);
 	state.req->state = xb_req_state_wait_reply;
-	list_add_tail(&state.req->list, &xs_reply_list);
+	list_add_tail(&state.req->list, &xs->reply_list);
 	state.req = NULL;
 
  out:
@@ -406,42 +401,45 @@ static int process_writes(void)
 	return err;
 }
 
-static int xb_thread_work(void)
+static int xb_thread_work(struct xenstore_private *xs)
 {
-	return xb_data_to_read() || xb_data_to_write();
+	return xb_data_to_read(xs) || xb_data_to_write(xs);
 }
 
-static int xenbus_thread(void *unused)
+static int xenbus_thread(void *_xh)
 {
+	xenhost_t *xh = (xenhost_t *)_xh;
+	struct xenstore_private *xs = xs_priv(xh);
 	int err;
 
 	while (!kthread_should_stop()) {
-		if (wait_event_interruptible(xb_waitq, xb_thread_work()))
+		if (wait_event_interruptible(xs->xb_waitq, xb_thread_work(xs)))
 			continue;
 
-		err = process_msg();
+		err = process_msg(xh);
 		if (err == -ENOMEM)
 			schedule();
 		else if (err)
 			pr_warn_ratelimited("error %d while reading message\n",
 					    err);
 
-		err = process_writes();
+		err = process_writes(xh);
 		if (err)
 			pr_warn_ratelimited("error %d while writing message\n",
 					    err);
 	}
 
-	xenbus_task = NULL;
+	xs->xenbus_task = NULL;
 	return 0;
 }
 
 /**
  * xb_init_comms - Set up interrupt handler off store event channel.
  */
-int xb_init_comms(void)
+int xb_init_comms(xenhost_t *xh)
 {
-	struct xenstore_domain_interface *intf = xen_store_interface;
+	struct xenstore_private *xs = xs_priv(xh);
+	struct xenstore_domain_interface *intf = xs->store_interface;
 
 	if (intf->req_prod != intf->req_cons)
 		pr_err("request ring is not quiescent (%08x:%08x)!\n",
@@ -455,34 +453,35 @@ int xb_init_comms(void)
 			intf->rsp_cons = intf->rsp_prod;
 	}
 
-	if (xenbus_irq) {
+	if (xs->xenbus_irq) {
 		/* Already have an irq; assume we're resuming */
-		rebind_evtchn_irq(xen_store_evtchn, xenbus_irq);
+		rebind_evtchn_irq(xs->store_evtchn, xs->xenbus_irq);
 	} else {
 		int err;
 
-		err = bind_evtchn_to_irqhandler(xh_default, xen_store_evtchn, wake_waiting,
-						0, "xenbus", &xb_waitq);
+		err = bind_evtchn_to_irqhandler(xh, xs->store_evtchn, wake_waiting,
+						0, "xenbus", xs);
 		if (err < 0) {
 			pr_err("request irq failed %i\n", err);
 			return err;
 		}
 
-		xenbus_irq = err;
+		xs->xenbus_irq = err;
 
-		if (!xenbus_task) {
-			xenbus_task = kthread_run(xenbus_thread, NULL,
+		if (!xs->xenbus_task) {
+			xs->xenbus_task = kthread_run(xenbus_thread, xh,
 						  "xenbus");
-			if (IS_ERR(xenbus_task))
-				return PTR_ERR(xenbus_task);
+			if (IS_ERR(xs->xenbus_task))
+				return PTR_ERR(xs->xenbus_task);
 		}
 	}
 
 	return 0;
 }
 
-void xb_deinit_comms(void)
+void xb_deinit_comms(xenhost_t *xh)
 {
-	unbind_from_irqhandler(xenbus_irq, &xb_waitq);
-	xenbus_irq = 0;
+	struct xenstore_private *xs = xs_priv(xh);
+	unbind_from_irqhandler(xs->xenbus_irq, xs);
+	xs->xenbus_irq = 0;
 }
diff --git a/drivers/xen/xenbus/xenbus_dev_backend.c b/drivers/xen/xenbus/xenbus_dev_backend.c
index edba5fecde4d..211f1ce53d30 100644
--- a/drivers/xen/xenbus/xenbus_dev_backend.c
+++ b/drivers/xen/xenbus/xenbus_dev_backend.c
@@ -19,6 +19,8 @@
 
 #include "xenbus.h"
 
+static xenhost_t *xh;
+
 static int xenbus_backend_open(struct inode *inode, struct file *filp)
 {
 	if (!capable(CAP_SYS_ADMIN))
@@ -31,6 +33,7 @@ static long xenbus_alloc(domid_t domid)
 {
 	struct evtchn_alloc_unbound arg;
 	int err = -EEXIST;
+	struct xenstore_private *xs = xs_priv(xh);
 
 	xs_suspend();
 
@@ -44,23 +47,23 @@ static long xenbus_alloc(domid_t domid)
 	 * unnecessarily complex for the intended use where xenstored is only
 	 * started once - so return -EEXIST if it's already running.
 	 */
-	if (xenstored_ready)
+	if (xs->xenstored_ready)
 		goto out_err;
 
-	gnttab_grant_foreign_access_ref(GNTTAB_RESERVED_XENSTORE, domid,
-			virt_to_gfn(xen_store_interface), 0 /* writable */);
+	gnttab_grant_foreign_access_ref(xh, GNTTAB_RESERVED_XENSTORE, domid,
+			virt_to_gfn(xs->store_interface), 0 /* writable */);
 
 	arg.dom = DOMID_SELF;
 	arg.remote_dom = domid;
 
-	err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &arg);
+	err = hypervisor_event_channel_op(xh, EVTCHNOP_alloc_unbound, &arg);
 	if (err)
 		goto out_err;
 
-	if (xen_store_evtchn > 0)
-		xb_deinit_comms();
+	if (xs->store_evtchn > 0)
+		xb_deinit_comms(xh);
 
-	xen_store_evtchn = arg.port;
+	xs->store_evtchn = arg.port;
 
 	xs_resume();
 
@@ -74,13 +77,15 @@ static long xenbus_alloc(domid_t domid)
 static long xenbus_backend_ioctl(struct file *file, unsigned int cmd,
 				 unsigned long data)
 {
+	struct xenstore_private *xs = xs_priv(xh);
+
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
 	switch (cmd) {
 	case IOCTL_XENBUS_BACKEND_EVTCHN:
-		if (xen_store_evtchn > 0)
-			return xen_store_evtchn;
+		if (xs->store_evtchn > 0)
+			return xs->store_evtchn;
 		return -ENODEV;
 	case IOCTL_XENBUS_BACKEND_SETUP:
 		return xenbus_alloc(data);
@@ -92,6 +97,7 @@ static long xenbus_backend_ioctl(struct file *file, unsigned int cmd,
 static int xenbus_backend_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	size_t size = vma->vm_end - vma->vm_start;
+	struct xenstore_private *xs = xs_priv(xh);
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -100,7 +106,7 @@ static int xenbus_backend_mmap(struct file *file, struct vm_area_struct *vma)
 		return -EINVAL;
 
 	if (remap_pfn_range(vma, vma->vm_start,
-			    virt_to_pfn(xen_store_interface),
+			    virt_to_pfn(xs->store_interface),
 			    size, vma->vm_page_prot))
 		return -EAGAIN;
 
@@ -125,6 +131,10 @@ static int __init xenbus_backend_init(void)
 
 	if (!xen_initial_domain())
 		return -ENODEV;
+	/*
+	 * Backends shouldn't have any truck with the remote xenhost.
+	 */
+	xh = xh_default;
 
 	err = misc_register(&xenbus_backend_dev);
 	if (err)
diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c
index c3e201025ef0..d6e0c397c6a0 100644
--- a/drivers/xen/xenbus/xenbus_dev_frontend.c
+++ b/drivers/xen/xenbus/xenbus_dev_frontend.c
@@ -58,10 +58,14 @@
 
 #include <xen/xenbus.h>
 #include <xen/xen.h>
+#include <xen/interface/xen.h>
+#include <xen/xenhost.h>
 #include <asm/xen/hypervisor.h>
 
 #include "xenbus.h"
 
+static xenhost_t *xh;
+
 /*
  * An element of a list of outstanding transactions, for which we're
  * still waiting a reply.
@@ -312,13 +316,13 @@ static void xenbus_file_free(struct kref *kref)
 	 */
 
 	list_for_each_entry_safe(trans, tmp, &u->transactions, list) {
-		xenbus_transaction_end(trans->handle, 1);
+		xenbus_transaction_end(xh, trans->handle, 1);
 		list_del(&trans->list);
 		kfree(trans);
 	}
 
 	list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) {
-		unregister_xenbus_watch(&watch->watch);
+		unregister_xenbus_watch(xh, &watch->watch);
 		list_del(&watch->list);
 		free_watch_adapter(watch);
 	}
@@ -450,7 +454,7 @@ static int xenbus_write_transaction(unsigned msg_type,
 		   (!strcmp(msg->body, "T") || !strcmp(msg->body, "F"))))
 		return xenbus_command_reply(u, XS_ERROR, "EINVAL");
 
-	rc = xenbus_dev_request_and_reply(&msg->hdr, u);
+	rc = xenbus_dev_request_and_reply(xh, &msg->hdr, u);
 	if (rc && trans) {
 		list_del(&trans->list);
 		kfree(trans);
@@ -489,7 +493,7 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
 		watch->watch.callback = watch_fired;
 		watch->dev_data = u;
 
-		err = register_xenbus_watch(&watch->watch);
+		err = register_xenbus_watch(xh, &watch->watch);
 		if (err) {
 			free_watch_adapter(watch);
 			rc = err;
@@ -500,7 +504,7 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
 		list_for_each_entry(watch, &u->watches, list) {
 			if (!strcmp(watch->token, token) &&
 			    !strcmp(watch->watch.node, path)) {
-				unregister_xenbus_watch(&watch->watch);
+				unregister_xenbus_watch(xh, &watch->watch);
 				list_del(&watch->list);
 				free_watch_adapter(watch);
 				break;
@@ -618,8 +622,9 @@ static ssize_t xenbus_file_write(struct file *filp,
 static int xenbus_file_open(struct inode *inode, struct file *filp)
 {
 	struct xenbus_file_priv *u;
+	struct xenstore_private *xs = xs_priv(xh);
 
-	if (xen_store_evtchn == 0)
+	if (xs->store_evtchn == 0)
 		return -ENOENT;
 
 	nonseekable_open(inode, filp);
@@ -687,6 +692,11 @@ static int __init xenbus_init(void)
 	if (!xen_domain())
 		return -ENODEV;
 
+	if (xen_driver_domain() && xen_nested())
+		xh = xh_remote;
+	else
+		xh = xh_default;
+
 	err = misc_register(&xenbus_dev);
 	if (err)
 		pr_err("Could not register xenbus frontend device\n");
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 049bd511f36e..bd90ba00d64c 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -65,20 +65,6 @@
 
 #include "xenbus.h"
 
-
-int xen_store_evtchn;
-EXPORT_SYMBOL_GPL(xen_store_evtchn);
-
-struct xenstore_domain_interface *xen_store_interface;
-EXPORT_SYMBOL_GPL(xen_store_interface);
-
-enum xenstore_init xen_store_domain_type;
-EXPORT_SYMBOL_GPL(xen_store_domain_type);
-
-static unsigned long xen_store_gfn;
-
-static BLOCKING_NOTIFIER_HEAD(xenstore_chain);
-
 /* If something in array of ids matches this device, return it. */
 static const struct xenbus_device_id *
 match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
@@ -112,7 +98,7 @@ static void free_otherend_details(struct xenbus_device *dev)
 static void free_otherend_watch(struct xenbus_device *dev)
 {
 	if (dev->otherend_watch.node) {
-		unregister_xenbus_watch(&dev->otherend_watch);
+		unregister_xenbus_watch(dev->xh, &dev->otherend_watch);
 		kfree(dev->otherend_watch.node);
 		dev->otherend_watch.node = NULL;
 	}
@@ -145,7 +131,7 @@ static int watch_otherend(struct xenbus_device *dev)
 int xenbus_read_otherend_details(struct xenbus_device *xendev,
 				 char *id_node, char *path_node)
 {
-	int err = xenbus_gather(XBT_NIL, xendev->nodename,
+	int err = xenbus_gather(xendev->xh, XBT_NIL, xendev->nodename,
 				id_node, "%i", &xendev->otherend_id,
 				path_node, NULL, &xendev->otherend,
 				NULL);
@@ -156,7 +142,7 @@ int xenbus_read_otherend_details(struct xenbus_device *xendev,
 		return err;
 	}
 	if (strlen(xendev->otherend) == 0 ||
-	    !xenbus_exists(XBT_NIL, xendev->otherend, "")) {
+	    !xenbus_exists(xendev->xh, XBT_NIL, xendev->otherend, "")) {
 		xenbus_dev_fatal(xendev, -ENOENT,
 				 "unable to read other end from %s.  "
 				 "missing or inaccessible.",
@@ -186,7 +172,7 @@ void xenbus_otherend_changed(struct xenbus_watch *watch,
 		return;
 	}
 
-	state = xenbus_read_driver_state(dev->otherend);
+	state = xenbus_read_driver_state(dev, dev->otherend);
 
 	dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n",
 		state, xenbus_strstate(state), dev->otherend_watch.node, path);
@@ -439,7 +425,11 @@ int xenbus_probe_node(struct xen_bus_type *bus,
 	size_t stringlen;
 	char *tmpstring;
 
-	enum xenbus_state state = xenbus_read_driver_state(nodename);
+	enum xenbus_state state;
+
+	err = xenbus_gather(bus->xh, XBT_NIL, nodename, "state", "%d", &state, NULL);
+	if (err)
+		state = XenbusStateUnknown;
 
 	if (state != XenbusStateInitialising) {
 		/* Device is not new, so ignore it.  This can happen if a
@@ -465,10 +455,11 @@ int xenbus_probe_node(struct xen_bus_type *bus,
 	xendev->devicetype = tmpstring;
 	init_completion(&xendev->down);
 
+	xendev->xh = bus->xh;
 	xendev->dev.bus = &bus->bus;
 	xendev->dev.release = xenbus_dev_release;
 
-	err = bus->get_bus_id(devname, xendev->nodename);
+	err = bus->get_bus_id(bus, devname, xendev->nodename);
 	if (err)
 		goto fail;
 
@@ -496,7 +487,7 @@ static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
 	unsigned int dir_n = 0;
 	int i;
 
-	dir = xenbus_directory(XBT_NIL, bus->root, type, &dir_n);
+	dir = xenbus_directory(bus->xh, XBT_NIL, bus->root, type, &dir_n);
 	if (IS_ERR(dir))
 		return PTR_ERR(dir);
 
@@ -516,7 +507,7 @@ int xenbus_probe_devices(struct xen_bus_type *bus)
 	char **dir;
 	unsigned int i, dir_n;
 
-	dir = xenbus_directory(XBT_NIL, bus->root, "", &dir_n);
+	dir = xenbus_directory(bus->xh, XBT_NIL, bus->root, "", &dir_n);
 	if (IS_ERR(dir))
 		return PTR_ERR(dir);
 
@@ -564,7 +555,7 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
 	if (char_count(node, '/') < 2)
 		return;
 
-	exists = xenbus_exists(XBT_NIL, node, "");
+	exists = xenbus_exists(bus->xh, XBT_NIL, node, "");
 	if (!exists) {
 		xenbus_cleanup_devices(node, &bus->bus);
 		return;
@@ -660,47 +651,61 @@ int xenbus_dev_cancel(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_cancel);
 
-/* A flag to determine if xenstored is 'ready' (i.e. has started) */
-int xenstored_ready;
-
-
-int register_xenstore_notifier(struct notifier_block *nb)
+int register_xenstore_notifier(xenhost_t *xh, struct notifier_block *nb)
 {
 	int ret = 0;
+	struct xenstore_private *xs = xs_priv(xh);
 
-	if (xenstored_ready > 0)
+	if (xs->xenstored_ready > 0)
 		ret = nb->notifier_call(nb, 0, NULL);
 	else
-		blocking_notifier_chain_register(&xenstore_chain, nb);
+		blocking_notifier_chain_register(&xs->xenstore_chain, nb);
 
 	return ret;
 }
 EXPORT_SYMBOL_GPL(register_xenstore_notifier);
 
-void unregister_xenstore_notifier(struct notifier_block *nb)
+void unregister_xenstore_notifier(xenhost_t *xh, struct notifier_block *nb)
 {
-	blocking_notifier_chain_unregister(&xenstore_chain, nb);
+	struct xenstore_private *xs = xs_priv(xh);
+
+	blocking_notifier_chain_unregister(&xs->xenstore_chain, nb);
 }
 EXPORT_SYMBOL_GPL(unregister_xenstore_notifier);
 
-void xenbus_probe(struct work_struct *unused)
+/* Needed by platform-pci */
+void __xenbus_probe(void *_xs)
 {
-	xenstored_ready = 1;
+	struct xenstore_private *xs = (struct xenstore_private *) _xs;
+	xs->xenstored_ready = 1;
 
 	/* Notify others that xenstore is up */
-	blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
+	blocking_notifier_call_chain(&xs->xenstore_chain, 0, NULL);
+}
+EXPORT_SYMBOL_GPL(__xenbus_probe);
+
+void xenbus_probe(struct work_struct *w)
+{
+	struct xenstore_private *xs = container_of(w,
+			struct xenstore_private, probe_work);
+
+	__xenbus_probe(xs);
 }
-EXPORT_SYMBOL_GPL(xenbus_probe);
 
 static int __init xenbus_probe_initcall(void)
 {
+	xenhost_t **xh;
+
 	if (!xen_domain())
 		return -ENODEV;
 
 	if (xen_initial_domain() || xen_hvm_domain())
 		return 0;
 
-	xenbus_probe(NULL);
+	for_each_xenhost(xh) {
+		struct xenstore_private *xs = xs_priv(*xh);
+		xenbus_probe(&xs->probe_work);
+	}
 	return 0;
 }
 
@@ -709,30 +714,31 @@ device_initcall(xenbus_probe_initcall);
 /* Set up event channel for xenstored which is run as a local process
  * (this is normally used only in dom0)
  */
-static int __init xenstored_local_init(void)
+static int __init xenstored_local_init(xenhost_t *xh)
 {
 	int err = -ENOMEM;
 	unsigned long page = 0;
 	struct evtchn_alloc_unbound alloc_unbound;
+	struct xenstore_private *xs = xs_priv(xh);
 
 	/* Allocate Xenstore page */
 	page = get_zeroed_page(GFP_KERNEL);
 	if (!page)
 		goto out_err;
 
-	xen_store_gfn = virt_to_gfn((void *)page);
+	xs->store_gfn = virt_to_gfn((void *)page);
 
 	/* Next allocate a local port which xenstored can bind to */
 	alloc_unbound.dom        = DOMID_SELF;
 	alloc_unbound.remote_dom = DOMID_SELF;
 
-	err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+	err = hypervisor_event_channel_op(xh, EVTCHNOP_alloc_unbound,
 					  &alloc_unbound);
 	if (err == -ENOSYS)
 		goto out_err;
 
 	BUG_ON(err);
-	xen_store_evtchn = alloc_unbound.port;
+	xs->store_evtchn = alloc_unbound.port;
 
 	return 0;
 
@@ -746,18 +752,24 @@ static int xenbus_resume_cb(struct notifier_block *nb,
 			    unsigned long action, void *data)
 {
 	int err = 0;
+	xenhost_t **xh;
 
-	if (xen_hvm_domain()) {
-		uint64_t v = 0;
+	for_each_xenhost(xh) {
+		struct xenstore_private *xs = xs_priv(*xh);
 
-		err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
-		if (!err && v)
-			xen_store_evtchn = v;
-		else
-			pr_warn("Cannot update xenstore event channel: %d\n",
-				err);
-	} else
-		xen_store_evtchn = xen_start_info->store_evtchn;
+		/* FIXME xh->resume_xs()? */
+		if (xen_hvm_domain()) {
+			uint64_t v = 0;
+
+			err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
+			if (!err && v)
+				xs->store_evtchn = v;
+			else
+				pr_warn("Cannot update xenstore event channel: %d\n",
+					err);
+		} else
+			xs->store_evtchn = xen_start_info->store_evtchn;
+	}
 
 	return err;
 }
@@ -766,67 +778,115 @@ static struct notifier_block xenbus_resume_nb = {
 	.notifier_call = xenbus_resume_cb,
 };
 
-static int __init xenbus_init(void)
+int xenbus_setup(xenhost_t *xh)
 {
+	struct xenstore_private *xs = xs_priv(xh);
 	int err = 0;
-	uint64_t v = 0;
-	xen_store_domain_type = XS_UNKNOWN;
 
-	if (!xen_domain())
-		return -ENODEV;
+	BUG_ON(xs->domain_type == XS_UNKNOWN);
 
-	xenbus_ring_ops_init();
-
-	if (xen_pv_domain())
-		xen_store_domain_type = XS_PV;
-	if (xen_hvm_domain())
-		xen_store_domain_type = XS_HVM;
-	if (xen_hvm_domain() && xen_initial_domain())
-		xen_store_domain_type = XS_LOCAL;
-	if (xen_pv_domain() && !xen_start_info->store_evtchn)
-		xen_store_domain_type = XS_LOCAL;
-	if (xen_pv_domain() && xen_start_info->store_evtchn)
-		xenstored_ready = 1;
-
-	switch (xen_store_domain_type) {
+	switch (xs->domain_type) {
 	case XS_LOCAL:
-		err = xenstored_local_init();
+		err = xenstored_local_init(xh);
 		if (err)
-			goto out_error;
-		xen_store_interface = gfn_to_virt(xen_store_gfn);
+			goto out;
+		xs->store_interface = gfn_to_virt(xs->store_gfn);
 		break;
 	case XS_PV:
-		xen_store_evtchn = xen_start_info->store_evtchn;
-		xen_store_gfn = xen_start_info->store_mfn;
-		xen_store_interface = gfn_to_virt(xen_store_gfn);
+		xs->store_interface = gfn_to_virt(xs->store_gfn);
+		xs->xenstored_ready = 1;
 		break;
 	case XS_HVM:
-		err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
-		if (err)
-			goto out_error;
-		xen_store_evtchn = (int)v;
-		err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
-		if (err)
-			goto out_error;
-		xen_store_gfn = (unsigned long)v;
-		xen_store_interface =
-			xen_remap(xen_store_gfn << XEN_PAGE_SHIFT,
+		xs->store_interface =
+			xen_remap(xs->store_gfn << XEN_PAGE_SHIFT,
 				  XEN_PAGE_SIZE);
 		break;
 	default:
 		pr_warn("Xenstore state unknown\n");
 		break;
 	}
+out:
+	return err;
+}
 
-	/* Initialize the interface to xenstore. */
-	err = xs_init();
-	if (err) {
-		pr_warn("Error initializing xenstore comms: %i\n", err);
-		goto out_error;
+int xen_hvm_setup_xs(xenhost_t *xh)
+{
+	uint64_t v = 0;
+	int err = 0;
+	struct xenstore_private *xs = xs_priv(xh);
+
+	if (xen_initial_domain()) {
+		xs->domain_type = XS_LOCAL;
+		xs->store_evtchn = 0;
+		xs->store_gfn = 0;
+	} else { /* Frontend */
+		xs->domain_type = XS_HVM;
+		err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
+		if (err)
+			goto out;
+		xs->store_evtchn = (int) v;
+
+		err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
+		if (err)
+			goto out;
+		xs->store_gfn = (int) v;
+	}
+
+out:
+	return err;
+}
+
+int xen_pv_setup_xs(xenhost_t *xh)
+{
+	struct xenstore_private *xs = xs_priv(xh);
+
+	if (xen_initial_domain()) {
+		xs->domain_type = XS_LOCAL;
+		xs->store_evtchn = 0;
+		xs->store_gfn = 0;
+	} else { /* Frontend */
+		xs->domain_type = XS_PV;
+		xs->store_evtchn = xen_start_info->store_evtchn;
+		xs->store_gfn = xen_start_info->store_mfn;
+	}
+
+	return 0;
+}
+
+static int __init xenbus_init(void)
+{
+	int err = 0;
+	struct xenstore_private *xs;
+	xenhost_t **xh;
+	int notifier = 0;
+
+	if (!xen_domain())
+		return -ENODEV;
+
+	xenbus_ring_ops_init();
+
+	for_each_xenhost(xh) {
+		(*xh)->xenstore_private = kzalloc(sizeof(*xs), GFP_KERNEL);
+		xenhost_setup_xs(*xh);
+		err = xenbus_setup(*xh);
+		if (err)
+			goto out_error;
+
+		/* Initialize the interface to xenstore. */
+		err = xs_init(*xh);
+		if (err) {
+			pr_warn("Error initializing xenstore comms: %i\n", err);
+			goto out_error;
+		}
+
+		xs = xs_priv(*xh);
+
+		if ((xs->domain_type != XS_LOCAL) &&
+		    (xs->domain_type != XS_UNKNOWN))
+		    notifier++;
 	}
 
-	if ((xen_store_domain_type != XS_LOCAL) &&
-	    (xen_store_domain_type != XS_UNKNOWN))
+	if (notifier)
 		xen_resume_notifier_register(&xenbus_resume_nb);
 
 #ifdef CONFIG_XEN_COMPAT_XENFS
diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c
index d3c53a9db5e3..f030d6ab3c31 100644
--- a/drivers/xen/xenbus/xenbus_probe_backend.c
+++ b/drivers/xen/xenbus/xenbus_probe_backend.c
@@ -57,7 +57,8 @@
 #include "xenbus.h"
 
 /* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */
-static int backend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
+static int backend_bus_id(struct xen_bus_type *bus, char bus_id[XEN_BUS_ID_SIZE],
+			  const char *nodename)
 {
 	int domid, err;
 	const char *devid, *type, *frontend;
@@ -73,14 +74,14 @@ static int backend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
 
 	devid = strrchr(nodename, '/') + 1;
 
-	err = xenbus_gather(XBT_NIL, nodename, "frontend-id", "%i", &domid,
+	err = xenbus_gather(bus->xh, XBT_NIL, nodename, "frontend-id", "%i", &domid,
 			    "frontend", NULL, &frontend,
 			    NULL);
 	if (err)
 		return err;
 	if (strlen(frontend) == 0)
 		err = -ERANGE;
-	if (!err && !xenbus_exists(XBT_NIL, frontend, ""))
+	if (!err && !xenbus_exists(bus->xh, XBT_NIL, frontend, ""))
 		err = -ENOENT;
 	kfree(frontend);
 
@@ -165,7 +166,7 @@ static int xenbus_probe_backend(struct xen_bus_type *bus, const char *type,
 	if (!nodename)
 		return -ENOMEM;
 
-	dir = xenbus_directory(XBT_NIL, nodename, "", &dir_n);
+	dir = xenbus_directory(bus->xh, XBT_NIL, nodename, "", &dir_n);
 	if (IS_ERR(dir)) {
 		kfree(nodename);
 		return PTR_ERR(dir);
@@ -189,6 +190,7 @@ static void frontend_changed(struct xenbus_watch *watch,
 
 static struct xen_bus_type xenbus_backend = {
 	.root = "backend",
+	.xh = NULL,		/* Filled at xenbus_probe_backend_init() */
 	.levels = 3,		/* backend/type/<frontend>/<id> */
 	.get_bus_id = backend_bus_id,
 	.probe = xenbus_probe_backend,
@@ -224,7 +226,7 @@ static int read_frontend_details(struct xenbus_device *xendev)
 
 int xenbus_dev_is_online(struct xenbus_device *dev)
 {
-	return !!xenbus_read_unsigned(dev->nodename, "online", 0);
+	return !!xenbus_read_unsigned(dev->xh, dev->nodename, "online", 0);
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_is_online);
 
@@ -244,7 +246,7 @@ static int backend_probe_and_watch(struct notifier_block *notifier,
 {
 	/* Enumerate devices in xenstore and watch for changes. */
 	xenbus_probe_devices(&xenbus_backend);
-	register_xenbus_watch(&be_watch);
+	register_xenbus_watch(xenbus_backend.xh,&be_watch);
 
 	return NOTIFY_DONE;
 }
@@ -258,12 +260,15 @@ static int __init xenbus_probe_backend_init(void)
 
 	DPRINTK("");
 
+	/* Backends always talk to default xenhost */
+	xenbus_backend.xh = xh_default;
+
 	/* Register ourselves with the kernel bus subsystem */
 	err = bus_register(&xenbus_backend.bus);
 	if (err)
 		return err;
 
-	register_xenstore_notifier(&xenstore_notifier);
+	register_xenstore_notifier(xenbus_backend.xh, &xenstore_notifier);
 
 	return 0;
 }
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index 3edab7cc03c3..fa2f733d1f1e 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -20,6 +20,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <xen/interface/xen.h>
+#include <xen/xenhost.h>
 #include <asm/xen/hypervisor.h>
 #include <xen/xenbus.h>
 #include <xen/events.h>
@@ -33,7 +34,8 @@
 
 
 /* device/<type>/<id> => <type>-<id> */
-static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
+static int frontend_bus_id(struct xen_bus_type *bus, char bus_id[XEN_BUS_ID_SIZE],
+				const char *nodename)
 {
 	nodename = strchr(nodename, '/');
 	if (!nodename || strlen(nodename + 1) >= XEN_BUS_ID_SIZE) {
@@ -101,13 +103,13 @@ static void xenbus_frontend_delayed_resume(struct work_struct *w)
 
 static int xenbus_frontend_dev_resume(struct device *dev)
 {
+	struct xenbus_device *xdev = to_xenbus_device(dev);
+	struct xenstore_private *xs = xs_priv(xdev->xh);
 	/*
 	 * If xenstored is running in this domain, we cannot access the backend
 	 * state at the moment, so we need to defer xenbus_dev_resume
 	 */
-	if (xen_store_domain_type == XS_LOCAL) {
-		struct xenbus_device *xdev = to_xenbus_device(dev);
-
+	if (xs->domain_type == XS_LOCAL) {
 		schedule_work(&xdev->work);
 
 		return 0;
@@ -118,8 +120,10 @@ static int xenbus_frontend_dev_resume(struct device *dev)
 
 static int xenbus_frontend_dev_probe(struct device *dev)
 {
-	if (xen_store_domain_type == XS_LOCAL) {
-		struct xenbus_device *xdev = to_xenbus_device(dev);
+	struct xenbus_device *xdev = to_xenbus_device(dev);
+	struct xenstore_private *xs = xs_priv(xdev->xh);
+
+	if (xs->domain_type == XS_LOCAL) {
 		INIT_WORK(&xdev->work, xenbus_frontend_delayed_resume);
 	}
 
@@ -136,6 +140,7 @@ static const struct dev_pm_ops xenbus_pm_ops = {
 
 static struct xen_bus_type xenbus_frontend = {
 	.root = "device",
+	.xh = NULL, 	/* initializd in xenbus_probe_frontend_init() */
 	.levels = 2,		/* device/type/<id> */
 	.get_bus_id = frontend_bus_id,
 	.probe = xenbus_probe_frontend,
@@ -242,7 +247,7 @@ static int print_device_status(struct device *dev, void *data)
 	} else if (xendev->state < XenbusStateConnected) {
 		enum xenbus_state rstate = XenbusStateUnknown;
 		if (xendev->otherend)
-			rstate = xenbus_read_driver_state(xendev->otherend);
+			rstate = xenbus_read_driver_state(xendev, xendev->otherend);
 		pr_warn("Timeout connecting to device: %s (local state %d, remote state %d)\n",
 			xendev->nodename, xendev->state, rstate);
 	}
@@ -335,7 +340,7 @@ static int backend_state;
 static void xenbus_reset_backend_state_changed(struct xenbus_watch *w,
 					const char *path, const char *token)
 {
-	if (xenbus_scanf(XBT_NIL, path, "", "%i",
+	if (xenbus_scanf(xenbus_frontend.xh, XBT_NIL, path, "", "%i",
 			 &backend_state) != 1)
 		backend_state = XenbusStateUnknown;
 	printk(KERN_DEBUG "XENBUS: backend %s %s\n",
@@ -373,26 +378,27 @@ static void xenbus_reset_frontend(char *fe, char *be, int be_state)
 	backend_state = XenbusStateUnknown;
 
 	pr_info("triggering reconnect on %s\n", be);
-	register_xenbus_watch(&be_watch);
+	register_xenbus_watch(xenbus_frontend.xh, &be_watch);
 
 	/* fall through to forward backend to state XenbusStateInitialising */
 	switch (be_state) {
 	case XenbusStateConnected:
-		xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosing);
+		xenbus_printf(xenbus_frontend.xh, XBT_NIL, fe,
+				"state", "%d", XenbusStateClosing);
 		xenbus_reset_wait_for_backend(be, XenbusStateClosing);
 		/* fall through */
 
 	case XenbusStateClosing:
-		xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosed);
+		xenbus_printf(xenbus_frontend.xh, XBT_NIL, fe, "state", "%d", XenbusStateClosed);
 		xenbus_reset_wait_for_backend(be, XenbusStateClosed);
 		/* fall through */
 
 	case XenbusStateClosed:
-		xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateInitialising);
+		xenbus_printf(xenbus_frontend.xh, XBT_NIL, fe, "state", "%d", XenbusStateInitialising);
 		xenbus_reset_wait_for_backend(be, XenbusStateInitWait);
 	}
 
-	unregister_xenbus_watch(&be_watch);
+	unregister_xenbus_watch(xenbus_frontend.xh, &be_watch);
 	pr_info("reconnect done on %s\n", be);
 	kfree(be_watch.node);
 }
@@ -406,7 +412,7 @@ static void xenbus_check_frontend(char *class, char *dev)
 	if (!frontend)
 		return;
 
-	err = xenbus_scanf(XBT_NIL, frontend, "state", "%i", &fe_state);
+	err = xenbus_scanf(xenbus_frontend.xh, XBT_NIL, frontend, "state", "%i", &fe_state);
 	if (err != 1)
 		goto out;
 
@@ -415,10 +421,10 @@ static void xenbus_check_frontend(char *class, char *dev)
 	case XenbusStateClosed:
 		printk(KERN_DEBUG "XENBUS: frontend %s %s\n",
 				frontend, xenbus_strstate(fe_state));
-		backend = xenbus_read(XBT_NIL, frontend, "backend", NULL);
+		backend = xenbus_read(xenbus_frontend.xh, XBT_NIL, frontend, "backend", NULL);
 		if (!backend || IS_ERR(backend))
 			goto out;
-		err = xenbus_scanf(XBT_NIL, backend, "state", "%i", &be_state);
+		err = xenbus_scanf(xenbus_frontend.xh, XBT_NIL, backend, "state", "%i", &be_state);
 		if (err == 1)
 			xenbus_reset_frontend(frontend, backend, be_state);
 		kfree(backend);
@@ -430,18 +436,18 @@ static void xenbus_check_frontend(char *class, char *dev)
 	kfree(frontend);
 }
 
-static void xenbus_reset_state(void)
+static void xenbus_reset_state(xenhost_t *xh)
 {
 	char **devclass, **dev;
 	int devclass_n, dev_n;
 	int i, j;
 
-	devclass = xenbus_directory(XBT_NIL, "device", "", &devclass_n);
+	devclass = xenbus_directory(xh, XBT_NIL, "device", "", &devclass_n);
 	if (IS_ERR(devclass))
 		return;
 
 	for (i = 0; i < devclass_n; i++) {
-		dev = xenbus_directory(XBT_NIL, "device", devclass[i], &dev_n);
+		dev = xenbus_directory(xh, XBT_NIL, "device", devclass[i], &dev_n);
 		if (IS_ERR(dev))
 			continue;
 		for (j = 0; j < dev_n; j++)
@@ -453,14 +459,14 @@ static void xenbus_reset_state(void)
 
 static int frontend_probe_and_watch(struct notifier_block *notifier,
 				   unsigned long event,
-				   void *data)
+				   void *xh)
 {
 	/* reset devices in Connected or Closed state */
 	if (xen_hvm_domain())
-		xenbus_reset_state();
+		xenbus_reset_state((xenhost_t *)xh);
 	/* Enumerate devices in xenstore and watch for changes. */
 	xenbus_probe_devices(&xenbus_frontend);
-	register_xenbus_watch(&fe_watch);
+	register_xenbus_watch(xh, &fe_watch);
 
 	return NOTIFY_DONE;
 }
@@ -475,12 +481,19 @@ static int __init xenbus_probe_frontend_init(void)
 
 	DPRINTK("");
 
+	if (xen_driver_domain() && xen_nested())
+		xenbus_frontend.xh = xh_remote;
+	else
+		xenbus_frontend.xh = xh_default;
+
 	/* Register ourselves with the kernel bus subsystem */
-	err = bus_register(&xenbus_frontend.bus);
-	if (err)
-		return err;
+	if (xenbus_frontend.xh) {
+		err = bus_register(&xenbus_frontend.bus);
+		if (err)
+			return err;
 
-	register_xenstore_notifier(&xenstore_notifier);
+		register_xenstore_notifier(xenbus_frontend.xh, &xenstore_notifier);
+	}
 
 	return 0;
 }
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index 74c2b9416b88..35c771bea9b6 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -76,8 +76,6 @@ static DECLARE_WAIT_QUEUE_HEAD(xs_state_enter_wq);
 /* Wait queue for suspend handling waiting for critical region being empty. */
 static DECLARE_WAIT_QUEUE_HEAD(xs_state_exit_wq);
 
-/* List of registered watches, and a lock to protect it. */
-static LIST_HEAD(watches);
 static DEFINE_SPINLOCK(watches_lock);
 
 /* List of pending watch callback events, and a lock to protect it. */
@@ -166,9 +164,9 @@ static int get_error(const char *errorstring)
 	return xsd_errors[i].errnum;
 }
 
-static bool xenbus_ok(void)
+static bool xenbus_ok(struct xenstore_private *xs)
 {
-	switch (xen_store_domain_type) {
+	switch (xs->domain_type) {
 	case XS_LOCAL:
 		switch (system_state) {
 		case SYSTEM_POWER_OFF:
@@ -190,9 +188,9 @@ static bool xenbus_ok(void)
 	return false;
 }
 
-static bool test_reply(struct xb_req_data *req)
+static bool test_reply(struct xenstore_private *xs, struct xb_req_data *req)
 {
-	if (req->state == xb_req_state_got_reply || !xenbus_ok())
+	if (req->state == xb_req_state_got_reply || !xenbus_ok(xs))
 		return true;
 
 	/* Make sure to reread req->state each time. */
@@ -201,12 +199,12 @@ static bool test_reply(struct xb_req_data *req)
 	return false;
 }
 
-static void *read_reply(struct xb_req_data *req)
+static void *read_reply(struct xenstore_private *xs, struct xb_req_data *req)
 {
 	while (req->state != xb_req_state_got_reply) {
-		wait_event(req->wq, test_reply(req));
+		wait_event(req->wq, test_reply(xs, req));
 
-		if (!xenbus_ok())
+		if (!xenbus_ok(xs))
 			/*
 			 * If we are in the process of being shut-down there is
 			 * no point of trying to contact XenBus - it is either
@@ -222,9 +220,10 @@ static void *read_reply(struct xb_req_data *req)
 	return req->body;
 }
 
-static void xs_send(struct xb_req_data *req, struct xsd_sockmsg *msg)
+static void xs_send(xenhost_t *xh, struct xb_req_data *req, struct xsd_sockmsg *msg)
 {
 	bool notify;
+	struct xenstore_private *xs = xs_priv(xh);
 
 	req->msg = *msg;
 	req->err = 0;
@@ -236,19 +235,19 @@ static void xs_send(struct xb_req_data *req, struct xsd_sockmsg *msg)
 	req->msg.req_id = xs_request_enter(req);
 
 	mutex_lock(&xb_write_mutex);
-	list_add_tail(&req->list, &xb_write_list);
-	notify = list_is_singular(&xb_write_list);
+	list_add_tail(&req->list, &xs->xb_write_list);
+	notify = list_is_singular(&xs->xb_write_list);
 	mutex_unlock(&xb_write_mutex);
 
 	if (notify)
-		wake_up(&xb_waitq);
+		wake_up(&xs->xb_waitq);
 }
 
-static void *xs_wait_for_reply(struct xb_req_data *req, struct xsd_sockmsg *msg)
+static void *xs_wait_for_reply(struct xenstore_private *xs, struct xb_req_data *req, struct xsd_sockmsg *msg)
 {
 	void *ret;
 
-	ret = read_reply(req);
+	ret = read_reply(xs, req);
 
 	xs_request_exit(req);
 
@@ -271,7 +270,7 @@ static void xs_wake_up(struct xb_req_data *req)
 	wake_up(&req->wq);
 }
 
-int xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void *par)
+int xenbus_dev_request_and_reply(xenhost_t *xh, struct xsd_sockmsg *msg, void *par)
 {
 	struct xb_req_data *req;
 	struct kvec *vec;
@@ -289,14 +288,15 @@ int xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void *par)
 	req->cb = xenbus_dev_queue_reply;
 	req->par = par;
 
-	xs_send(req, msg);
+	xs_send(xh, req, msg);
 
 	return 0;
 }
 EXPORT_SYMBOL(xenbus_dev_request_and_reply);
 
 /* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
-static void *xs_talkv(struct xenbus_transaction t,
+static void *xs_talkv(xenhost_t *xh,
+		      struct xenbus_transaction t,
 		      enum xsd_sockmsg_type type,
 		      const struct kvec *iovec,
 		      unsigned int num_vecs,
@@ -307,6 +307,7 @@ static void *xs_talkv(struct xenbus_transaction t,
 	void *ret = NULL;
 	unsigned int i;
 	int err;
+	struct xenstore_private *xs = xs_priv(xh);
 
 	req = kmalloc(sizeof(*req), GFP_NOIO | __GFP_HIGH);
 	if (!req)
@@ -323,9 +324,9 @@ static void *xs_talkv(struct xenbus_transaction t,
 	for (i = 0; i < num_vecs; i++)
 		msg.len += iovec[i].iov_len;
 
-	xs_send(req, &msg);
+	xs_send(xh, req, &msg);
 
-	ret = xs_wait_for_reply(req, &msg);
+	ret = xs_wait_for_reply(xs, req, &msg);
 	if (len)
 		*len = msg.len;
 
@@ -348,7 +349,7 @@ static void *xs_talkv(struct xenbus_transaction t,
 }
 
 /* Simplified version of xs_talkv: single message. */
-static void *xs_single(struct xenbus_transaction t,
+static void *xs_single(xenhost_t *xh, struct xenbus_transaction t,
 		       enum xsd_sockmsg_type type,
 		       const char *string,
 		       unsigned int *len)
@@ -357,7 +358,7 @@ static void *xs_single(struct xenbus_transaction t,
 
 	iovec.iov_base = (void *)string;
 	iovec.iov_len = strlen(string) + 1;
-	return xs_talkv(t, type, &iovec, 1, len);
+	return xs_talkv(xh, t, type, &iovec, 1, len);
 }
 
 /* Many commands only need an ack, don't care what it says. */
@@ -415,7 +416,7 @@ static char **split(char *strings, unsigned int len, unsigned int *num)
 	return ret;
 }
 
-char **xenbus_directory(struct xenbus_transaction t,
+char **xenbus_directory(xenhost_t *xh, struct xenbus_transaction t,
 			const char *dir, const char *node, unsigned int *num)
 {
 	char *strings, *path;
@@ -425,7 +426,7 @@ char **xenbus_directory(struct xenbus_transaction t,
 	if (IS_ERR(path))
 		return (char **)path;
 
-	strings = xs_single(t, XS_DIRECTORY, path, &len);
+	strings = xs_single(xh, t, XS_DIRECTORY, path, &len);
 	kfree(path);
 	if (IS_ERR(strings))
 		return (char **)strings;
@@ -435,13 +436,13 @@ char **xenbus_directory(struct xenbus_transaction t,
 EXPORT_SYMBOL_GPL(xenbus_directory);
 
 /* Check if a path exists. Return 1 if it does. */
-int xenbus_exists(struct xenbus_transaction t,
+int xenbus_exists(xenhost_t *xh, struct xenbus_transaction t,
 		  const char *dir, const char *node)
 {
 	char **d;
 	int dir_n;
 
-	d = xenbus_directory(t, dir, node, &dir_n);
+	d = xenbus_directory(xh, t, dir, node, &dir_n);
 	if (IS_ERR(d))
 		return 0;
 	kfree(d);
@@ -453,7 +454,7 @@ EXPORT_SYMBOL_GPL(xenbus_exists);
  * Returns a kmalloced value: call free() on it after use.
  * len indicates length in bytes.
  */
-void *xenbus_read(struct xenbus_transaction t,
+void *xenbus_read(xenhost_t *xh, struct xenbus_transaction t,
 		  const char *dir, const char *node, unsigned int *len)
 {
 	char *path;
@@ -463,7 +464,7 @@ void *xenbus_read(struct xenbus_transaction t,
 	if (IS_ERR(path))
 		return (void *)path;
 
-	ret = xs_single(t, XS_READ, path, len);
+	ret = xs_single(xh, t, XS_READ, path, len);
 	kfree(path);
 	return ret;
 }
@@ -472,7 +473,7 @@ EXPORT_SYMBOL_GPL(xenbus_read);
 /* Write the value of a single file.
  * Returns -err on failure.
  */
-int xenbus_write(struct xenbus_transaction t,
+int xenbus_write(xenhost_t *xh, struct xenbus_transaction t,
 		 const char *dir, const char *node, const char *string)
 {
 	const char *path;
@@ -488,14 +489,14 @@ int xenbus_write(struct xenbus_transaction t,
 	iovec[1].iov_base = (void *)string;
 	iovec[1].iov_len = strlen(string);
 
-	ret = xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
+	ret = xs_error(xs_talkv(xh, t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
 	kfree(path);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(xenbus_write);
 
 /* Create a new directory. */
-int xenbus_mkdir(struct xenbus_transaction t,
+int xenbus_mkdir(xenhost_t *xh, struct xenbus_transaction t,
 		 const char *dir, const char *node)
 {
 	char *path;
@@ -505,14 +506,14 @@ int xenbus_mkdir(struct xenbus_transaction t,
 	if (IS_ERR(path))
 		return PTR_ERR(path);
 
-	ret = xs_error(xs_single(t, XS_MKDIR, path, NULL));
+	ret = xs_error(xs_single(xh, t, XS_MKDIR, path, NULL));
 	kfree(path);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(xenbus_mkdir);
 
 /* Destroy a file or directory (directories must be empty). */
-int xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node)
+int xenbus_rm(xenhost_t *xh,struct xenbus_transaction t, const char *dir, const char *node)
 {
 	char *path;
 	int ret;
@@ -521,7 +522,7 @@ int xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node)
 	if (IS_ERR(path))
 		return PTR_ERR(path);
 
-	ret = xs_error(xs_single(t, XS_RM, path, NULL));
+	ret = xs_error(xs_single(xh, t, XS_RM, path, NULL));
 	kfree(path);
 	return ret;
 }
@@ -530,11 +531,11 @@ EXPORT_SYMBOL_GPL(xenbus_rm);
 /* Start a transaction: changes by others will not be seen during this
  * transaction, and changes will not be visible to others until end.
  */
-int xenbus_transaction_start(struct xenbus_transaction *t)
+int xenbus_transaction_start(xenhost_t *xh, struct xenbus_transaction *t)
 {
 	char *id_str;
 
-	id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL);
+	id_str = xs_single(xh, XBT_NIL, XS_TRANSACTION_START, "", NULL);
 	if (IS_ERR(id_str))
 		return PTR_ERR(id_str);
 
@@ -547,7 +548,7 @@ EXPORT_SYMBOL_GPL(xenbus_transaction_start);
 /* End a transaction.
  * If abandon is true, transaction is discarded instead of committed.
  */
-int xenbus_transaction_end(struct xenbus_transaction t, int abort)
+int xenbus_transaction_end(xenhost_t *xh, struct xenbus_transaction t, int abort)
 {
 	char abortstr[2];
 
@@ -556,19 +557,19 @@ int xenbus_transaction_end(struct xenbus_transaction t, int abort)
 	else
 		strcpy(abortstr, "T");
 
-	return xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL));
+	return xs_error(xs_single(xh, t, XS_TRANSACTION_END, abortstr, NULL));
 }
 EXPORT_SYMBOL_GPL(xenbus_transaction_end);
 
 /* Single read and scanf: returns -errno or num scanned. */
-int xenbus_scanf(struct xenbus_transaction t,
+int xenbus_scanf(xenhost_t *xh, struct xenbus_transaction t,
 		 const char *dir, const char *node, const char *fmt, ...)
 {
 	va_list ap;
 	int ret;
 	char *val;
 
-	val = xenbus_read(t, dir, node, NULL);
+	val = xenbus_read(xh, t, dir, node, NULL);
 	if (IS_ERR(val))
 		return PTR_ERR(val);
 
@@ -584,13 +585,13 @@ int xenbus_scanf(struct xenbus_transaction t,
 EXPORT_SYMBOL_GPL(xenbus_scanf);
 
 /* Read an (optional) unsigned value. */
-unsigned int xenbus_read_unsigned(const char *dir, const char *node,
+unsigned int xenbus_read_unsigned(xenhost_t *xh, const char *dir, const char *node,
 				  unsigned int default_val)
 {
 	unsigned int val;
 	int ret;
 
-	ret = xenbus_scanf(XBT_NIL, dir, node, "%u", &val);
+	ret = xenbus_scanf(xh, XBT_NIL, dir, node, "%u", &val);
 	if (ret <= 0)
 		val = default_val;
 
@@ -599,7 +600,7 @@ unsigned int xenbus_read_unsigned(const char *dir, const char *node,
 EXPORT_SYMBOL_GPL(xenbus_read_unsigned);
 
 /* Single printf and write: returns -errno or 0. */
-int xenbus_printf(struct xenbus_transaction t,
+int xenbus_printf(xenhost_t *xh, struct xenbus_transaction t,
 		  const char *dir, const char *node, const char *fmt, ...)
 {
 	va_list ap;
@@ -613,7 +614,7 @@ int xenbus_printf(struct xenbus_transaction t,
 	if (!buf)
 		return -ENOMEM;
 
-	ret = xenbus_write(t, dir, node, buf);
+	ret = xenbus_write(xh, t, dir, node, buf);
 
 	kfree(buf);
 
@@ -622,7 +623,7 @@ int xenbus_printf(struct xenbus_transaction t,
 EXPORT_SYMBOL_GPL(xenbus_printf);
 
 /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
-int xenbus_gather(struct xenbus_transaction t, const char *dir, ...)
+int xenbus_gather(xenhost_t *xh, struct xenbus_transaction t, const char *dir, ...)
 {
 	va_list ap;
 	const char *name;
@@ -634,7 +635,7 @@ int xenbus_gather(struct xenbus_transaction t, const char *dir, ...)
 		void *result = va_arg(ap, void *);
 		char *p;
 
-		p = xenbus_read(t, dir, name, NULL);
+		p = xenbus_read(xh, t, dir, name, NULL);
 		if (IS_ERR(p)) {
 			ret = PTR_ERR(p);
 			break;
@@ -651,7 +652,7 @@ int xenbus_gather(struct xenbus_transaction t, const char *dir, ...)
 }
 EXPORT_SYMBOL_GPL(xenbus_gather);
 
-static int xs_watch(const char *path, const char *token)
+static int xs_watch(xenhost_t *xh, const char *path, const char *token)
 {
 	struct kvec iov[2];
 
@@ -660,11 +661,11 @@ static int xs_watch(const char *path, const char *token)
 	iov[1].iov_base = (void *)token;
 	iov[1].iov_len = strlen(token) + 1;
 
-	return xs_error(xs_talkv(XBT_NIL, XS_WATCH, iov,
+	return xs_error(xs_talkv(xh, XBT_NIL, XS_WATCH, iov,
 				 ARRAY_SIZE(iov), NULL));
 }
 
-static int xs_unwatch(const char *path, const char *token)
+static int xs_unwatch(xenhost_t *xh, const char *path, const char *token)
 {
 	struct kvec iov[2];
 
@@ -673,24 +674,25 @@ static int xs_unwatch(const char *path, const char *token)
 	iov[1].iov_base = (char *)token;
 	iov[1].iov_len = strlen(token) + 1;
 
-	return xs_error(xs_talkv(XBT_NIL, XS_UNWATCH, iov,
+	return xs_error(xs_talkv(xh, XBT_NIL, XS_UNWATCH, iov,
 				 ARRAY_SIZE(iov), NULL));
 }
 
-static struct xenbus_watch *find_watch(const char *token)
+static struct xenbus_watch *find_watch(xenhost_t *xh, const char *token)
 {
 	struct xenbus_watch *i, *cmp;
+	struct xenstore_private *xs = xs_priv(xh);
 
 	cmp = (void *)simple_strtoul(token, NULL, 16);
 
-	list_for_each_entry(i, &watches, list)
+	list_for_each_entry(i, &xs->watches, list)
 		if (i == cmp)
 			return i;
 
 	return NULL;
 }
 
-int xs_watch_msg(struct xs_watch_event *event)
+int xs_watch_msg(xenhost_t *xh, struct xs_watch_event *event)
 {
 	if (count_strings(event->body, event->len) != 2) {
 		kfree(event);
@@ -700,7 +702,7 @@ int xs_watch_msg(struct xs_watch_event *event)
 	event->token = (const char *)strchr(event->body, '\0') + 1;
 
 	spin_lock(&watches_lock);
-	event->handle = find_watch(event->token);
+	event->handle = find_watch(xh, event->token);
 	if (event->handle != NULL) {
 		spin_lock(&watch_events_lock);
 		list_add_tail(&event->list, &watch_events);
@@ -719,7 +721,7 @@ int xs_watch_msg(struct xs_watch_event *event)
  * so if we are running on anything older than 4 do not attempt to read
  * control/platform-feature-xs_reset_watches.
  */
-static bool xen_strict_xenbus_quirk(void)
+static bool xen_strict_xenbus_quirk(xenhost_t *xh)
 {
 #ifdef CONFIG_X86
 	uint32_t eax, ebx, ecx, edx, base;
@@ -733,42 +735,44 @@ static bool xen_strict_xenbus_quirk(void)
 	return false;
 
 }
-static void xs_reset_watches(void)
+static void xs_reset_watches(xenhost_t *xh)
 {
 	int err;
 
 	if (!xen_hvm_domain() || xen_initial_domain())
 		return;
 
-	if (xen_strict_xenbus_quirk())
+	if (xen_strict_xenbus_quirk(xh))
 		return;
 
-	if (!xenbus_read_unsigned("control",
+	if (!xenbus_read_unsigned(xh, "control",
 				  "platform-feature-xs_reset_watches", 0))
 		return;
 
-	err = xs_error(xs_single(XBT_NIL, XS_RESET_WATCHES, "", NULL));
+	err = xs_error(xs_single(xh, XBT_NIL, XS_RESET_WATCHES, "", NULL));
 	if (err && err != -EEXIST)
 		pr_warn("xs_reset_watches failed: %d\n", err);
 }
 
 /* Register callback to watch this node. */
-int register_xenbus_watch(struct xenbus_watch *watch)
+int register_xenbus_watch(xenhost_t *xh, struct xenbus_watch *watch)
 {
 	/* Pointer in ascii is the token. */
 	char token[sizeof(watch) * 2 + 1];
+	struct xenstore_private *xs = xs_priv(xh);
 	int err;
 
 	sprintf(token, "%lX", (long)watch);
+	watch->xh = xh;
 
 	down_read(&xs_watch_rwsem);
 
 	spin_lock(&watches_lock);
-	BUG_ON(find_watch(token));
-	list_add(&watch->list, &watches);
+	BUG_ON(find_watch(xh, token));
+	list_add(&watch->list, &xs->watches);
 	spin_unlock(&watches_lock);
 
-	err = xs_watch(watch->node, token);
+	err = xs_watch(xh, watch->node, token);
 
 	if (err) {
 		spin_lock(&watches_lock);
@@ -782,7 +786,7 @@ int register_xenbus_watch(struct xenbus_watch *watch)
 }
 EXPORT_SYMBOL_GPL(register_xenbus_watch);
 
-void unregister_xenbus_watch(struct xenbus_watch *watch)
+void unregister_xenbus_watch(xenhost_t *xh, struct xenbus_watch *watch)
 {
 	struct xs_watch_event *event, *tmp;
 	char token[sizeof(watch) * 2 + 1];
@@ -793,11 +797,11 @@ void unregister_xenbus_watch(struct xenbus_watch *watch)
 	down_read(&xs_watch_rwsem);
 
 	spin_lock(&watches_lock);
-	BUG_ON(!find_watch(token));
+	BUG_ON(!find_watch(xh, token));
 	list_del(&watch->list);
 	spin_unlock(&watches_lock);
 
-	err = xs_unwatch(watch->node, token);
+	err = xs_unwatch(xh, watch->node, token);
 	if (err)
 		pr_warn("Failed to release watch %s: %i\n", watch->node, err);
 
@@ -831,24 +835,29 @@ void xs_suspend(void)
 	mutex_lock(&xs_response_mutex);
 }
 
-void xs_resume(void)
+void xs_resume()
 {
 	struct xenbus_watch *watch;
 	char token[sizeof(watch) * 2 + 1];
+	xenhost_t **xh;
 
-	xb_init_comms();
+	for_each_xenhost(xh) {
+		struct xenstore_private *xs = xs_priv(*xh);
 
-	mutex_unlock(&xs_response_mutex);
+		xb_init_comms(*xh);
 
-	xs_suspend_exit();
+		mutex_unlock(&xs_response_mutex);
 
-	/* No need for watches_lock: the xs_watch_rwsem is sufficient. */
-	list_for_each_entry(watch, &watches, list) {
-		sprintf(token, "%lX", (long)watch);
-		xs_watch(watch->node, token);
+		xs_suspend_exit();
+
+		/* No need for watches_lock: the xs_watch_rwsem is sufficient. */
+		list_for_each_entry(watch, &xs->watches, list) {
+			sprintf(token, "%lX", (long)watch);
+			xs_watch(*xh, watch->node, token);
+		}
+
+		up_write(&xs_watch_rwsem);
 	}
-
-	up_write(&xs_watch_rwsem);
 }
 
 void xs_suspend_cancel(void)
@@ -905,13 +914,18 @@ static int xs_reboot_notify(struct notifier_block *nb,
 			    unsigned long code, void *unused)
 {
 	struct xb_req_data *req;
+	xenhost_t **xh;
 
-	mutex_lock(&xb_write_mutex);
-	list_for_each_entry(req, &xs_reply_list, list)
-		wake_up(&req->wq);
-	list_for_each_entry(req, &xb_write_list, list)
-		wake_up(&req->wq);
-	mutex_unlock(&xb_write_mutex);
+	for_each_xenhost(xh) {
+		struct xenstore_private *xs = xs_priv(*xh);
+
+		mutex_lock(&xb_write_mutex);
+		list_for_each_entry(req, &xs->reply_list, list)
+			wake_up(&req->wq);
+		list_for_each_entry(req, &xs->xb_write_list, list)
+			wake_up(&req->wq);
+		mutex_unlock(&xb_write_mutex);
+	}
 	return NOTIFY_DONE;
 }
 
@@ -919,15 +933,17 @@ static struct notifier_block xs_reboot_nb = {
 	.notifier_call = xs_reboot_notify,
 };
 
-int xs_init(void)
+int xs_init(xenhost_t *xh)
 {
 	int err;
 	struct task_struct *task;
 
-	register_reboot_notifier(&xs_reboot_nb);
+	if (xh->type != xenhost_r2)
+		/* Needs to be moved out */
+		register_reboot_notifier(&xs_reboot_nb);
 
 	/* Initialize the shared memory rings to talk to xenstored */
-	err = xb_init_comms();
+	err = xb_init_comms(xh);
 	if (err)
 		return err;
 
@@ -936,7 +952,7 @@ int xs_init(void)
 		return PTR_ERR(task);
 
 	/* shutdown watches for kexec boot */
-	xs_reset_watches();
+	xs_reset_watches(xh);
 
 	return 0;
 }
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 75be9059893f..3ba2f6b1e196 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -204,6 +204,9 @@ int xen_unmap_domain_gfn_range(struct vm_area_struct *vma,
 int xen_xlate_map_ballooned_pages(xen_pfn_t **pfns, void **vaddr,
 				  unsigned long nr_grant_frames);
 
+int xen_hvm_setup_xs(xenhost_t *xh);
+int xen_pv_setup_xs(xenhost_t *xh);
+
 bool xen_running_on_version_or_later(unsigned int major, unsigned int minor);
 
 efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc);
diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
index 869c816d5f8c..8f8c39008e15 100644
--- a/include/xen/xenbus.h
+++ b/include/xen/xenbus.h
@@ -43,6 +43,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <xen/interface/xen.h>
+#include <xen/xenhost.h>
 #include <xen/interface/grant_table.h>
 #include <xen/interface/io/xenbus.h>
 #include <xen/interface/io/xs_wire.h>
@@ -58,6 +59,8 @@ struct xenbus_watch
 
 	/* Path being watched. */
 	const char *node;
+	/* On xenhost. */
+	xenhost_t *xh;
 
 	/* Callback (executed in a process context with no locks held). */
 	void (*callback)(struct xenbus_watch *,
@@ -70,6 +73,7 @@ struct xenbus_device {
 	const char *devicetype;
 	const char *nodename;
 	const char *otherend;
+	xenhost_t *xh;
 	int otherend_id;
 	struct xenbus_watch otherend_watch;
 	struct device dev;
@@ -78,6 +82,13 @@ struct xenbus_device {
 	struct work_struct work;
 };
 
+enum xenstore_init {
+	XS_UNKNOWN,
+	XS_PV,
+	XS_HVM,
+	XS_LOCAL,
+};
+
 static inline struct xenbus_device *to_xenbus_device(struct device *dev)
 {
 	return container_of(dev, struct xenbus_device, dev);
@@ -133,52 +144,51 @@ struct xenbus_transaction
 /* Nil transaction ID. */
 #define XBT_NIL ((struct xenbus_transaction) { 0 })
 
-char **xenbus_directory(struct xenbus_transaction t,
+char **xenbus_directory(xenhost_t *xh, struct xenbus_transaction t,
 			const char *dir, const char *node, unsigned int *num);
-void *xenbus_read(struct xenbus_transaction t,
+void *xenbus_read(xenhost_t *xh, struct xenbus_transaction t,
 		  const char *dir, const char *node, unsigned int *len);
-int xenbus_write(struct xenbus_transaction t,
+int xenbus_write(xenhost_t *xh, struct xenbus_transaction t,
 		 const char *dir, const char *node, const char *string);
-int xenbus_mkdir(struct xenbus_transaction t,
+int xenbus_mkdir(xenhost_t *xh, struct xenbus_transaction t,
 		 const char *dir, const char *node);
-int xenbus_exists(struct xenbus_transaction t,
+int xenbus_exists(xenhost_t *xh, struct xenbus_transaction t,
 		  const char *dir, const char *node);
-int xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node);
-int xenbus_transaction_start(struct xenbus_transaction *t);
-int xenbus_transaction_end(struct xenbus_transaction t, int abort);
+int xenbus_rm(xenhost_t *xh, struct xenbus_transaction t, const char *dir, const char *node);
+int xenbus_transaction_start(xenhost_t *xh, struct xenbus_transaction *t);
+int xenbus_transaction_end(xenhost_t *xh, struct xenbus_transaction t, int abort);
 
 /* Single read and scanf: returns -errno or num scanned if > 0. */
-__scanf(4, 5)
-int xenbus_scanf(struct xenbus_transaction t,
+__scanf(5, 6)
+int xenbus_scanf(xenhost_t *xh, struct xenbus_transaction t,
 		 const char *dir, const char *node, const char *fmt, ...);
 
 /* Read an (optional) unsigned value. */
-unsigned int xenbus_read_unsigned(const char *dir, const char *node,
+unsigned int xenbus_read_unsigned(xenhost_t *xh, const char *dir, const char *node,
 				  unsigned int default_val);
 
 /* Single printf and write: returns -errno or 0. */
-__printf(4, 5)
-int xenbus_printf(struct xenbus_transaction t,
+__printf(5, 6)
+int xenbus_printf(xenhost_t *xh, struct xenbus_transaction t,
 		  const char *dir, const char *node, const char *fmt, ...);
 
 /* Generic read function: NULL-terminated triples of name,
  * sprintf-style type string, and pointer. Returns 0 or errno.*/
-int xenbus_gather(struct xenbus_transaction t, const char *dir, ...);
+int xenbus_gather(xenhost_t *xh, struct xenbus_transaction t, const char *dir, ...);
 
 /* notifer routines for when the xenstore comes up */
-extern int xenstored_ready;
-int register_xenstore_notifier(struct notifier_block *nb);
-void unregister_xenstore_notifier(struct notifier_block *nb);
+int register_xenstore_notifier(xenhost_t *xh, struct notifier_block *nb);
+void unregister_xenstore_notifier(xenhost_t *xh, struct notifier_block *nb);
 
-int register_xenbus_watch(struct xenbus_watch *watch);
-void unregister_xenbus_watch(struct xenbus_watch *watch);
+int register_xenbus_watch(xenhost_t *xh, struct xenbus_watch *watch);
+void unregister_xenbus_watch(xenhost_t *xh, struct xenbus_watch *watch);
 void xs_suspend(void);
 void xs_resume(void);
 void xs_suspend_cancel(void);
 
 struct work_struct;
 
-void xenbus_probe(struct work_struct *);
+void __xenbus_probe(void *xs);
 
 #define XENBUS_IS_ERR_READ(str) ({			\
 	if (!IS_ERR(str) && strlen(str) == 0) {		\
@@ -218,7 +228,7 @@ int xenbus_unmap_ring(struct xenbus_device *dev,
 int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port);
 int xenbus_free_evtchn(struct xenbus_device *dev, int port);
 
-enum xenbus_state xenbus_read_driver_state(const char *path);
+enum xenbus_state xenbus_read_driver_state(struct xenbus_device *dev, const char *path);
 
 __printf(3, 4)
 void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...);
@@ -230,7 +240,5 @@ int xenbus_dev_is_online(struct xenbus_device *dev);
 int xenbus_frontend_closed(struct xenbus_device *dev);
 
 extern const struct file_operations xen_xenbus_fops;
-extern struct xenstore_domain_interface *xen_store_interface;
-extern int xen_store_evtchn;
 
 #endif /* _XEN_XENBUS_H */
diff --git a/include/xen/xenhost.h b/include/xen/xenhost.h
index acee0c7872b6..91574ecaad6c 100644
--- a/include/xen/xenhost.h
+++ b/include/xen/xenhost.h
@@ -140,6 +140,9 @@ typedef struct {
 		void *gnttab_status_vm_area;
 		void *auto_xlat_grant_frames;
 	};
+
+	/* xenstore private state */
+	void *xenstore_private;
 } xenhost_t;
 
 typedef struct xenhost_ops {
@@ -228,6 +231,17 @@ typedef struct xenhost_ops {
 	int (*alloc_ballooned_pages)(xenhost_t *xh, int nr_pages, struct page **pages);
 	void (*free_ballooned_pages)(xenhost_t *xh, int nr_pages, struct page **pages);
 
+	/*
+	 * xenbus: as part of xenbus-init, frontend/backend need to talk to the
+	 * correct xenbus.  This might be a local xenstore (backend) or might
+	 * be a XS_PV/XS_HVM interface (frontend). We bootstrap these with
+	 * evtchn/gfn parameters from (*setup_xs)().
+	 *
+	 * Once done, stash the xenhost_t * in xen_bus_type, xenbus_device or
+	 * xenbus_watch and then the frontend and backend devices implicitly
+	 * use the correct interface.
+	 */
+	int (*setup_xs)(xenhost_t *xh);
 } xenhost_ops_t;
 
 extern xenhost_t *xh_default, *xh_remote;
@@ -279,4 +293,10 @@ static inline void xenhost_probe_vcpu_id(xenhost_t *xh, int cpu)
 	(xh->ops->probe_vcpu_id)(xh, cpu);
 }
 
+static inline void xenhost_setup_xs(xenhost_t *xh)
+{
+	if (xh)
+		(xh->ops->setup_xs)(xh);
+}
+
 #endif /* __XENHOST_H */
-- 
2.20.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2019-05-09 17:25 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-09 17:25 [Xen-devel] [RFC PATCH 00/16] xenhost support Ankur Arora
2019-05-09 17:25 ` [Xen-devel] [RFC PATCH 01/16] x86/xen: add xenhost_t interface Ankur Arora
2019-06-07 15:04   ` Juergen Gross
2019-06-11  7:16     ` Ankur Arora
2019-06-14 11:52       ` Juergen Gross
2019-05-09 17:25 ` Ankur Arora
2019-05-09 17:25 ` [RFC PATCH 02/16] x86/xen: cpuid support in xenhost_t Ankur Arora
2019-05-09 17:25   ` [Xen-devel] " Ankur Arora
2019-06-12 21:09   ` Andrew Cooper
2019-05-09 17:25 ` [Xen-devel] [RFC PATCH 03/16] x86/xen: make hypercall_page generic Ankur Arora
2019-05-09 17:25 ` Ankur Arora
2019-05-09 17:25 ` [RFC PATCH 04/16] x86/xen: hypercall support for xenhost_t Ankur Arora
2019-05-09 17:25 ` [Xen-devel] " Ankur Arora
2019-06-12 21:15   ` Andrew Cooper
2019-06-14  7:20     ` Ankur Arora
2019-06-14  7:35       ` Juergen Gross
2019-06-14  8:00         ` Andrew Cooper
2019-05-09 17:25 ` [RFC PATCH 05/16] x86/xen: add feature support in xenhost_t Ankur Arora
2019-05-09 17:25 ` [Xen-devel] " Ankur Arora
2019-05-09 17:25 ` [Xen-devel] [RFC PATCH 06/16] x86/xen: add shared_info support to xenhost_t Ankur Arora
2019-06-07 15:08   ` Juergen Gross
2019-06-08  5:01     ` Ankur Arora
2019-05-09 17:25 ` Ankur Arora
2019-05-09 17:25 ` [RFC PATCH 07/16] x86/xen: make vcpu_info part of xenhost_t Ankur Arora
2019-05-09 17:25   ` [Xen-devel] " Ankur Arora
2019-06-14 11:53   ` Juergen Gross
2019-06-17  6:28     ` Ankur Arora
2019-05-09 17:25 ` [RFC PATCH 08/16] x86/xen: irq/upcall handling with multiple xenhosts Ankur Arora
2019-05-09 17:25 ` [Xen-devel] " Ankur Arora
2019-06-14 12:01   ` Juergen Gross
2019-05-09 17:25 ` [RFC PATCH 09/16] xen/evtchn: support evtchn in xenhost_t Ankur Arora
2019-05-09 17:25 ` [Xen-devel] " Ankur Arora
2019-06-14 12:04   ` Juergen Gross
2019-06-17  6:09     ` Ankur Arora
2019-05-09 17:25 ` [RFC PATCH 10/16] xen/balloon: support ballooning " Ankur Arora
2019-05-09 17:25 ` [Xen-devel] " Ankur Arora
2019-06-17  9:28   ` Juergen Gross
2019-06-19  2:24     ` Ankur Arora
2019-05-09 17:25 ` [RFC PATCH 11/16] xen/grant-table: make grant-table xenhost aware Ankur Arora
2019-05-09 17:25   ` [Xen-devel] " Ankur Arora
2019-06-17  9:36   ` Juergen Gross
2019-06-19  2:25     ` Ankur Arora
2019-05-09 17:25 ` Ankur Arora [this message]
2019-05-09 17:25 ` [Xen-devel] [RFC PATCH 12/16] xen/xenbus: support xenbus frontend/backend with xenhost_t Ankur Arora
2019-06-17  9:50   ` Juergen Gross
2019-06-19  2:38     ` Ankur Arora
2019-05-09 17:25 ` [Xen-devel] [RFC PATCH 13/16] drivers/xen: gnttab, evtchn, xenbus API changes Ankur Arora
2019-06-17 10:07   ` Juergen Gross
2019-06-19  2:55     ` Ankur Arora
2019-05-09 17:25 ` Ankur Arora
2019-05-09 17:25 ` [Xen-devel] [RFC PATCH 14/16] xen/blk: " Ankur Arora
2019-06-17 10:14   ` Juergen Gross
2019-06-19  2:59     ` Ankur Arora
2019-05-09 17:25 ` Ankur Arora
2019-05-09 17:25 ` [RFC PATCH 15/16] xen/net: " Ankur Arora
2019-05-09 17:25 ` [Xen-devel] " Ankur Arora
2019-06-17 10:14   ` Juergen Gross
2019-05-09 17:25 ` [Xen-devel] [RFC PATCH 16/16] xen/grant-table: host_addr fixup in mapping on xenhost_r0 Ankur Arora
2019-06-17 10:55   ` Juergen Gross
2019-06-19  3:02     ` Ankur Arora
2019-05-09 17:25 ` Ankur Arora
2019-06-07 14:51 ` [Xen-devel] [RFC PATCH 00/16] xenhost support Juergen Gross
2019-06-07 15:22   ` Joao Martins
2019-06-07 16:21     ` Juergen Gross
2019-06-08  5:50       ` Ankur Arora
2019-06-08  5:33   ` Ankur Arora

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='20190509172540.12398-13-ankur.a.arora__16996.6459668771$1557422812$gmane$org@oracle.com' \
    --to=ankur.a.arora@oracle.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=jgross@suse.com \
    --cc=joao.m.martins@oracle.com \
    --cc=konrad.wilk@oracle.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).