mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
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:
@@ -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] = {
|
||||
|
||||
@@ -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
13
tasks/mm0/TODO
Normal 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.
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user