>From ae39029b82490d89c1012e0c963f28ca55313427 Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Wed, 8 Jul 2020 21:26:12 +1000 Subject: [PATCH 2/2] mach: vm_allocate_contiguous RPC now allows physical alignment/limits --- i386/include/mach/i386/machine_types.defs | 9 ++++++ include/mach/mach.defs | 35 ++++++++------------ vm/vm_user.c | 39 +++++++++++++++++++---- 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); -- 2.25.1