summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2020-07-08 21:26:12 +1000
committerDamien Zammit <damien@zamaudio.com>2020-07-09 21:04:31 +1000
commitae39029b82490d89c1012e0c963f28ca55313427 (patch)
treef2f1058d3be9f10602e97a898cc29115dd0ecec8
parentadfad36aab3bb1f9a626fa5ba22d12f286e39fd6 (diff)
mach: vm_allocate_contiguous RPC now allows physical alignment/limitsirq-as-device
-rwxr-xr-xi386/include/mach/i386/machine_types.defs9
-rw-r--r--include/mach/mach.defs35
-rw-r--r--vm/vm_user.c39
3 files changed, 54 insertions, 29 deletions
diff --git a/i386/include/mach/i386/machine_types.defs b/i386/include/mach/i386/machine_types.defs
index 6ff93dbd..f3fbc314 100755
--- a/i386/include/mach/i386/machine_types.defs
+++ b/i386/include/mach/i386/machine_types.defs
@@ -58,4 +58,13 @@ type natural_t = uint32_t;
*/
type integer_t = int32_t;
+/*
+ * Physical address size
+ */
+#ifdef PAE
+type phys_addr_t = uint64_t;
+#else
+type phys_addr_t = uint32_t;
+#endif
+
#endif /* _MACHINE_MACHINE_TYPES_DEFS_ */
diff --git a/include/mach/mach.defs b/include/mach/mach.defs
index 77cc7d49..a024cf75 100644
--- a/include/mach/mach.defs
+++ b/include/mach/mach.defs
@@ -723,34 +723,25 @@ skip; /* old host_fpa_counters_reset */
* This routine is created for allocating DMA buffers.
* We are going to get a contiguous physical memory
* and its physical address in addition to the virtual address.
+ * We can specify physical memory range limits and alignment.
+ * NB:
+ * pmax is defined as the byte after the maximum address,
+ * eg 0x100000000 for 4GiB limit.
*/
-
- /* XXX
- This RPC lacks a few additional constraints like boundaries, alignment
-and maybe phase. We may not use them now, but they're important for
-portability (e.g. if GNU Mach supports PAE, drivers that can't use
-physical memory beyond the 4 GiB limit must be able to express it).
-
-> What do you mean by "phase"?
-
-Offset from the alignment. But I don't think it's useful at all in this
-case. Minimum and maximum addresses and alignment should do. Maybe
-boundary crossing but usually, specifying the right alignment and size
-is enough.
-
-For upstream
-inclusion, we need to do it properly: the RPC should return a special
-memory object (similar to device_map() ), which can then be mapped into
-the process address space with vm_map() like any other memory object.
-
-phys_address_t?
+/* XXX
+ * Future work: the RPC should return a special
+ * memory object (similar to device_map() ), which can then be mapped into
+ * the process address space with vm_map() like any other memory object.
*/
routine vm_allocate_contiguous(
host_priv : host_priv_t;
target_task : vm_task_t;
out vaddr : vm_address_t;
- out paddr : vm_address_t;
- size : vm_size_t);
+ out paddr : phys_addr_t;
+ size : vm_size_t;
+ pmin : phys_addr_t;
+ pmax : phys_addr_t;
+ palign : phys_addr_t);
/*
* There is no more room in this interface for additional calls.
diff --git a/vm/vm_user.c b/vm/vm_user.c
index 1789dbfa..09a35ab2 100644
--- a/vm/vm_user.c
+++ b/vm/vm_user.c
@@ -532,17 +532,24 @@ kern_return_t vm_msync(
return vm_map_msync(map, (vm_offset_t) address, size, sync_flags);
}
-kern_return_t vm_allocate_contiguous(host_priv, map, result_vaddr, result_paddr, size)
- host_t host_priv;
- vm_map_t map;
- vm_address_t *result_vaddr;
- vm_address_t *result_paddr;
- vm_size_t size;
+/* TODO: respect physical alignment (palign)
+ * and minimum physical address (pmin)
+ */
+kern_return_t vm_allocate_contiguous(
+ host_t host_priv,
+ vm_map_t map,
+ vm_address_t *result_vaddr,
+ phys_addr_t *result_paddr,
+ vm_size_t size,
+ phys_addr_t pmin,
+ phys_addr_t pmax,
+ phys_addr_t palign)
{
vm_size_t alloc_size;
unsigned int npages;
unsigned int i;
unsigned int order;
+ unsigned int selector;
vm_page_t pages;
vm_object_t object;
kern_return_t kr;
@@ -554,6 +561,24 @@ kern_return_t vm_allocate_contiguous(host_priv, map, result_vaddr, result_paddr,
if (map == VM_MAP_NULL)
return KERN_INVALID_TASK;
+ /* FIXME */
+ if (pmin != 0)
+ return KERN_INVALID_ARGUMENT;
+
+ /* FIXME */
+ if (palign == 0)
+ palign = PAGE_SIZE;
+
+ selector = VM_PAGE_SEL_DMA;
+ if (pmax > VM_PAGE_DMA_LIMIT)
+#ifdef VM_PAGE_DMA32_LIMIT
+ selector = VM_PAGE_SEL_DMA32;
+ if (pmax > VM_PAGE_DMA32_LIMIT)
+#endif
+ selector = VM_PAGE_SEL_DIRECTMAP;
+ if (pmax > VM_PAGE_DIRECTMAP_LIMIT)
+ selector = VM_PAGE_SEL_HIGHMEM;
+
size = vm_page_round(size);
if (size == 0)
@@ -573,7 +598,7 @@ kern_return_t vm_allocate_contiguous(host_priv, map, result_vaddr, result_paddr,
alloc_size = (1 << (order + PAGE_SHIFT));
npages = vm_page_atop(alloc_size);
- pages = vm_page_grab_contig(alloc_size, VM_PAGE_SEL_DIRECTMAP);
+ pages = vm_page_grab_contig(alloc_size, selector);
if (pages == NULL) {
vm_object_deallocate(object);