From 95b7b65c890bda4929e4ff74014815bfe4503722 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Wed, 19 Aug 2009 14:44:36 +0300 Subject: [PATCH] Pager virtual address pool bookkeeping added for all pager virtual addresses Previously virt_to_phys/phys_to_virt macros were used such that they did a blind offset translation for creating a pager internal virtual address for user mappings. This is now changed such that a properly bookkeeped virtual address pool is used which will avoid any clashes on the virtual space. --- src/generic/container.c | 2 +- tasks/libl4/include/l4lib/arch-arm/syslib.h | 11 +++-- tasks/mm0/TODO | 13 ++++++ tasks/mm0/include/lib/addr.h | 3 ++ tasks/mm0/include/linker.lds | 14 +++--- tasks/mm0/include/memory.h | 4 ++ tasks/mm0/src/bootdesc.c | 13 ++---- tasks/mm0/src/init.c | 6 +-- tasks/mm0/src/lib/addr.c | 15 +++++++ tasks/mm0/src/memory.c | 50 ++++++++++++--------- tasks/mm0/src/pagers.c | 9 +++- 11 files changed, 94 insertions(+), 46 deletions(-) create mode 100644 tasks/mm0/TODO diff --git a/src/generic/container.c b/src/generic/container.c index 8f0ee0a..863783b 100644 --- a/src/generic/container.c +++ b/src/generic/container.c @@ -29,7 +29,7 @@ struct container_info cinfo[] = { [0] = { .pager_lma = __pfn(CONFIG_CONT0_PAGER_START), .pager_vma = __pfn(0xE0000000), - .pager_size = __pfn(0xa0000), + .pager_size = __pfn(0xa2000), .ncaps = 14, .caps = { [0] = { diff --git a/tasks/libl4/include/l4lib/arch-arm/syslib.h b/tasks/libl4/include/l4lib/arch-arm/syslib.h index 3645d0a..cfba52a 100644 --- a/tasks/libl4/include/l4lib/arch-arm/syslib.h +++ b/tasks/libl4/include/l4lib/arch-arm/syslib.h @@ -263,14 +263,18 @@ static inline int l4_ipc_return(int retval) return l4_ipc(sender, L4_NILTHREAD, 0); } +void *l4_new_virtual(int npages); +void *l4_del_virtual(void *virt, int npages); + /* A helper that translates and maps a physical address to virtual */ static inline void *l4_map_helper(void *phys, int npages) { struct task_ids ids; + void *virt = l4_new_virtual(npages); l4_getid(&ids); - l4_map(phys, phys_to_virt(phys), npages, MAP_USR_RW_FLAGS, ids.tid); - return phys_to_virt(phys); + l4_map(phys, virt, npages, MAP_USR_RW_FLAGS, ids.tid); + return virt; } @@ -281,7 +285,8 @@ static inline void *l4_unmap_helper(void *virt, int npages) l4_getid(&ids); l4_unmap(virt, npages, ids.tid); - return virt_to_phys(virt); + l4_del_virtual(virt, npages); + return 0; } #endif /* __L4LIB_SYSLIB_H__ */ diff --git a/tasks/mm0/TODO b/tasks/mm0/TODO new file mode 100644 index 0000000..cf931ea --- /dev/null +++ b/tasks/mm0/TODO @@ -0,0 +1,13 @@ +MM0 TODO List: + +1.) Bootmem needs to be freed. +2.) Virtual memory regions available as capabilities need to be dynamically + allocated to various purposes, i.e. task region, shared memory region, + utcb region, etc. by traversing each region and matching to purposes. +3.) virt_to_phys()/phys_to_virt() uses the fixed offset of INITTASK_OFFSET, this + either needs to be discovered at run-time or specified at config-time. +4.) pager_new_address()/pager_delete_address() needs to use a region inside + pager start/end regions, and virt_to_phys()/phys_to_virt() should not clash + with those regions. +5.) read_file_pages()/write_file_pages() needs to be tested and improved in + terms of syscalls to microkernel. diff --git a/tasks/mm0/include/lib/addr.h b/tasks/mm0/include/lib/addr.h index c58bc49..774a1ce 100644 --- a/tasks/mm0/include/lib/addr.h +++ b/tasks/mm0/include/lib/addr.h @@ -15,6 +15,9 @@ struct address_pool { unsigned long end; }; +int address_pool_init_with_idpool(struct address_pool *pool, + struct id_pool *idpool, + unsigned long start, unsigned long end); int address_pool_init(struct address_pool *pool, unsigned long start, unsigned long end); void *address_new(struct address_pool *pool, int npages); diff --git a/tasks/mm0/include/linker.lds b/tasks/mm0/include/linker.lds index c114b26..0d5ba22 100644 --- a/tasks/mm0/include/linker.lds +++ b/tasks/mm0/include/linker.lds @@ -17,7 +17,7 @@ virtual_base = 0xE0000000; INCLUDE "include/physical_base.lds" /* physical_base = 0x228000; */ -offset = virtual_base - physical_base; +pager_offset = virtual_base - physical_base; ENTRY(_start) @@ -25,20 +25,20 @@ SECTIONS { . = virtual_base; _start_text = .; - .text : AT (ADDR(.text) - offset) { crt0.o(.text) *(.text) } + .text : AT (ADDR(.text) - pager_offset) { crt0.o(.text) *(.text) } /* rodata is needed else your strings will link at physical! */ - .rodata : AT (ADDR(.rodata) - offset) { *(.rodata) } - .rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) } - .data : AT (ADDR(.data) - offset) + .rodata : AT (ADDR(.rodata) - pager_offset) { *(.rodata) } + .rodata1 : AT (ADDR(.rodata1) - pager_offset) { *(.rodata1) } + .data : AT (ADDR(.data) - pager_offset) { *(.data) } - .bss : AT (ADDR(.bss) - offset) { *(.bss) } + .bss : AT (ADDR(.bss) - pager_offset) { *(.bss) } . = ALIGN(4K); . += 0x2000; /* BSS doesnt increment link counter??? */ /* Below part is to be discarded after boot */ _start_init = .; - .init : AT (ADDR(.init) - offset) + .init : AT (ADDR(.init) - pager_offset) { *(.init.data) *(.init.bootmem) diff --git a/tasks/mm0/include/memory.h b/tasks/mm0/include/memory.h index 281c47a..1db0198 100644 --- a/tasks/mm0/include/memory.h +++ b/tasks/mm0/include/memory.h @@ -25,4 +25,8 @@ void *pager_map_file_range(struct vm_file *f, unsigned long byte_offset, unsigned long size); void *pager_validate_map_user_range2(struct tcb *user, void *userptr, unsigned long size, unsigned int vm_flags); + +void *l4_new_virtual(int npages); +void *l4_del_virtual(void *virt, int npages); + #endif /* __MEMORY_H__ */ diff --git a/tasks/mm0/src/bootdesc.c b/tasks/mm0/src/bootdesc.c index bae6118..542f2eb 100644 --- a/tasks/mm0/src/bootdesc.c +++ b/tasks/mm0/src/bootdesc.c @@ -10,6 +10,7 @@ #include extern unsigned long _end[]; +extern unsigned long pager_offset; void read_bootdesc(struct initdata *initdata) { @@ -21,15 +22,9 @@ void read_bootdesc(struct initdata *initdata) */ bootdesc = (struct bootdesc *)_end; - /* Check if bootdesc spans across pages, and how many */ - npages = __pfn((((unsigned long)bootdesc + - bootdesc->desc_size) - & ~PAGE_MASK) - - ((unsigned long)bootdesc & ~PAGE_MASK)); - - if (npages > 0) - l4_map_helper(virt_to_phys((void *)page_align_up(_end)), - PAGE_SIZE * npages); + /* Check if bootdesc is on an unmapped page */ + if (is_page_aligned(bootdesc)) + l4_map_helper(bootdesc - pager_offset, PAGE_SIZE); /* Allocate bootdesc sized structure */ initdata->bootdesc = alloc_bootmem(bootdesc->desc_size, 0); diff --git a/tasks/mm0/src/init.c b/tasks/mm0/src/init.c index f433468..d3521b7 100644 --- a/tasks/mm0/src/init.c +++ b/tasks/mm0/src/init.c @@ -240,15 +240,15 @@ void init_mm(struct initdata *initdata) BUG(); } - /* For supplying contiguous virtual addresses to pager */ - pager_address_pool_init(); - // printf("%s: Initialised utcb address pool.\n", __TASKNAME__); } void init_pager(void) { + /* For supplying contiguous virtual addresses to pager */ + pager_address_pool_init(); + read_kernel_capabilities(&initdata); read_bootdesc(&initdata); diff --git a/tasks/mm0/src/lib/addr.c b/tasks/mm0/src/lib/addr.c index e610fc6..d7c7733 100644 --- a/tasks/mm0/src/lib/addr.c +++ b/tasks/mm0/src/lib/addr.c @@ -11,6 +11,21 @@ #include #include +/* + * Initializes an address pool, but uses an already + * allocated id pool for it. + */ +int address_pool_init_with_idpool(struct address_pool *pool, + struct id_pool *idpool, + unsigned long start, unsigned long end) +{ + pool->idpool = idpool; + pool->start = start; + pool->end = end; + + return 0; +} + int address_pool_init(struct address_pool *pool, unsigned long start, unsigned long end) { if ((pool->idpool = id_pool_new_init(__pfn(end - start))) < 0) diff --git a/tasks/mm0/src/memory.c b/tasks/mm0/src/memory.c index 0d4ae77..02e284e 100644 --- a/tasks/mm0/src/memory.c +++ b/tasks/mm0/src/memory.c @@ -20,14 +20,39 @@ struct address_pool pager_vaddr_pool; -void *phys_to_virt(void *addr) +/* Bitmap size to represent an address pool of 256 MB. */ +#define ADDRESS_POOL_256MB 2048 + +/* Same as a regular id pool except that its bitmap size is fixed */ +static struct pager_virtual_address_id_pool { + int nwords; + int bitlimit; + u32 bitmap[ADDRESS_POOL_256MB]; +} pager_virtual_address_id_pool = { + .nwords = ADDRESS_POOL_256MB, + .bitlimit = ADDRESS_POOL_256MB * 32, +}; + +int pager_address_pool_init(void) { - return addr + INITTASK_OFFSET; + /* Initialise id pool for pager virtual address allocation */ + address_pool_init_with_idpool(&pager_vaddr_pool, + (struct id_pool *) + &pager_virtual_address_id_pool, + (unsigned long)0xD0000000, + (unsigned long)0xE0000000); + return 0; } -void *virt_to_phys(void *addr) +void *l4_new_virtual(int npages) { - return addr - INITTASK_OFFSET; + return pager_new_address(npages); +} + +void *l4_del_virtual(void *virt, int npages) +{ + pager_delete_address(virt, npages); + return 0; } /* Maps a page from a vm_file to the pager's address space */ @@ -51,20 +76,6 @@ void pager_unmap_page(void *addr) l4_unmap_helper(addr, 1); } -int pager_address_pool_init(void) -{ - int err; - - /* Initialise the global shm virtual address pool */ - if ((err = address_pool_init(&pager_vaddr_pool, - (unsigned long)0xD0000000, - (unsigned long)0xE0000000)) < 0) { - printf("Pager virtual address pool initialisation failed.\n"); - return err; - } - return 0; -} - void *pager_new_address(int npages) { return address_new(&pager_vaddr_pool, npages); @@ -110,9 +121,6 @@ void pager_unmap_pages(void *addr, unsigned long npages) /* Unmap so many pages */ l4_unmap_helper(addr, npages); - - /* Free the address range */ - pager_delete_address(addr, npages); } /* diff --git a/tasks/mm0/src/pagers.c b/tasks/mm0/src/pagers.c index 9b88c62..4c356ca 100644 --- a/tasks/mm0/src/pagers.c +++ b/tasks/mm0/src/pagers.c @@ -86,7 +86,7 @@ int file_page_out(struct vm_object *vm_obj, unsigned long page_offset) return 0; paddr = (void *)page_to_phys(page); - vaddr = phys_to_virt(paddr); + vaddr = l4_new_virtual(1); /* Map the page to vfs task */ l4_map(paddr, vaddr, 1, MAP_USR_RW_FLAGS, VFS_TID); @@ -100,6 +100,7 @@ int file_page_out(struct vm_object *vm_obj, unsigned long page_offset) /* Unmap it from vfs */ l4_unmap(vaddr, 1, VFS_TID); + l4_del_virtual(vaddr, 1); /* Clear dirty flag */ page->flags &= ~VM_DIRTY; @@ -108,6 +109,8 @@ int file_page_out(struct vm_object *vm_obj, unsigned long page_offset) out_err: l4_unmap(vaddr, 1, VFS_TID); + l4_del_virtual(vaddr, 1); + return err; } @@ -130,7 +133,7 @@ struct page *file_page_in(struct vm_object *vm_obj, unsigned long page_offset) if (!(page = find_page(vm_obj, page_offset))) { /* Allocate a new page */ paddr = alloc_page(1); - vaddr = phys_to_virt(paddr); + vaddr = l4_new_virtual(1); page = phys_to_page(paddr); /* Map the page to vfs task */ @@ -143,6 +146,7 @@ struct page *file_page_in(struct vm_object *vm_obj, unsigned long page_offset) /* Unmap it from vfs */ l4_unmap(vaddr, 1, VFS_TID); + l4_del_virtual(vaddr, 1); /* Update vm object details */ vm_obj->npages++; @@ -163,6 +167,7 @@ struct page *file_page_in(struct vm_object *vm_obj, unsigned long page_offset) out_err: l4_unmap(vaddr, 1, VFS_TID); + l4_del_virtual(vaddr, 1); free_page(paddr); return PTR_ERR(err); }