From 59e972f074578072502effad0ee78f2fe8d696b3 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Thu, 12 Feb 2009 12:26:08 +0000 Subject: [PATCH] let drivers allocate memory at 64k physical boundary. --- include/minix/syslib.h | 1 + include/sys/mman.h | 1 + lib/syslib/alloc_util.c | 20 ++++++++++++-------- servers/vm/alloc.c | 36 ++++++++++++++++++++++++++++-------- servers/vm/mmap.c | 4 +++- servers/vm/region.c | 10 ++++++++-- servers/vm/region.h | 1 + servers/vm/vm.h | 1 + 8 files changed, 55 insertions(+), 19 deletions(-) diff --git a/include/minix/syslib.h b/include/minix/syslib.h index 391837ea5..24f394b82 100755 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -84,6 +84,7 @@ _PROTOTYPE( int sys_sdevio, (int req, long port, endpoint_t proc_nr, _PROTOTYPE(void *alloc_contig, (size_t len, int flags, phys_bytes *phys)); #define AC_ALIGN4K 0x01 #define AC_LOWER16M 0x02 +#define AC_ALIGN64K 0x04 /* Clock functionality: get system times or (un)schedule an alarm call. */ _PROTOTYPE( int sys_times, (endpoint_t proc_nr, clock_t *user_time, diff --git a/include/sys/mman.h b/include/sys/mman.h index 1c3ef37a2..7209fc9be 100755 --- a/include/sys/mman.h +++ b/include/sys/mman.h @@ -19,6 +19,7 @@ #define MAP_PREALLOC 0x0008 /* not on-demand */ #define MAP_CONTIG 0x0010 /* contiguous in physical memory */ #define MAP_LOWER16M 0x0020 /* physically below 16MB */ +#define MAP_ALIGN64K 0x0040 /* physically aligned at 64kB */ /* mmap() error return */ #define MAP_FAILED ((void *)-1) diff --git a/lib/syslib/alloc_util.c b/lib/syslib/alloc_util.c index 269b3b43a..a2a5bd761 100644 --- a/lib/syslib/alloc_util.c +++ b/lib/syslib/alloc_util.c @@ -29,6 +29,8 @@ void *alloc_contig(size_t len, int flags, phys_bytes *phys) if(flags & AC_LOWER16M) mmapflags |= MAP_LOWER16M; + if(flags & AC_ALIGN64K) + mmapflags |= MAP_ALIGN64K; /* First try to get memory with mmap. This is gauranteed * to be page-aligned, and we can tell VM it has to be @@ -44,20 +46,22 @@ void *alloc_contig(size_t len, int flags, phys_bytes *phys) * so we can page align it ourselves. */ if(buf == (vir_bytes) MAP_FAILED) { + u32_t align = 0; if(errno != (_SIGN ENXIO)) { return NULL; } -#define ALIGN 4096 - if(flags & AC_ALIGN4K) { - if(len + ALIGN < len) - return NULL; - len += ALIGN; - } + if(flags & AC_ALIGN4K) + align = 4*1024; + if(flags & AC_ALIGN64K) + align = 64*1024; + if(len + align < len) + return NULL; + len += align; if(!(buf = (vir_bytes) malloc(len))) { return NULL; } - if(flags & AC_ALIGN4K) - buf += ALIGN - (buf % ALIGN); + if(align) + buf += align - (buf % align); } /* Get physical address. */ diff --git a/servers/vm/alloc.c b/servers/vm/alloc.c index e28f4574d..7ab0fd488 100644 --- a/servers/vm/alloc.c +++ b/servers/vm/alloc.c @@ -206,17 +206,19 @@ PUBLIC phys_clicks alloc_mem_f(phys_clicks clicks, u32_t memflags) * needed for FORK or EXEC. */ register struct hole *hp, *prev_ptr; - phys_clicks old_base; + phys_clicks old_base, mem = NO_MEM, align_clicks = 0; int s; + if(memflags & PAF_ALIGN64K) { + align_clicks = (64 * 1024) / CLICK_SIZE; + clicks += align_clicks; + } + if(vm_paged) { vm_assert(CLICK_SIZE == VM_PAGE_SIZE); - return alloc_pages(clicks, memflags); - } - + mem = alloc_pages(clicks, memflags); + } else { CHECKHOLES; - - { prev_ptr = NIL_HOLE; hp = hole_head; while (hp != NIL_HOLE) { @@ -239,15 +241,33 @@ CHECKHOLES; /* Return the start address of the acquired block. */ CHECKHOLES; - return(old_base); + mem = old_base; + break; } prev_ptr = hp; hp = hp->h_next; } } + + if(mem == NO_MEM) + return mem; + CHECKHOLES; - return(NO_MEM); + + if(align_clicks) { + phys_clicks o; + o = mem % align_clicks; + if(o > 0) { + phys_clicks e; + e = align_clicks - o; + FREE_MEM(mem, e); + mem += e; + } + } +CHECKHOLES; + + return mem; } /*===========================================================================* diff --git a/servers/vm/mmap.c b/servers/vm/mmap.c index f519f9538..1bbbf699e 100644 --- a/servers/vm/mmap.c +++ b/servers/vm/mmap.c @@ -57,6 +57,7 @@ PUBLIC int do_mmap(message *m) if(m->VMM_FD == -1 || (m->VMM_FLAGS & MAP_ANON)) { int s; vir_bytes v; + u32_t vrflags = VR_ANON | VR_WRITABLE; size_t len = (vir_bytes) m->VMM_LEN; if(m->VMM_FD != -1) { @@ -65,13 +66,14 @@ PUBLIC int do_mmap(message *m) if(m->VMM_FLAGS & MAP_CONTIG) mfflags |= MF_CONTIG; if(m->VMM_FLAGS & MAP_PREALLOC) mfflags |= MF_PREALLOC; + if(m->VMM_FLAGS & MAP_ALIGN64K) vrflags |= VR_PHYS64K; if(len % VM_PAGE_SIZE) len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE); if(!(vr = map_page_region(vmp, arch_vir2map(vmp, vmp->vm_stacktop), VM_DATATOP, len, MAP_NONE, - VR_ANON | VR_WRITABLE, mfflags))) { + vrflags, mfflags))) { return ENOMEM; } } else { diff --git a/servers/vm/region.c b/servers/vm/region.c index 358996db8..0784b9db8 100644 --- a/servers/vm/region.c +++ b/servers/vm/region.c @@ -432,7 +432,10 @@ struct phys_region *physhint; /* Memory for new physical block. */ clicks = CLICKSPERPAGE * length / VM_PAGE_SIZE; if(what_mem == MAP_NONE) { - if((mem_clicks = ALLOC_MEM(clicks, PAF_CLEAR)) == NO_MEM) { + u32_t af = PAF_CLEAR; + if(region->flags & VR_PHYS64K) + af |= PAF_ALIGN64K; + if((mem_clicks = ALLOC_MEM(clicks, af)) == NO_MEM) { SLABFREE(newpb); SLABFREE(newphysr); return ENOMEM; @@ -499,6 +502,7 @@ struct phys_region *ph; int r; phys_bytes newmem, newmem_cl, clicks; struct phys_block *newpb; + u32_t af = 0; SANITYCHECK(SCL_FUNCTIONS); @@ -514,7 +518,9 @@ struct phys_region *ph; clicks = CLICKSPERPAGE * ph->ph->length / VM_PAGE_SIZE; vm_assert(CLICK2ABS(clicks) == ph->ph->length); - if((newmem_cl = ALLOC_MEM(clicks, 0)) == NO_MEM) { + if(region->flags & VR_PHYS64K) + af |= PAF_ALIGN64K; + if((newmem_cl = ALLOC_MEM(clicks, af)) == NO_MEM) { SLABFREE(newpb); return ENOMEM; } diff --git a/servers/vm/region.h b/servers/vm/region.h index a134ef73c..3b884a87c 100644 --- a/servers/vm/region.h +++ b/servers/vm/region.h @@ -29,6 +29,7 @@ struct vir_region { /* Mapping flags: */ #define VR_WRITABLE 0x01 /* Process may write here. */ #define VR_NOPF 0x02 /* May not generate page faults. */ +#define VR_PHYS64K 0x04 /* Physical memory must be 64k aligned. */ /* Mapping type: */ #define VR_ANON 0x10 /* Memory to be cleared and allocated */ diff --git a/servers/vm/vm.h b/servers/vm/vm.h index b305817b8..0f4040db7 100644 --- a/servers/vm/vm.h +++ b/servers/vm/vm.h @@ -4,6 +4,7 @@ /* Memory flags to pt_allocmap() and alloc_mem(). */ #define PAF_CLEAR 0x01 /* Clear physical memory. */ #define PAF_CONTIG 0x02 /* Physically contiguous. */ +#define PAF_ALIGN64K 0x04 /* Aligned to 64k boundary. */ /* special value for v in pt_allocmap */ #define AM_AUTO ((u32_t) -1)