]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
xen/xenpv: Implement {,dev}activate_resource for ARM
authorJulien Grall <julien.grall@linaro.org>
Sun, 8 Jun 2014 15:55:38 +0000 (16:55 +0100)
committerJulien Grall <julien.grall@citrix.com>
Sat, 3 Oct 2015 18:37:33 +0000 (19:37 +0100)
sys/dev/xen/xenpv.c

index fcb634fb8c44cb05622f2dbf8dfa7204efa34c7f..356ebb9837be3fd430a84743e8210cae4b9a7d12 100644 (file)
@@ -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>
@@ -148,6 +149,64 @@ xenpv_free_physmem(device_t dev, device_t child, int res_id, struct resource *re
        return (bus_release_resource(child, SYS_RES_MEMORY, res_id, res));
 }
 
+#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 */
        DEVMETHOD(device_identify,              xenpv_identify),
@@ -160,8 +219,13 @@ static device_method_t xenpv_methods[] = {
        DEVMETHOD(bus_add_child,                bus_generic_add_child),
        DEVMETHOD(bus_alloc_resource,           bus_generic_alloc_resource),
        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
 
        /* Interface to allocate memory for foreign mappings */
        DEVMETHOD(xenmem_alloc,                 xenpv_alloc_physmem),