Page MenuHomeFreeBSD

D44251.diff
No OneTemporary

D44251.diff

diff --git a/sys/dev/xen/bus/xenpv.c b/sys/dev/xen/bus/xenpv.c
--- a/sys/dev/xen/bus/xenpv.c
+++ b/sys/dev/xen/bus/xenpv.c
@@ -65,6 +65,12 @@
#define LOW_MEM_LIMIT 0
#endif
+static struct rman unpopulated_mem = {
+ .rm_end = ~0,
+ .rm_type = RMAN_ARRAY,
+ .rm_descr = "Xen unpopulated memory",
+};
+
static void
xenpv_identify(driver_t *driver, device_t parent)
{
@@ -91,10 +97,24 @@
return (BUS_PROBE_NOWILDCARD);
}
+/* Dummy init for arches that don't have a specific implementation. */
+int __weak_symbol
+xen_arch_init_physmem(device_t dev, struct rman *mem)
+{
+ return (0);
+}
+
static int
xenpv_attach(device_t dev)
{
- int error;
+ int error = rman_init(&unpopulated_mem);
+
+ if (error != 0)
+ return (error);
+
+ error = xen_arch_init_physmem(dev, &unpopulated_mem);
+ if (error != 0)
+ return (error);
/*
* Let our child drivers identify any child devices that they
@@ -110,6 +130,14 @@
return (error);
}
+static int
+release_unpopulated_mem(device_t dev, struct resource *res)
+{
+
+ return (rman_is_region_manager(res, &unpopulated_mem) ?
+ rman_release_resource(res) : bus_release_resource(dev, res));
+}
+
static struct resource *
xenpv_alloc_physmem(device_t dev, device_t child, int *res_id, size_t size)
{
@@ -117,17 +145,48 @@
vm_paddr_t phys_addr;
void *virt_addr;
int error;
+ const unsigned int flags = RF_ACTIVE | RF_UNMAPPED |
+ RF_ALIGNMENT_LOG2(PAGE_SHIFT);
- res = bus_alloc_resource(child, SYS_RES_MEMORY, res_id, LOW_MEM_LIMIT,
- ~0, size, RF_ACTIVE | RF_UNMAPPED);
- if (res == NULL)
+ KASSERT((size & PAGE_MASK) == 0, ("unaligned size requested"));
+ size = round_page(size);
+
+ /* Attempt to allocate from arch resource manager. */
+ res = rman_reserve_resource(&unpopulated_mem, 0, ~0, size, flags,
+ child);
+ if (res != NULL) {
+ rman_set_rid(res, *res_id);
+ rman_set_type(res, SYS_RES_MEMORY);
+ } else {
+ static bool warned = false;
+
+ /* Fallback to generic MMIO allocator. */
+ if (__predict_false(!warned)) {
+ warned = true;
+ device_printf(dev,
+ "unable to allocate from arch specific routine, "
+ "fall back to unused memory areas\n");
+ }
+ res = bus_alloc_resource(child, SYS_RES_MEMORY, res_id,
+ LOW_MEM_LIMIT, ~0, size, flags);
+ }
+
+ if (res == NULL) {
+ device_printf(dev,
+ "failed to allocate Xen unpopulated memory\n");
return (NULL);
+ }
phys_addr = rman_get_start(res);
error = vm_phys_fictitious_reg_range(phys_addr, phys_addr + size,
VM_MEMATTR_XEN);
if (error) {
- bus_release_resource(child, SYS_RES_MEMORY, *res_id, res);
+ int error = release_unpopulated_mem(child, res);
+
+ if (error != 0)
+ device_printf(dev, "failed to release resource: %d\n",
+ error);
+
return (NULL);
}
virt_addr = pmap_mapdev_attr(phys_addr, size, VM_MEMATTR_XEN);
@@ -150,7 +209,8 @@
pmap_unmapdev(virt_addr, size);
vm_phys_fictitious_unreg_range(phys_addr, phys_addr + size);
- return (bus_release_resource(child, SYS_RES_MEMORY, res_id, res));
+
+ return release_unpopulated_mem(child, res);
}
static device_method_t xenpv_methods[] = {
diff --git a/sys/x86/include/xen/xen-os.h b/sys/x86/include/xen/xen-os.h
--- a/sys/x86/include/xen/xen-os.h
+++ b/sys/x86/include/xen/xen-os.h
@@ -39,6 +39,7 @@
#ifndef __ASSEMBLY__
#include <sys/pcpu.h>
+#include <sys/rman.h>
/* If non-zero, the hypervisor has been configured to use a direct vector */
extern int xen_vector_callback_enabled;
diff --git a/sys/x86/xen/hvm.c b/sys/x86/xen/hvm.c
--- a/sys/x86/xen/hvm.c
+++ b/sys/x86/xen/hvm.c
@@ -47,6 +47,7 @@
#include <machine/cpu.h>
#include <machine/md_var.h>
#include <machine/metadata.h>
+#include <machine/pc/bios.h>
#include <machine/smp.h>
#include <x86/apicreg.h>
@@ -548,3 +549,52 @@
return (regs[0] & XEN_HVM_CPUID_IOMMU_MAPPINGS);
}
+
+int
+xen_arch_init_physmem(device_t dev, struct rman *mem)
+{
+ static struct bios_smap smap[128];
+ struct xen_memory_map memmap = {
+ .nr_entries = nitems(smap),
+ };
+ unsigned int i;
+ int error;
+
+ if (!xen_initial_domain())
+ return (0);
+
+ set_xen_guest_handle(memmap.buffer, smap);
+ error = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
+ if (error != 0)
+ return (error);
+
+ /*
+ * Fill with UNUSABLE regions, as it's always fine to use those for
+ * foreign mappings, they will never be populated.
+ */
+ for (i = 0; i < memmap.nr_entries; i++) {
+ vm_paddr_t start, end;
+
+ if (smap[i].type != SMAP_TYPE_ACPI_ERROR)
+ continue;
+
+ start = round_page(smap[i].base);
+ end = trunc_page(smap[i].base + smap[i].length) - 1;
+
+ if (start >= end)
+ continue;
+
+ if (bootverbose != 0)
+ device_printf(dev,
+ "scratch mapping region @ [%#lx, %#lx]\n",
+ start, end);
+
+ error = rman_manage_region(mem, start, end);
+ if (error != 0)
+ device_printf(dev,
+ "unable to add scratch region [%#lx, %#lx]: %d\n",
+ start, end, error);
+ }
+
+ return (0);
+}
diff --git a/sys/xen/xen-os.h b/sys/xen/xen-os.h
--- a/sys/xen/xen-os.h
+++ b/sys/xen/xen-os.h
@@ -158,6 +158,9 @@
*/
void xen_emergency_print(const char *str, size_t size);
+/* Arch-specific helper to init scratch mapping space. */
+int xen_arch_init_physmem(device_t dev, struct rman *mem);
+
#ifndef xen_mb
#define xen_mb() mb()
#endif

File Metadata

Mime Type
text/plain
Expires
Thu, Feb 13, 3:00 AM (21 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16621409
Default Alt Text
D44251.diff (5 KB)

Event Timeline