Pager works until end of init_physmem_secondary

This commit is contained in:
Bahadir Balban
2009-08-09 17:22:13 +03:00
parent a45b5676ab
commit 02a3f1ac91
33 changed files with 607 additions and 556 deletions

View File

@@ -6,4 +6,8 @@
#ifndef __API_CAPABILITY_H__
#define __API_CAPABILITY_H__
/* Capability syscall request types */
#define CAP_CONTROL_NCAPS 0
#define CAP_CONTROL_READ_CAPS 1
#endif /* __API_CAPABILITY_H__ */

View File

@@ -1,45 +0,0 @@
/*
* Boot time memory initialisation and memory allocator interface.
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __GENERIC_PHYSMEM_H__
#define __GENERIC_PHYSMEM_H__
#include <l4/lib/list.h>
#include INC_PLAT(offsets.h)
#include INC_GLUE(memory.h)
#define PHYSMEM_TOTAL_PAGES ((PHYS_MEM_END - PHYS_MEM_START) >> PAGE_BITS)
/* A compact memory descriptor to determine used/unused pages in the system */
struct page_bitmap {
unsigned long pfn_start;
unsigned long pfn_end;
unsigned int map[PHYSMEM_TOTAL_PAGES >> 5];
};
/* Describes a portion of physical memory. */
struct memdesc {
unsigned int start;
unsigned int end;
unsigned int free_cur;
unsigned int free_end;
unsigned int numpages;
};
#if defined(__KERNEL__)
/* Describes bitmap of used/unused state for all physical pages */
extern struct page_bitmap page_map;
extern struct memdesc physmem;
#endif
/* Sets the global page map as used/unused. Aligns input when needed. */
int set_page_map(unsigned long start, int numpages, int val);
/* Memory allocator interface */
void physmem_init(void);
void memory_init(void);
#endif /* __GENERIC_PHYSMEM_H__ */

View File

@@ -11,6 +11,7 @@
#include <l4/lib/spinlock.h>
#include <l4/generic/scheduler.h>
#include <l4/generic/resource.h>
#include <l4/generic/capability.h>
#include <l4/generic/space.h>
#include INC_GLUE(memory.h)
#include INC_GLUE(syscall.h)
@@ -98,6 +99,11 @@ struct ktcb {
/* Container */
struct container *container;
struct pager *pager;
/* Capability list */
struct cap_list *cap_list_ptr;
struct cap_list cap_list;
/* Fields for ipc rendezvous */
struct waitqueue_head wqh_recv;

View File

@@ -7,7 +7,6 @@
#ifndef __GLUE_ARM_MEMORY_H__
#define __GLUE_ARM_MEMORY_H__
#include INC_ARCH(bootdesc.h) /* Definition of last loaded svc image address */
#include INC_GLUE(memlayout.h) /* Important generic definitions */
#include INC_SUBARCH(mm.h)

View File

@@ -8,50 +8,79 @@
*/
#include <l4/api/capability.h>
#include <l4/generic/tcb.h>
#include <l4/generic/physmem.h>
#include <l4/generic/space.h>
#include <l4/generic/capability.h>
#include <l4/generic/container.h>
#include <l4/api/errno.h>
#include INC_API(syscall.h)
/* Error-checked kernel data request call */
int __sys_capability_control(unsigned int req, unsigned int flags, void *userbuf)
int task_read_capabilities(void *userbuf)
{
int err = 0;
#if 0
int copy_size, copy_offset = 0;
struct capability *cap;
int err;
/*
* Currently only pagers can
* read their own capabilities
*/
if (current != current->pager->tcb)
return -EPERM;
/* Determine size of pager capabilities */
copy_size = current->cap_list_ptr->ncaps * sizeof(*cap);
/* Validate user buffer for this copy size */
if ((err = check_access((unsigned long)userbuf, copy_size,
MAP_USR_RW_FLAGS, 1)) < 0)
return err;
/* Copy capabilities from list to buffer */
list_foreach_struct(cap,
&current->cap_list_ptr->caps,
list) {
memcpy(userbuf + copy_offset, cap, sizeof(*cap));
copy_offset += sizeof(*cap);
}
return 0;
}
/*
* Read, manipulate capabilities. Currently only capability read support.
*/
int sys_capability_control(unsigned int req, unsigned int flags, void *userbuf)
{
int err;
switch(req) {
case KDATA_PAGE_MAP:
// printk("Handling KDATA_PAGE_MAP request.\n");
if (check_access(vaddr, sizeof(page_map), MAP_USR_RW_FLAGS, 1) < 0)
return -EINVAL;
memcpy(dest, &page_map, sizeof(page_map));
/* Return number of capabilities the thread has */
case CAP_CONTROL_NCAPS:
if (current != current->pager->tcb)
return -EPERM;
if ((err = check_access((unsigned long)userbuf, sizeof(int),
MAP_USR_RW_FLAGS, 1)) < 0)
return err;
/* Copy ncaps value */
*((int *)userbuf) = current->cap_list_ptr->ncaps;
break;
case KDATA_BOOTDESC:
// printk("Handling KDATA_BOOTDESC request.\n");
if (check_access(vaddr, bootdesc->desc_size, MAP_USR_RW_FLAGS, 1) < 0)
return -EINVAL;
memcpy(dest, bootdesc, bootdesc->desc_size);
break;
case KDATA_BOOTDESC_SIZE:
// printk("Handling KDATA_BOOTDESC_SIZE request.\n");
if (check_access(vaddr, sizeof(unsigned int), MAP_USR_RW_FLAGS, 1) < 0)
return -EINVAL;
*(unsigned int *)dest = bootdesc->desc_size;
/* Return all capabilities as an array of capabilities */
case CAP_CONTROL_READ_CAPS:
err = task_read_capabilities(userbuf);
break;
default:
printk("Unsupported kernel data request.\n");
err = -1;
/* Invalid request id */
return -EINVAL;
}
#endif
return err;
return 0;
}
int sys_capability_control(unsigned int req, unsigned int flags, void *userbuf)
{
return __sys_capability_control(req, flags, userbuf);
}

View File

@@ -4,7 +4,7 @@
Import('env')
# The set of source files associated with this SConscript file.
src_local = ['head.S', 'vectors.S', 'syscall.S', 'exception.c', 'bootdesc.c']
src_local = ['head.S', 'vectors.S', 'syscall.S', 'exception.c']
obj = env.Object(src_local)
Return('obj')

View File

@@ -1,46 +0,0 @@
/*
* Reading of bootdesc forged at build time.
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <l4/lib/printk.h>
#include <l4/lib/string.h>
#include <l4/generic/space.h>
#include INC_ARCH(linker.h)
#include INC_ARCH(bootdesc.h)
#include INC_GLUE(memory.h)
#include INC_PLAT(printascii.h)
#include INC_SUBARCH(mm.h)
struct bootdesc *bootdesc;
#if 0
void copy_bootdesc()
{
struct bootdesc *new = kzalloc(bootdesc->desc_size);
memcpy(new, bootdesc, bootdesc->desc_size);
remove_mapping((unsigned long)bootdesc);
bootdesc = new;
}
void read_bootdesc(void)
{
/*
* End of the kernel image is where bootdesc resides. Note this is
* not added to the page_map because it's meant to be discarded.
*/
// add_mapping(virt_to_phys(_end), (unsigned long)_end, PAGE_SIZE,
// MAP_USR_DEFAULT_FLAGS);
/* Get original bootdesc */
bootdesc = (struct bootdesc *)_end;
/* Determine end of physical memory used by loaded images. */
for (int i = 0; i < bootdesc->total_images; i++)
if (bootdesc->images[i].phys_end > __svc_images_end)
__svc_images_end = bootdesc->images[i].phys_end;
}
#endif

