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.
This commit is contained in:
Bahadir Balban
2009-08-19 14:44:36 +03:00
parent d351d6846a
commit 95b7b65c89
11 changed files with 94 additions and 46 deletions

View File

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

View File

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

13
tasks/mm0/TODO Normal file
View File

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

View File

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

View File

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

View File

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

View File

@@ -10,6 +10,7 @@
#include <l4lib/arch/syslib.h>
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);

View File

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

View File

@@ -11,6 +11,21 @@
#include <lib/addr.h>
#include <stdio.h>
/*
* 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)

View File

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

View File

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