From 7f1ea739ed3d392d57c6ed3d2b84619a2f5c1009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Almudena=20Garc=C3=ADa?= Date: Sun, 19 Jul 2020 23:56:32 +0200 Subject: [PATCH 3/7] Add kmem_alloc_aligned_table This function allows to map a table in a memory page, using its physical address,aligning the start of the page with the start of the table *vm/vm_kern.c (kmem_alloc_aligned_table): New function. Returns a reference for the virtual address of the table *vm/vm_kern.h (kmem_alloc_aligned_table): New prototype --- vm/vm_kern.c | 33 +++++++++++++++++++++++++++++++++ vm/vm_kern.h | 2 ++ 2 files changed, 35 insertions(+) diff --git a/vm/vm_kern.c b/vm/vm_kern.c index 2e333ee1..3960df46 100644 --- a/vm/vm_kern.c +++ b/vm/vm_kern.c @@ -635,6 +635,39 @@ retry: return KERN_SUCCESS; } +/* kmem_map_aligned_table: map a table or structure in a virtual memory page + * Align the table initial address with the page initial address + * + * Parameters: + * phys_address: physical address, the start address of the table + * size: size of the table + * mode: access mode. VM_PROT_READ for read, VM_PROT_WRITE for write + * + * Returns a reference to the virtual address if success, NULL if failure + */ + +void* +kmem_map_aligned_table (unsigned long phys_address, unsigned long size, int mode) +{ + vm_offset_t virt_addr; + kern_return_t ret; + uintptr_t into_page = phys_address % PAGE_SIZE; + uintptr_t nearest_page = (uintptr_t)trunc_page(phys_address); + + size += into_page; + + ret = kmem_alloc_wired(kernel_map, &virt_addr, round_page (size)); + + if (ret != KERN_SUCCESS) + return NULL; + + (void) pmap_map_bd (virt_addr, nearest_page, nearest_page + round_page (size), mode); + + /* XXX remember mapping somewhere so we can free it? */ + + return (void *) (virt_addr + into_page); +} + /* * kmem_alloc_pageable: * diff --git a/vm/vm_kern.h b/vm/vm_kern.h index 0cdb19db..46a1a274 100644 --- a/vm/vm_kern.h +++ b/vm/vm_kern.h @@ -55,6 +55,8 @@ extern kern_return_t kmem_alloc_pageable(vm_map_t, vm_offset_t *, extern kern_return_t kmem_valloc(vm_map_t, vm_offset_t *, vm_size_t); extern kern_return_t kmem_alloc_wired(vm_map_t, vm_offset_t *, vm_size_t); extern kern_return_t kmem_alloc_aligned(vm_map_t, vm_offset_t *, vm_size_t); +extern void* kmem_map_aligned_table (unsigned long phys_address, unsigned long size, int mode); + extern void kmem_free(vm_map_t, vm_offset_t, vm_size_t); extern void kmem_submap(vm_map_t, vm_map_t, vm_offset_t *, -- 2.27.0