View File

@@ -4,7 +4,7 @@
Import('env')
# The set of source files associated with this SConscript file.
src_local = ['physmem.c', 'irq.c', 'scheduler.c', 'time.c', 'tcb.c', 'space.c', 'bootm.c', 'resource.c', 'container.c', 'capability.c']
src_local = ['irq.c', 'scheduler.c', 'time.c', 'tcb.c', 'space.c', 'bootm.c', 'resource.c', 'container.c', 'capability.c']
obj = env.Object(src_local)
Return('obj')

View File

@@ -17,15 +17,19 @@
* Add irqs, exceptions
*/
#define CONFIG_CONT0_PAGER_START 0x40000
#define CONFIG_CONT0_PHYS_END 0x1000000
#define CONFIG_CONT0_PHYS_START CONFIG_CONT0_PAGER_START
struct container_info cinfo[] = {
[0] = {
.name = "Codezero POSIX Services",
.npagers = 1,
.pager = {
[0] = {
.pager_lma = __pfn(0x38000),
.pager_lma = __pfn(CONFIG_CONT0_PAGER_START),
.pager_vma = __pfn(0xE0000000),
.pager_size = __pfn(0x96000),
.pager_size = __pfn(0x9F000),
.ncaps = 14,
.caps = {
[0] = {
@@ -67,8 +71,8 @@ struct container_info cinfo[] = {
.access = CAP_MAP_CACHED | CAP_MAP_UNCACHED
| CAP_MAP_READ | CAP_MAP_WRITE
| CAP_MAP_EXEC | CAP_MAP_UNMAP,
.start = __pfn(0x38000),
.end = __pfn(0x1000000), /* 16 MB for all posix services */
.start = __pfn(CONFIG_CONT0_PHYS_START),
.end = __pfn(CONFIG_CONT0_PHYS_END), /* 16 MB for all posix services */
},
[5] = {
.type = CAP_TYPE_IPC | CAP_RTYPE_CONTAINER,
@@ -269,9 +273,13 @@ int init_first_pager(struct pager *pager,
mutex_init(&space->lock);
space->pgd = current_pgd;
/* Initialize container relationships */
task->space = space;
task->container = cont;
pager->tcb = task;
task->pager = pager;
task->container = cont;
link_init(&task->cap_list.caps); /* TODO: Do this in tcb_alloc_init */
task->cap_list_ptr = &pager->cap_list;
/* Map the task's space */
add_mapping_pgd(pager->start_lma, pager->start_vma,
@@ -314,9 +322,12 @@ int init_pager(struct pager *pager, struct container *cont)
task->space = address_space_create(0);
task->container = cont;
/* Initialize container relationships */
pager->tcb = task;
task->pager = pager;
task->container = cont;
link_init(&task->cap_list.caps); /* TODO: Do this in tcb_alloc_init */
task->cap_list_ptr = &pager->cap_list;
add_mapping_pgd(pager->start_lma, pager->start_vma,
page_align_up(pager->memsize),

View File

@@ -1,93 +0,0 @@
/*
* Global physical memory descriptions.
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <l4/generic/physmem.h>
#include <l4/generic/resource.h>
#include <l4/generic/tcb.h>
#include <l4/lib/list.h>
#include <l4/lib/spinlock.h>
#include INC_SUBARCH(mm.h)
#include INC_GLUE(memlayout.h)
#include INC_GLUE(memory.h)
#include INC_PLAT(offsets.h)
#include INC_PLAT(printascii.h)
#include INC_ARCH(linker.h)
struct page_bitmap page_map;
static void init_page_map(unsigned long start, unsigned long end)
{
page_map.pfn_start = __pfn(start);
page_map.pfn_end = __pfn(end);
set_page_map(start, __pfn(end - start), 0);
}
/*
* Marks pages in the global page_map as used or unused.
*
* @start = start page address to set, inclusive.
* @numpages = number of pages to set.
*/
int set_page_map(unsigned long start, int numpages, int val)
{
unsigned long pfn_start = __pfn(start);
unsigned long pfn_end = __pfn(start) + numpages;
unsigned long pfn_err = 0;
if (page_map.pfn_start > pfn_start || page_map.pfn_end < pfn_start) {
pfn_err = pfn_start;
goto error;
}
if (page_map.pfn_end < pfn_end || page_map.pfn_start > pfn_end) {
pfn_err = pfn_end;
goto error;
}
if (val)
for (int i = pfn_start; i < pfn_end; i++)
page_map.map[BITWISE_GETWORD(i)] |= BITWISE_GETBIT(i);
else
for (int i = pfn_start; i < pfn_end; i++)
page_map.map[BITWISE_GETWORD(i)] &= ~BITWISE_GETBIT(i);
return 0;
error:
BUG_MSG("Given page area is out of system page_map range: 0x%lx\n",
pfn_err << PAGE_BITS);
return -1;
}
/* Describes physical memory boundaries of the system. */
struct memdesc physmem;
/* Fills in the physmem structure with free physical memory information */
void physmem_init()
{
unsigned long start = (unsigned long)_start_kernel;
unsigned long end = (unsigned long)_end_kernel;
/* Initialise page map */
init_page_map(PHYS_MEM_START, PHYS_MEM_END);
/* Mark kernel areas as used */
set_page_map(virt_to_phys(start), __pfn(end - start), 1);
/* Map initial pgd area as used */
start = (unsigned long)__pt_start;
end = (unsigned long)__pt_end;
set_page_map(virt_to_phys(TASK_PGD(current)), __pfn(end - start), 1);
physmem.start = PHYS_MEM_START;
physmem.end = PHYS_MEM_END;
physmem.free_cur = __svc_images_end;
physmem.free_end = PHYS_MEM_END;
physmem.numpages = (PHYS_MEM_START - PHYS_MEM_END) / PAGE_SIZE;
}
void memory_init()
{
//init_pgalloc();
}

View File

@@ -8,7 +8,6 @@
#include <l4/lib/string.h>
#include <l4/lib/idpool.h>
#include <l4/generic/platform.h>
#include <l4/generic/physmem.h>
#include <l4/generic/scheduler.h>
#include <l4/generic/space.h>
#include <l4/generic/tcb.h>
@@ -17,7 +16,6 @@
#include <l4/generic/container.h>
#include INC_ARCH(linker.h)
#include INC_ARCH(asm.h)
#include INC_ARCH(bootdesc.h)
#include INC_SUBARCH(mm.h)
#include INC_SUBARCH(mmu_ops.h)
#include INC_GLUE(memlayout.h)

View File

@@ -6,7 +6,6 @@
#include <l4/lib/list.h>
#include <l4/lib/string.h>
#include <l4/lib/printk.h>
#include <l4/generic/physmem.h>
#include <l4/generic/space.h>
#include <l4/generic/tcb.h>
#include INC_SUBARCH(mm.h)

View File

@@ -1,24 +0,0 @@
/*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __MM_KDATA_H__
#define __MM_KDATA_H__
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include <l4/generic/physmem.h>
#include INC_PLAT(offsets.h)
#include INC_GLUE(memory.h)
#include INC_GLUE(memlayout.h)
#include INC_ARCH(bootdesc.h)
struct initdata {
struct bootdesc *bootdesc;
};
extern struct initdata initdata;
int request_initdata(struct initdata *i);
#endif /* __MM_KDATA_H__ */

View File

@@ -12,7 +12,6 @@
#include <l4lib/ipcdefs.h>
#include <fs.h>
#include <init.h>
#include <kdata.h>
#include <syscalls.h>
#include <task.h>
#include <posix/sys/time.h>

View File

@@ -7,7 +7,6 @@
#include <vfs.h>
#include <bdev.h>
#include <task.h>
#include <kdata.h>
#include <stdio.h>
#include <string.h>
#include <l4/lib/list.h>
@@ -58,7 +57,7 @@ int initialise(void)
struct superblock *root_sb;
/* Get standard init data from microkernel */
request_initdata(&initdata);
// request_initdata(&initdata);
/* Register compiled-in filesystems with vfs core. */
vfs_register_filesystems();

View File

@@ -1,63 +0,0 @@
/*
* Requesting system information from kernel during init.
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <stdio.h>
#include <l4lib/arch/syscalls.h>
#include <kdata.h>
#include <string.h>
#include INC_API(kip.h)
#include <task.h>
/* Kernel data acquired during initialisation */
struct initdata initdata;
#define BOOTDESC_PREALLOC_SIZE 128
static char bootdesc_memory[BOOTDESC_PREALLOC_SIZE]; /* 128 bytes */
void print_bootdesc(struct bootdesc *bd)
{
for (int i = 0; i < bd->total_images; i++) {
printf("Task Image: %d\n", i);
printf("Name: %s\n", bd->images[i].name);
printf("Start: 0x%x\n", bd->images[i].phys_start);
printf("End: 0x%x\n", bd->images[i].phys_end);
}
}
int request_initdata(struct initdata *initdata)
{
int err;
int bootdesc_size;
/* Read the boot descriptor size */
if ((err = l4_kread(KDATA_BOOTDESC_SIZE, &bootdesc_size)) < 0) {
printf("L4_kdata_read() call failed. Could not complete"
"KDATA_BOOTDESC_SIZE request.\n");
goto error;
}
if (bootdesc_size > BOOTDESC_PREALLOC_SIZE) {
printf("Insufficient preallocated memory for bootdesc. "
"Size too big.\n");
goto error;
}
/* Get preallocated bootdesc memory */
initdata->bootdesc = (struct bootdesc *)&bootdesc_memory;
/* Read the boot descriptor */
if ((err = l4_kread(KDATA_BOOTDESC, initdata->bootdesc)) < 0) {
printf("L4_kdata_read() call failed. Could not complete"
"KDATA_BOOTDESC request.\n");
goto error;
}
return 0;
error:
printf("FATAL: %s failed during initialisation. exiting.\n", __TASKNAME__);
return err;
}

View File

@@ -15,11 +15,7 @@ struct bootdesc {
struct svc_image images[];
} __attribute__((__packed__));
#if defined (__KERNEL__)
extern struct bootdesc *bootdesc;
void read_bootdesc(void);
void copy_bootdesc(void);
#endif
struct initdata;
void read_bootdesc(struct initdata *initdata);
#endif /* __BOOTDESC_H__ */

View File

@@ -0,0 +1,9 @@
#ifndef __PAGER_BOOTM_H__
#define __PAGER_BOOTM_H__
#define __initdata SECTION(".init.data")
void *alloc_bootmem(int size, int alignment);
#endif /* __PAGER_BOOTM_H__ */

View File

@@ -0,0 +1,41 @@
/*
* Capability-related operations of the pager.
*
* Copyright (C) 2009 Bahadir Balban
*/
#ifndef __MM0_CAPABILITY_H__
#define __MM0_CAPABILITY_H__
#include <l4lib/types.h>
#include <l4/lib/list.h>
struct cap_list {
int ncaps;
struct link caps;
};
struct capability {
struct link list;
/* Capability identifiers */
l4id_t capid; /* Unique capability ID */
l4id_t resid; /* Targeted resource ID */
l4id_t owner; /* Capability owner ID */
unsigned int type; /* Capability and target resource type */
/* Capability limits/permissions */
u32 access; /* Permitted operations */
/* Limits on the resource */
unsigned long start; /* Resource start value */
unsigned long end; /* Resource end value */
unsigned long size; /* Resource size */
};
extern struct cap_list capability_list;
struct initdata;
int read_kernel_capabilities(struct initdata *);
#endif /* __MM0_CAPABILITY_H__ */

View File

@@ -9,16 +9,19 @@
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include <l4/generic/physmem.h>
#include INC_PLAT(offsets.h)
#include INC_GLUE(memory.h)
#include INC_GLUE(memlayout.h)
#include INC_ARCH(bootdesc.h)
#include <bootdesc.h>
#include <physmem.h>
#include <vm_area.h>
#include <capability.h>
struct initdata {
struct capability *bootcaps;
struct capability *physmem;
struct bootdesc *bootdesc;
struct page_bitmap page_map;
struct page_bitmap *page_map;
unsigned long pager_utcb_virt;
unsigned long pager_utcb_phys;
struct link boot_file_list;
@@ -26,9 +29,9 @@ struct initdata {
extern struct initdata initdata;
int request_initdata(struct initdata *i);
void init_pager(void);
void initialise(void);
/* TODO: Remove this stuff from here. */
int init_devzero(void);
struct vm_file *get_devzero(void);
int init_boot_files(struct initdata *initdata);

View File

@@ -33,12 +33,19 @@ SECTIONS
{
*(.data)
}
. = ALIGN(4K);
_start_init = .;
.init : AT (ADDR(.init) - offset) { *(.init.stack) }
. = ALIGN(8);
__stack = .; /* This is the preallocated boot stack */
_end_init = .;
.bss : AT (ADDR(.bss) - 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.data)
*(.init.bootmem)
*(.init.stack)
}
_end_init = .;
__stack = .; /* This is the preallocated boot stack */
_end_init = .;
_end = .;
}

View File

@@ -8,14 +8,7 @@
#include <vm_area.h>
#include <init.h>
struct membank {
unsigned long start;
unsigned long end;
unsigned long free;
struct page *page_array;
};
extern struct membank membank[];
#include <physmem.h>
void init_mm_descriptors(struct page_bitmap *page_map,
struct bootdesc *bootdesc, struct membank *membank);

View File

@@ -0,0 +1,45 @@
/*
* Physical memory descriptors
*
* Copyright (C) 2007 - 2009 Bahadir Balban
*/
#ifndef __PAGER_PHYSMEM_H__
#define __PAGER_PHYSMEM_H__
/* A compact memory descriptor to determine used/unused pages in the system */
struct page_bitmap {
unsigned long pfn_start;
unsigned long pfn_end;
unsigned int map[];
};
/* Describes a portion of physical memory. */
struct memdesc {
unsigned int start;
unsigned int end;
unsigned int free_cur;
unsigned int free_end;
unsigned int numpages;
};
struct membank {
unsigned long start;
unsigned long end;
unsigned long free;
struct page *page_array;
};
extern struct membank membank[];
/* Describes bitmap of used/unused state for all physical pages */
extern struct page_bitmap page_map;
extern struct memdesc physmem;
/* Sets the global page map as used/unused. Aligns input when needed. */
int set_page_map(struct page_bitmap *pmap, unsigned long start,
int numpages, int val);
struct initdata;
void init_physmem_primary(struct initdata *initdata);
void init_physmem_secondary(struct initdata *initdata, struct membank *membank);
#endif /* __PAGER_PHYSMEM_H__ */

View File

@@ -261,7 +261,7 @@ void main(void)
printf("\n%s: Started with thread id %d\n", __TASKNAME__, self_tid());
/* Initialise the memory, server tasks, mmap and start them. */
initialise();
init_pager();
printf("%s: Memory/Process manager initialized. Listening requests.\n", __TASKNAME__);
while (1) {

44
tasks/mm0/src/bootdesc.c Normal file
View File

@@ -0,0 +1,44 @@
/*
* Reading of bootdesc forged at build time.
*
* Copyright (C) 2007 - 2009 Bahadir Balban
*/
#include <bootdesc.h>
#include <bootm.h>
#include <init.h>
#include <l4lib/arch/syslib.h>
extern unsigned long _end[];
void read_bootdesc(struct initdata *initdata)
{
int npages;
struct bootdesc *bootdesc;
/*
* End of the executable image is where bootdesc resides
*/
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);
/* Allocate bootdesc sized structure */
initdata->bootdesc = alloc_bootmem(bootdesc->desc_size, 0);
/* Copy bootdesc to initdata */
memcpy(initdata->bootdesc, bootdesc,
bootdesc->desc_size);
if (npages > 0)
l4_unmap_helper((void *)page_align_up(_end),
PAGE_SIZE * npages);
}

62
tasks/mm0/src/bootm.c Normal file
View File

@@ -0,0 +1,62 @@
/*
* Boot memory allocator
*
* Copyright (C) 2009 Bahadir Balban
*/
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include <l4/lib/list.h>
#include <l4/lib/math.h>
#include <l4/api/thread.h>
#include <l4/api/kip.h>
#include <l4/api/errno.h>
#include INC_GLUE(memory.h)
#include <stdio.h>
/* All memory allocated here is discarded after boot */
#define BOOTMEM_SIZE SZ_32K
SECTION(".init.bootmem") char bootmem[BOOTMEM_SIZE];
SECTION(".init.stack") char stack[4096];
// SECTION("init.data")
extern unsigned long __stack[]; /* Linker defined */
static unsigned long cursor = (unsigned long)&bootmem;
void *alloc_bootmem(int size, int alignment)
{
void *ptr;
/* If alignment is required */
if (alignment) {
/* And cursor is not aligned */
if (!is_aligned(cursor, alignment))
/* Align the cursor to alignment */
cursor = align_up(cursor, alignment);
/* Align to 4 byte by default */
} else if (size >= 4) {
/* And cursor is not aligned */
if (!is_aligned(cursor, 4))
/* Align the cursor to alignment */
cursor = align_up(cursor, 4);
}
/* Allocate from cursor */
ptr = (void *)cursor;
/* Update cursor */
cursor += size;
/* Check if cursor is passed bootmem area */
if (cursor >= (unsigned long)&bootmem[BOOTMEM_SIZE]) {
printk("Fatal: Insufficient boot memory.\n");
BUG();
}
return ptr;
}

View File

@@ -0,0 +1,62 @@
/*
* Pager's capabilities for kernel resources
*
* Copyright (C) 2009 Bahadir Balban
*/
#include <bootm.h>
#include <init.h>
#include <capability.h>
#include <l4/api/capability.h>
#include <l4lib/arch/syscalls.h>
#include <l4/generic/cap-types.h> /* TODO: Move this to API */
extern struct cap_list capability_list;
__initdata static struct capability *caparray;
int read_kernel_capabilities(struct initdata *initdata)
{
int ncaps;
int err;
/* Read number of capabilities */
if ((err = l4_capability_control(CAP_CONTROL_NCAPS, 0, &ncaps)) < 0) {
printf("l4_capability_control() reading # of capabilities failed.\n"
"Could not complete CAP_CONTROL_NCAPS request.\n");
goto error;
}
/* Allocate array of caps from boot memory */
caparray = alloc_bootmem(sizeof(struct capability) * ncaps, 0);
/* Read all capabilities */
if ((err = l4_capability_control(CAP_CONTROL_READ_CAPS, 0, caparray)) < 0) {
printf("l4_capability_control() reading of capabilities failed.\n"
"Could not complete CAP_CONTROL_READ_CAPS request.\n");
goto error;
}
/* Set up initdata pointer to important capabilities */
initdata->bootcaps = caparray;
for (int i = 0; i < ncaps; i++) {
/*
* TODO: There may be multiple physmem caps!
* This really needs to be considered as multiple
* membanks!!!
*/
if ((caparray[i].type & CAP_RTYPE_MASK)
== CAP_RTYPE_PHYSMEM) {
initdata->physmem = &caparray[i];
return 0;
}
}
printf("%s: Error, pager has no physmem capability defined.\n",
__TASKNAME__);
goto error;
return 0;
error:
BUG();
}

View File

@@ -19,10 +19,61 @@
#include <test.h>
#include <boot.h>
#include <utcb.h>
#include <bootm.h>
/* A separate list than the generic file list that keeps just the boot files */
LINK_DECLARE(boot_file_list);
/* Kernel data acquired during initialisation */
__initdata struct initdata initdata;
void print_bootdesc(struct bootdesc *bd)
{
for (int i = 0; i < bd->total_images; i++) {
printf("Task Image: %d\n", i);
printf("Name: %s\n", bd->images[i].name);
printf("Start: 0x%x\n", bd->images[i].phys_start);
printf("End: 0x%x\n", bd->images[i].phys_end);
}
}
void print_pfn_range(int pfn, int size)
{
unsigned int addr = pfn << PAGE_BITS;
unsigned int end = (pfn + size) << PAGE_BITS;
printf("Used: 0x%x - 0x%x\n", addr, end);
}
#if 0
void print_page_map(struct page_bitmap *map)
{
unsigned int start_pfn = 0;
unsigned int total_used = 0;
int numpages = 0;
// printf("Page map: 0x%x-0x%x\n", map->pfn_start << PAGE_BITS, map->pfn_end << PAGE_BITS);
for (int i = 0; i < (PHYSMEM_TOTAL_PAGES >> 5); i++) {
for (int x = 0; x < WORD_BITS; x++) {
if (map->map[i] & (1 << x)) { /* A used page found? */
if (!start_pfn) /* First such page found? */
start_pfn = (WORD_BITS * i) + x;
total_used++;
numpages++; /* Increase number of pages */
} else { /* Either used pages ended or were never found */
if (start_pfn) { /* We had a used page */
/* Finished end of used range.
* Print and reset. */
//print_pfn_range(start_pfn, numpages);
start_pfn = 0;
numpages = 0;
}
}
}
}
printf("%s: Pagemap: Total of %d used physical pages. %d Kbytes used.\n", __TASKNAME__, total_used, total_used << 2);
}
#endif
/*
* A specialised function for setting up the task environment of mm0.
* Essentially all the memory regions are set up but a new task isn't
@@ -160,7 +211,10 @@ int start_boot_tasks(struct initdata *initdata)
void init_mm(struct initdata *initdata)
{
/* Initialise the page and bank descriptors */
init_physmem(initdata, membank);
init_physmem_primary(initdata);
init_physmem_secondary(initdata, membank);
// printf("%s: Initialised physmem.\n", __TASKNAME__);
/* Initialise the page allocator on first bank. */
@@ -190,14 +244,14 @@ void init_mm(struct initdata *initdata)
pager_address_pool_init();
// printf("%s: Initialised utcb address pool.\n", __TASKNAME__);
/* Give the kernel some memory to use for its allocators */
l4_kmem_control(__pfn(alloc_page(__pfn(SZ_1MB))), __pfn(SZ_1MB), 1);
}
void initialise(void)
void init_pager(void)
{
request_initdata(&initdata);
read_kernel_capabilities(&initdata);
read_bootdesc(&initdata);
init_mm(&initdata);

View File

@@ -1,105 +0,0 @@
/*
* Requesting system information from kernel during init.
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <stdio.h>
#include <string.h>
#include <init.h>
#include INC_API(kip.h)
#include <lib/malloc.h>
#include <l4lib/arch/syscalls.h>
/* Kernel data acquired during initialisation */
struct initdata initdata;
#define BOOTDESC_PREALLOC_SIZE 128
static char bootdesc_memory[BOOTDESC_PREALLOC_SIZE]; /* 128 bytes */
void print_bootdesc(struct bootdesc *bd)
{
for (int i = 0; i < bd->total_images; i++) {
printf("Task Image: %d\n", i);
printf("Name: %s\n", bd->images[i].name);
printf("Start: 0x%x\n", bd->images[i].phys_start);
printf("End: 0x%x\n", bd->images[i].phys_end);
}
}
void print_pfn_range(int pfn, int size)
{
unsigned int addr = pfn << PAGE_BITS;
unsigned int end = (pfn + size) << PAGE_BITS;
printf("Used: 0x%x - 0x%x\n", addr, end);
}
void print_page_map(struct page_bitmap *map)
{
unsigned int start_pfn = 0;
unsigned int total_used = 0;
int numpages = 0;
// printf("Page map: 0x%x-0x%x\n", map->pfn_start << PAGE_BITS, map->pfn_end << PAGE_BITS);
for (int i = 0; i < (PHYSMEM_TOTAL_PAGES >> 5); i++) {
for (int x = 0; x < WORD_BITS; x++) {
if (map->map[i] & (1 << x)) { /* A used page found? */
if (!start_pfn) /* First such page found? */
start_pfn = (WORD_BITS * i) + x;
total_used++;
numpages++; /* Increase number of pages */
} else { /* Either used pages ended or were never found */
if (start_pfn) { /* We had a used page */
/* Finished end of used range.
* Print and reset. */
//print_pfn_range(start_pfn, numpages);
start_pfn = 0;
numpages = 0;
}
}
}
}
printf("%s: Pagemap: Total of %d used physical pages. %d Kbytes used.\n", __TASKNAME__, total_used, total_used << 2);
}
int request_initdata(struct initdata *initdata)
{
int err;
int bootdesc_size;
/* Read all used physical page information in a bitmap. */
if ((err = l4_kread(KDATA_PAGE_MAP, &initdata->page_map)) < 0) {
printf("L4_kdata_read() call failed. Could not complete"
"KDATA_PAGE_MAP request.\n");
goto error;
}
print_page_map(&initdata->page_map);
/* Read the boot descriptor size */
if ((err = l4_kread(KDATA_BOOTDESC_SIZE, &bootdesc_size)) < 0) {
printf("L4_kdata_read() call failed. Could not complete"
"KDATA_BOOTDESC_SIZE request.\n");
goto error;
}
if (bootdesc_size > BOOTDESC_PREALLOC_SIZE) {
printf("Insufficient preallocated memory for bootdesc. "
"Size too big.\n");
goto error;
}
/* Get preallocated bootdesc memory */
initdata->bootdesc = (struct bootdesc *)&bootdesc_memory;
/* Read the boot descriptor */
if ((err = l4_kread(KDATA_BOOTDESC, initdata->bootdesc)) < 0) {
printf("L4_kdata_read() call failed. Could not complete"
"KDATA_BOOTDESC request.\n");
goto error;
}
return 0;
error:
printf("FATAL: Inittask failed during initialisation. exiting.\n");
return err;
}

View File

@@ -17,8 +17,6 @@
#include <file.h>
#include <user.h>
struct membank membank[1];
struct page *page_array;
struct address_pool pager_vaddr_pool;
@@ -32,69 +30,6 @@ void *virt_to_phys(void *addr)
return addr - INITTASK_OFFSET;
}
/* Allocates page descriptors and initialises them using page_map information */
void init_physmem(struct initdata *initdata, struct membank *membank)
{
struct page_bitmap *pmap = &initdata->page_map;
int npages = pmap->pfn_end - pmap->pfn_start;
/* Allocation marks for the struct page array */
int pg_npages, pg_spfn, pg_epfn;
unsigned long ffree_addr;
/*
* Means the page array won't map one to one to pfns. That's ok,
* but we dont allow it for now.
*/
BUG_ON(pmap->pfn_start);
membank[0].start = __pfn_to_addr(pmap->pfn_start);
membank[0].end = __pfn_to_addr(pmap->pfn_end);
/* First find the first free page after last used page */
for (int i = 0; i < npages; i++)
if ((pmap->map[BITWISE_GETWORD(i)] & BITWISE_GETBIT(i)))
membank[0].free = (i + 1) * PAGE_SIZE;
BUG_ON(membank[0].free >= membank[0].end);
/*
* One struct page for every physical page. Calculate how many pages
* needed for page structs, start and end pfn marks.
*/
pg_npages = __pfn((sizeof(struct page) * npages));
/* These are relative pfn offsets to the start of the memory bank */
pg_spfn = __pfn(membank[0].free) - __pfn(membank[0].start);
pg_epfn = pg_spfn + pg_npages;
/* Use free pages from the bank as the space for struct page array */
membank[0].page_array = l4_map_helper((void *)membank[0].free,
pg_npages);
/* Update free memory left */
membank[0].free += pg_npages * PAGE_SIZE;
/* Update page bitmap for the pages used for the page array */
for (int i = pg_spfn; i < pg_epfn; i++)
pmap->map[BITWISE_GETWORD(i)] |= BITWISE_GETBIT(i);
/* Initialise the page array */
for (int i = 0; i < npages; i++) {
link_init(&membank[0].page_array[i].list);
/* Set use counts for pages the kernel has already used up */
if (!(pmap->map[BITWISE_GETWORD(i)] & BITWISE_GETBIT(i)))
membank[0].page_array[i].refcnt = -1;
else /* Last page used +1 is free */
ffree_addr = (i + 1) * PAGE_SIZE;
}
/* First free address must come up the same for both */
BUG_ON(ffree_addr != membank[0].free);
/* Set global page array to this bank's 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)
{

View File

@@ -12,7 +12,6 @@
#include <globals.h>
#include <file.h>
#include <init.h>
#include INC_ARCH(bootdesc.h)
#include <l4/api/errno.h>
struct page *page_init(struct page *page)

166
tasks/mm0/src/physmem.c Normal file
View File

@@ -0,0 +1,166 @@
/*
* Global physical memory descriptions.
*
* Copyright (C) 2007 - 2009 Bahadir Balban
*/
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include <l4/lib/list.h>
#include <l4/lib/math.h>
#include <l4/api/thread.h>
#include <l4/api/kip.h>
#include <l4/api/errno.h>
#include INC_GLUE(memory.h)
#include <l4lib/arch/syslib.h>
#include <stdio.h>
#include <init.h>
#include <physmem.h>
struct page_bitmap page_map; /* Bitmap of used/unused pages at bootup */
struct memdesc physmem; /* Initial, primitive memory descriptor */
struct membank membank[1]; /* The memory bank */
struct page *page_array; /* The physical page array based on mem bank */
static void init_page_map(unsigned long pfn_start, unsigned long pfn_end)
{
page_map.pfn_start = pfn_start;
page_map.pfn_end = pfn_end;
set_page_map(&page_map, pfn_start, pfn_end - pfn_start, 0);
}
/*
* Marks pages in the global page_map as used or unused.
*
* @start = start page address to set, inclusive.
* @numpages = number of pages to set.
*/
int set_page_map(struct page_bitmap *page_map, unsigned long pfn_start,
int numpages, int val)
{
unsigned long pfn_end = pfn_start + numpages;
unsigned long pfn_err = 0;
if (page_map->pfn_start > pfn_start || page_map->pfn_end < pfn_start) {
pfn_err = pfn_start;
goto error;
}
if (page_map->pfn_end < pfn_end || page_map->pfn_start > pfn_end) {
pfn_err = pfn_end;
goto error;
}
if (val)
for (int i = pfn_start; i < pfn_end; i++)
page_map->map[BITWISE_GETWORD(i)] |= BITWISE_GETBIT(i);
else
for (int i = pfn_start; i < pfn_end; i++)
page_map->map[BITWISE_GETWORD(i)] &= ~BITWISE_GETBIT(i);
return 0;
error:
BUG_MSG("Given page area is out of system page_map range: 0x%lx\n",
pfn_err << PAGE_BITS);
return -1;
}
/* Allocates page descriptors and initialises them using page_map information */
void init_physmem_secondary(struct initdata *initdata, struct membank *membank)
{
struct page_bitmap *pmap = initdata->page_map;
int npages = pmap->pfn_end - pmap->pfn_start;
/* Allocation marks for the struct page array; npages, start, end */
int pg_npages, pg_spfn, pg_epfn;
unsigned long ffree_addr;
/*
* Means the page array won't map one to one to pfns. That's ok,
* but we dont allow it for now.
*/
// BUG_ON(pmap->pfn_start);
membank[0].start = __pfn_to_addr(pmap->pfn_start);
membank[0].end = __pfn_to_addr(pmap->pfn_end);
/* First find the first free page after last used page */
for (int i = 0; i < npages; i++)
if ((pmap->map[BITWISE_GETWORD(i)] & BITWISE_GETBIT(i)))
membank[0].free = (i + 1) * PAGE_SIZE;
BUG_ON(membank[0].free >= membank[0].end);
/*
* One struct page for every physical page. Calculate how many pages
* needed for page structs, start and end pfn marks.
*/
pg_npages = __pfn(page_align_up((sizeof(struct page) * npages)));
/* These are relative pfn offsets to the start of the memory bank */
/* FIXME:
* 1.) These values were only right when membank started from pfn 0.
* 2.) Use set_page_map to set page map below instead of manually.
*/
pg_spfn = __pfn(membank[0].free);
pg_epfn = pg_spfn + pg_npages;
/* Use free pages from the bank as the space for struct page array */
membank[0].page_array = l4_map_helper((void *)membank[0].free,
pg_npages);
/* Update free memory left */
membank[0].free += pg_npages * PAGE_SIZE;
/* Update page bitmap for the pages used for the page array */
for (int i = pg_spfn; i < pg_epfn; i++)
pmap->map[BITWISE_GETWORD(i)] |= BITWISE_GETBIT(i);
/* Initialise the page array */
for (int i = 0; i < npages; i++) {
link_init(&membank[0].page_array[i].list);
/* Set use counts for pages the kernel has already used up */
if (!(pmap->map[BITWISE_GETWORD(i)] & BITWISE_GETBIT(i)))
membank[0].page_array[i].refcnt = -1;
else /* Last page used +1 is free */
ffree_addr = (i + 1) * PAGE_SIZE;
}
/* First free address must come up the same for both */
BUG_ON(ffree_addr != membank[0].free);
/* Set global page array to this bank's array */
page_array = membank[0].page_array;
}
/* Fills in the physmem structure with free physical memory information */
void init_physmem_primary(struct initdata *initdata)
{
unsigned long pfn_start, pfn_end, pfn_images_end = 0;
struct bootdesc *bootdesc = initdata->bootdesc;
/* Initialise page map from physmem capability */
init_page_map(initdata->physmem->start,
initdata->physmem->end);
/* Set initdata pointer to initialized page map */
initdata->page_map = &page_map;
/* Mark pager and other boot task areas as used */
for (int i = 0; i < bootdesc->total_images; i++) {
pfn_start = __pfn(page_align_up(bootdesc->images[i].phys_start));
pfn_end = __pfn(page_align_up(bootdesc->images[i].phys_end));
if (pfn_end > pfn_images_end)
pfn_images_end = pfn_end;
set_page_map(&page_map, pfn_start, pfn_end - pfn_start, 1);
}
physmem.start = initdata->physmem->start;
physmem.end = initdata->physmem->end;
physmem.free_cur = pfn_images_end;
physmem.free_end = physmem.end;
physmem.numpages = __pfn(physmem.end - physmem.start);
}

View File

@@ -1,33 +0,0 @@
/*
* TODO: This is to be used when moving mm0's temporary
* stack to a proper place. It's unused for now.
*
* Copyright (C) 2007, 2008 Bahadir Balban
*/
#include <l4/config.h>
#include <l4/macros.h>
#include <l4/types.h>
#include INC_GLUE(memlayout.h)
#include <string.h>
/* The initial temporary stack used until memory is set up */
__attribute__ ((section("init.stack"))) char stack[4096];
extern unsigned long __stack[]; /* Linker defined */
/* Moves from temporary stack to where it should be in actual. */
void move_stack()
{
register unsigned int sp asm("sp");
register unsigned int fp asm("r11");
unsigned int stack_offset = (unsigned long)__stack - sp;
unsigned int frame_offset = (unsigned long)__stack - fp;
/* Copy current stack into new stack. NOTE: This might demand-page
* the new stack, but maybe that won't work. */
memcpy((void *)USER_AREA_END, __stack, stack_offset);
sp = USER_AREA_END - stack_offset;
fp = USER_AREA_END - frame_offset;
}