From 0a85afaeceb73a7088b7be2ff5a5831e2b4208bf Mon Sep 17 00:00:00 2001
From: Julien Grall <julien.grall@linaro.org>
Date: Sun, 8 Jun 2014 16:55:38 +0100
Subject: [PATCH 2/5] xen/xenpv: Implement {,dev}activate_resource for ARM

---
 sys/dev/xen/xenpv.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/sys/dev/xen/xenpv.c b/sys/dev/xen/xenpv.c
index d709e4c..fc732d8 100644
--- a/sys/dev/xen/xenpv.c
+++ b/sys/dev/xen/xenpv.c
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
+#include <sys/rman.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/pcpu.h>
@@ -103,6 +104,7 @@ xenpv_attach(device_t dev)
 	return (0);
 }
 
+#ifndef __arm__
 static struct resource *
 xenpv_alloc_resource(device_t dev, device_t child, int type, int *rid,
     u_long start, u_long end, u_long count, u_int flags)
@@ -120,6 +122,65 @@ xenpv_alloc_resource(device_t dev, device_t child, int type, int *rid,
         return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
 	    count, flags));
 }
+#endif
+
+#if defined(__arm__)
+static int
+xenpv_activate_resource(device_t bus, device_t child, int type, int rid,
+			struct resource *r)
+{
+	int err;
+	bus_addr_t paddr;
+	bus_size_t psize;
+	bus_space_handle_t vaddr;
+
+	/* On ARM, ring buffer and other pages shared with a guest must be
+	 * mapped cacheable. But the Nexus is mapping them with DEVICE attribute.
+	 * As every xen device is linked to xenpv, we can override the
+	 * bus_activate_resource callback here.
+	 */
+	if (type != SYS_RES_MEMORY)
+		return bus_generic_activate_resource(bus, child, type, rid,
+						     r);
+
+	if ((err = rman_activate_resource(r)) != 0)
+		return (err);
+
+	paddr = (bus_addr_t)rman_get_start(r);
+	psize = (bus_size_t)rman_get_size(r);
+	vaddr = (bus_space_handle_t)xen_pmap((vm_offset_t)paddr,
+					     (vm_size_t)psize);
+	if (vaddr == 0) {
+		rman_deactivate_resource(r);
+		return (ENOMEM);
+	}
+	rman_set_bustag(r, (void *)1);
+	rman_set_virtual(r, (void *)vaddr);
+	rman_set_bushandle(r, vaddr);
+
+	return (0);
+}
+
+static int
+xenpv_deactivate_resource(device_t bus, device_t child, int type, int rid,
+			  struct resource *r)
+{
+	bus_size_t psize;
+	bus_space_handle_t vaddr;
+
+	psize = (bus_size_t)rman_get_size(r);
+	vaddr = rman_get_bushandle(r);
+
+	if (vaddr != 0) {
+		xen_unmap((vm_offset_t)vaddr, (vm_size_t)psize);
+		rman_set_virtual(r, NULL);
+		rman_set_bushandle(r, 0);
+	}
+
+	return (rman_deactivate_resource(r));
+}
+
+#endif
 
 static device_method_t xenpv_methods[] = {
 	/* Device interface */
@@ -131,10 +192,20 @@ static device_method_t xenpv_methods[] = {
 
 	/* Bus interface */
 	DEVMETHOD(bus_add_child,		bus_generic_add_child),
+
+#if defined(__arm__)
+	DEVMETHOD(bus_alloc_resource,		bus_generic_alloc_resource),
+#else
 	DEVMETHOD(bus_alloc_resource,		xenpv_alloc_resource),
+#endif
 	DEVMETHOD(bus_release_resource,		bus_generic_release_resource),
+#if defined(__arm__)
+	DEVMETHOD(bus_activate_resource,	xenpv_activate_resource),
+	DEVMETHOD(bus_deactivate_resource,	xenpv_deactivate_resource),
+#else
 	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
 	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
+#endif
 
 	DEVMETHOD_END
 };
-- 
2.1.0

