mirror of
https://github.com/drasko/codezero.git
synced 2026-04-03 02:29:06 +02:00
Moved all pager page-mapping routines to memory.c
Added a new virtual address pool for contiguous virtual addresses for the pager. This will help in mapping multi-page user buffers and files.
This commit is contained in:
@@ -19,6 +19,8 @@ int file_open(struct tcb *opener, int fd);
|
|||||||
|
|
||||||
struct vm_file *do_open2(struct tcb *task, int fd, unsigned long vnum, unsigned long length);
|
struct vm_file *do_open2(struct tcb *task, int fd, unsigned long vnum, unsigned long length);
|
||||||
int flush_file_pages(struct vm_file *f);
|
int flush_file_pages(struct vm_file *f);
|
||||||
|
int read_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
|
||||||
|
unsigned long pfn_end);
|
||||||
|
|
||||||
struct vfs_file_data {
|
struct vfs_file_data {
|
||||||
unsigned long vnum;
|
unsigned long vnum;
|
||||||
|
|||||||
@@ -21,4 +21,12 @@ void init_mm_descriptors(struct page_bitmap *page_map,
|
|||||||
struct bootdesc *bootdesc, struct membank *membank);
|
struct bootdesc *bootdesc, struct membank *membank);
|
||||||
void init_physmem(struct initdata *initdata, struct membank *membank);
|
void init_physmem(struct initdata *initdata, struct membank *membank);
|
||||||
|
|
||||||
|
int pager_address_pool_init(void);
|
||||||
|
void *pager_new_address(int npages);
|
||||||
|
int pager_delete_address(void *virt_addr, int npages);
|
||||||
|
void *pager_map_pages(struct vm_file *f, unsigned long page_offset, unsigned long npages);
|
||||||
|
void pager_unmap_pages(void *addr, unsigned long npages);
|
||||||
|
void *pager_map_page(struct vm_file *f, unsigned long page_offset);
|
||||||
|
void pager_unmap_page(void *addr);
|
||||||
|
|
||||||
#endif /* __MEMORY_H__ */
|
#endif /* __MEMORY_H__ */
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <user.h>
|
#include <user.h>
|
||||||
#include <test.h>
|
#include <test.h>
|
||||||
|
|
||||||
|
|
||||||
/* Copy from one page's buffer into another page */
|
/* Copy from one page's buffer into another page */
|
||||||
int page_copy(struct page *dst, struct page *src,
|
int page_copy(struct page *dst, struct page *src,
|
||||||
unsigned long dst_offset, unsigned long src_offset,
|
unsigned long dst_offset, unsigned long src_offset,
|
||||||
@@ -308,27 +309,6 @@ int read_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Maps a page from a vm_file to the pager's address space */
|
|
||||||
void *pager_map_page(struct vm_file *f, unsigned long page_offset)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
struct page *p;
|
|
||||||
|
|
||||||
if ((err = read_file_pages(f, page_offset, page_offset + 1)) < 0)
|
|
||||||
return PTR_ERR(err);
|
|
||||||
|
|
||||||
if ((p = find_page(&f->vm_obj, page_offset)))
|
|
||||||
return (void *)l4_map_helper((void *)page_to_phys(p), 1);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmaps a page's virtual address from the pager's address space */
|
|
||||||
void pager_unmap_page(void *addr)
|
|
||||||
{
|
|
||||||
l4_unmap_helper(addr, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int vfs_write(unsigned long vnum, unsigned long file_offset,
|
int vfs_write(unsigned long vnum, unsigned long file_offset,
|
||||||
unsigned long npages, void *pagebuf)
|
unsigned long npages, void *pagebuf)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -174,6 +174,10 @@ void init_mm(struct initdata *initdata)
|
|||||||
printf("UTCB initialisation failed.\n");
|
printf("UTCB initialisation failed.\n");
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For supplying contiguous virtual addresses to pager */
|
||||||
|
pager_address_pool_init();
|
||||||
|
|
||||||
// printf("%s: Initialised utcb address pool.\n", __TASKNAME__);
|
// printf("%s: Initialised utcb address pool.\n", __TASKNAME__);
|
||||||
|
|
||||||
/* Give the kernel some memory to use for its allocators */
|
/* Give the kernel some memory to use for its allocators */
|
||||||
|
|||||||
@@ -24,6 +24,13 @@ int elf_probe(struct elf_header *header)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void *pager_map_file_offset(struct vm_file *f, unsigned long f_offset)
|
||||||
|
{
|
||||||
|
void *page = pager_map_page(f, __pfn(f_offset));
|
||||||
|
|
||||||
|
return (void *)((unsigned long)page | (PAGE_MASK & f_offset));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loading an ELF file:
|
* Loading an ELF file:
|
||||||
*
|
*
|
||||||
@@ -59,8 +66,14 @@ int elf_parse_executable(struct tcb *task, struct vm_file *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the section header table */
|
/* Get the section header table */
|
||||||
sect_header = (struct elf_section_header *)
|
if (__pfn(elf_header->e_shoff) > 0)
|
||||||
((void *)elf_header + elf_header->e_shoff);
|
sect_header = pager_map_file_offset(file, elf_header->e_shoff);
|
||||||
|
else
|
||||||
|
sect_header = (struct elf_section_header *)
|
||||||
|
((void *)elf_header + elf_header->e_shoff);
|
||||||
|
|
||||||
|
/* Determine if we cross a page boundary during traversal */
|
||||||
|
if (elf_header->e_shentsize * elf_header->e_shnum > TILL_PAGE_ENDS(sect_header))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sift through sections and copy their marks to tcb and efd
|
* Sift through sections and copy their marks to tcb and efd
|
||||||
|
|||||||
@@ -8,15 +8,19 @@
|
|||||||
#include <l4/macros.h>
|
#include <l4/macros.h>
|
||||||
#include <l4/config.h>
|
#include <l4/config.h>
|
||||||
#include <l4/types.h>
|
#include <l4/types.h>
|
||||||
|
#include <l4/api/errno.h>
|
||||||
#include <l4/generic/space.h>
|
#include <l4/generic/space.h>
|
||||||
#include <l4lib/arch/syslib.h>
|
#include <l4lib/arch/syslib.h>
|
||||||
#include INC_GLUE(memory.h)
|
#include INC_GLUE(memory.h)
|
||||||
#include INC_SUBARCH(mm.h)
|
#include INC_SUBARCH(mm.h)
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
#include <file.h>
|
||||||
|
|
||||||
struct membank membank[1];
|
struct membank membank[1];
|
||||||
struct page *page_array;
|
struct page *page_array;
|
||||||
|
|
||||||
|
struct address_pool pager_vaddr_pool;
|
||||||
|
|
||||||
void *phys_to_virt(void *addr)
|
void *phys_to_virt(void *addr)
|
||||||
{
|
{
|
||||||
return addr + INITTASK_OFFSET;
|
return addr + INITTASK_OFFSET;
|
||||||
@@ -90,3 +94,82 @@ void init_physmem(struct initdata *initdata, struct membank *membank)
|
|||||||
page_array = membank[0].page_array;
|
page_array = membank[0].page_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Maps a page from a vm_file to the pager's address space */
|
||||||
|
void *pager_map_page(struct vm_file *f, unsigned long page_offset)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct page *p;
|
||||||
|
|
||||||
|
if ((err = read_file_pages(f, page_offset, page_offset + 1)) < 0)
|
||||||
|
return PTR_ERR(err);
|
||||||
|
|
||||||
|
if ((p = find_page(&f->vm_obj, page_offset)))
|
||||||
|
return (void *)l4_map_helper((void *)page_to_phys(p), 1);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmaps a page's virtual address from the pager's address space */
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pager_delete_address(void *virt_addr, int npages)
|
||||||
|
{
|
||||||
|
return address_del(&pager_vaddr_pool, virt_addr, npages);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Maps a page from a vm_file to the pager's address space */
|
||||||
|
void *pager_map_pages(struct vm_file *f, unsigned long page_offset, unsigned long npages)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct page *p;
|
||||||
|
void *addr_start, *addr;
|
||||||
|
|
||||||
|
/* Get the pages */
|
||||||
|
if ((err = read_file_pages(f, page_offset, page_offset + npages)) < 0)
|
||||||
|
return PTR_ERR(err);
|
||||||
|
|
||||||
|
/* Get the address range */
|
||||||
|
if (!(addr_start = pager_new_address(npages)))
|
||||||
|
return PTR_ERR(-ENOMEM);
|
||||||
|
addr = addr_start;
|
||||||
|
|
||||||
|
/* Map pages contiguously one by one */
|
||||||
|
for (unsigned long pfn = page_offset; pfn < page_offset + npages; pfn++) {
|
||||||
|
BUG_ON(!(p = find_page(&f->vm_obj, page_offset)))
|
||||||
|
l4_map((void *)page_to_phys(p), addr, 1, MAP_USR_RW_FLAGS, self_tid());
|
||||||
|
addr += PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmaps a page's virtual address from the pager's address space */
|
||||||
|
void pager_unmap_pages(void *addr, unsigned long npages)
|
||||||
|
{
|
||||||
|
l4_unmap_helper(addr, npages);
|
||||||
|
pager_delete_address(addr, npages);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user