xenpv.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright (c) 2014 Roger Pau Monné <roger.pau@citrix.com>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. * SUCH DAMAGE.
  25. */
  26. #include <sys/cdefs.h>
  27. __FBSDID("$FreeBSD$");
  28. #include <sys/param.h>
  29. #include <sys/systm.h>
  30. #include <sys/bus.h>
  31. #include <sys/kernel.h>
  32. #include <sys/module.h>
  33. #include <sys/pcpu.h>
  34. #include <sys/rman.h>
  35. #include <sys/smp.h>
  36. #include <sys/limits.h>
  37. #include <sys/vmmeter.h>
  38. #include <vm/vm.h>
  39. #include <vm/vm_page.h>
  40. #include <vm/vm_param.h>
  41. #include <vm/vm_phys.h>
  42. #include <xen/xen-os.h>
  43. #include <xen/gnttab.h>
  44. #include "xenmem_if.h"
  45. /*
  46. * Allocate unused physical memory above 4GB in order to map memory
  47. * from foreign domains. We use memory starting at 4GB in order to
  48. * prevent clashes with MMIO/ACPI regions.
  49. *
  50. * Since this is not possible on i386 just use any available memory
  51. * chunk above 1MB and hope we don't clash with anything else.
  52. */
  53. #ifdef __amd64__
  54. #define LOW_MEM_LIMIT 0x100000000ul
  55. #elif defined(__i386__)
  56. #define LOW_MEM_LIMIT 0x100000ul
  57. #else
  58. #error "Unsupported architecture"
  59. #endif
  60. static devclass_t xenpv_devclass;
  61. static void
  62. xenpv_identify(driver_t *driver, device_t parent)
  63. {
  64. if (!xen_domain())
  65. return;
  66. /* Make sure there's only one xenpv device. */
  67. if (devclass_get_device(xenpv_devclass, 0))
  68. return;
  69. /*
  70. * The xenpv bus should be the last to attach in order
  71. * to properly detect if an ISA bus has already been added.
  72. */
  73. if (BUS_ADD_CHILD(parent, UINT_MAX, "xenpv", 0) == NULL)
  74. panic("Unable to attach xenpv bus.");
  75. }
  76. static int
  77. xenpv_probe(device_t dev)
  78. {
  79. device_set_desc(dev, "Xen PV bus");
  80. return (BUS_PROBE_NOWILDCARD);
  81. }
  82. static int
  83. xenpv_attach(device_t dev)
  84. {
  85. int error;
  86. /*
  87. * Let our child drivers identify any child devices that they
  88. * can find. Once that is done attach any devices that we
  89. * found.
  90. */
  91. error = bus_generic_probe(dev);
  92. if (error)
  93. return (error);
  94. error = bus_generic_attach(dev);
  95. return (error);
  96. }
  97. static struct resource *
  98. xenpv_alloc_physmem(device_t dev, device_t child, int *res_id, size_t size)
  99. {
  100. struct resource *res;
  101. vm_paddr_t phys_addr;
  102. int error;
  103. res = bus_alloc_resource(child, SYS_RES_MEMORY, res_id, LOW_MEM_LIMIT,
  104. ~0, size, RF_ACTIVE);
  105. if (res == NULL)
  106. return (NULL);
  107. phys_addr = rman_get_start(res);
  108. error = vm_phys_fictitious_reg_range(phys_addr, phys_addr + size,
  109. VM_MEMATTR_DEFAULT);
  110. if (error) {
  111. bus_release_resource(child, SYS_RES_MEMORY, *res_id, res);
  112. return (NULL);
  113. }
  114. return (res);
  115. }
  116. static int
  117. xenpv_free_physmem(device_t dev, device_t child, int res_id, struct resource *res)
  118. {
  119. vm_paddr_t phys_addr;
  120. size_t size;
  121. phys_addr = rman_get_start(res);
  122. size = rman_get_size(res);
  123. vm_phys_fictitious_unreg_range(phys_addr, phys_addr + size);
  124. return (bus_release_resource(child, SYS_RES_MEMORY, res_id, res));
  125. }
  126. static device_method_t xenpv_methods[] = {
  127. /* Device interface */
  128. DEVMETHOD(device_identify, xenpv_identify),
  129. DEVMETHOD(device_probe, xenpv_probe),
  130. DEVMETHOD(device_attach, xenpv_attach),
  131. DEVMETHOD(device_suspend, bus_generic_suspend),
  132. DEVMETHOD(device_resume, bus_generic_resume),
  133. /* Bus interface */
  134. DEVMETHOD(bus_add_child, bus_generic_add_child),
  135. DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
  136. DEVMETHOD(bus_release_resource, bus_generic_release_resource),
  137. DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
  138. DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
  139. /* Interface to allocate memory for foreign mappings */
  140. DEVMETHOD(xenmem_alloc, xenpv_alloc_physmem),
  141. DEVMETHOD(xenmem_free, xenpv_free_physmem),
  142. DEVMETHOD_END
  143. };
  144. static driver_t xenpv_driver = {
  145. "xenpv",
  146. xenpv_methods,
  147. 0,
  148. };
  149. DRIVER_MODULE(xenpv, nexus, xenpv_driver, xenpv_devclass, 0, 0);
  150. struct resource *
  151. xenmem_alloc(device_t dev, int *res_id, size_t size)
  152. {
  153. device_t parent;
  154. parent = device_get_parent(dev);
  155. if (parent == NULL)
  156. return (NULL);
  157. return (XENMEM_ALLOC(parent, dev, res_id, size));
  158. }
  159. int
  160. xenmem_free(device_t dev, int res_id, struct resource *res)
  161. {
  162. device_t parent;
  163. parent = device_get_parent(dev);
  164. if (parent == NULL)
  165. return (ENXIO);
  166. return (XENMEM_FREE(parent, dev, res_id, res));
  167. }