let drivers allocate memory at 64k physical boundary.

This commit is contained in:
Ben Gras 2009-02-12 12:26:08 +00:00
parent 6ac0338584
commit 59e972f074
8 changed files with 55 additions and 19 deletions

View file

@ -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,

View file

@ -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)

View file

@ -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. */

View file

@ -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;
}
/*===========================================================================*

View file

@ -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 {

View file

@ -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;
}

View file

@ -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 */

View file

@ -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)