Changes in merged posix pager mm0 initialization.

- Moved rootfs from being embedded to mm0 image to being an independent image.
- MM0 boots up to start_init_process with updated boot convention.
This commit is contained in:
Bahadir Balban
2009-10-05 13:25:32 +03:00
parent f8bcd7a546
commit da5f4dcff3
22 changed files with 383 additions and 601 deletions

View File

@@ -56,6 +56,7 @@ def configure_kernel(cml_file):
cml2_update_config_h(CONFIG_H, config)
configuration_save(config)
#config.config_print()
# Generate bare container files if new ones defined
bare_cont_gen = BareContGenerator()

View File

@@ -70,13 +70,17 @@ mm0 = SConscript('mm0/SConscript', \
exports = { 'config' : config, 'env' : mm0_env, 'contid' : contid }, duplicate = 0, \
variant_dir = join(BUILDDIR, 'cont' + str(contid) + '/posix' + '/mm0'))
rootfs = SConscript('rootfs/SConscript', \
exports = { 'config' : config, 'environment' : env, 'contid' : contid, 'previmage' : mm0 }, duplicate = 0, \
variant_dir = join(BUILDDIR, 'cont' + str(contid) + '/posix' + '/rootfs'))
test0_env = env.Clone()
test0_env.Replace(CPPPATH = ['include', KERNEL_INCLUDE, LIBL4_INCLUDE, LIBMEM_INCLUDE])
test0 = SConscript('test0/SConscript', \
exports = { 'config' : config, 'environment' : test0_env, 'contid' : contid, 'previmage' : mm0 }, duplicate = 0, \
exports = { 'config' : config, 'environment' : test0_env, 'contid' : contid, 'previmage' : rootfs }, duplicate = 0, \
variant_dir = join(BUILDDIR, 'cont' + str(contid) + '/posix' + '/test0'))
images = [mm0, test0]
images = [mm0, rootfs, test0]
bootdesc_env = env.Clone()
bootdesc_env['bootdesc_dir'] = 'bootdesc'
@@ -87,11 +91,13 @@ bootdesc = SConscript('bootdesc/SConscript', \
Depends(mm0, libposix)
Depends(test0, libposix)
Depends(bootdesc, [test0, mm0])
Depends(rootfs, mm0)
Depends(test0, rootfs)
Depends(bootdesc, [test0, mm0, rootfs])
Alias('libposix', libposix)
Alias('mm0', mm0)
Alias('test0', test0)
Alias('bootdesc', bootdesc)
Alias('rootfs', rootfs)
Default([mm0, libposix, test0, bootdesc])

View File

@@ -1,97 +0,0 @@
#
# User space application build script
#
# Copyright (C) 2007 Bahadir Balban
#
import os
import sys
import shutil
from string import split
from os.path import join
from glob import glob
task_name = "mm0"
# The root directory of the repository where this file resides:
project_root = "../.."
tools_root = join(project_root, "tools")
prev_image = join(project_root, "build/start.axf")
libs_path = join(project_root, "libs")
ld_script = "include/linker.lds"
physical_base_ld_script = "include/physical_base.lds"
# libc paths:
libc_variant = "userspace"
libc_libpath = join(libs_path, "c/build/%s" % libc_variant)
libc_incpath = join(libc_libpath, "include")
libc_crt0 = join(libs_path, "c/build/crt/sys-userspace/arch-arm/crt0.o")
libc_name = "c-%s" % libc_variant
# libl4 paths:
libl4_path = "../libl4"
libl4_incpath = join(libl4_path, "include")
# libposix paths:
libposix_path = "../libposix"
libposix_incpath = join(libposix_path, "include")
#libmem paths:
libmem_path = "../libmem"
libmem_incpath = "../libmem"
# kernel paths:
kernel_incpath = join(project_root, "include")
# Kernel config header.
config_h = join(project_root, "include/l4/config.h")
# If crt0 is in its library path, it becomes hard to link with it.
# For instance the linker script must use an absolute path for it.
def copy_crt0(source, target, env):
os.system("cp " + str(source[0]) + " " + str(target[0]))
def get_physical_base(source, target, env):
os.system(join(tools_root, "pyelf/readelf.py --first-free-page " + \
prev_image +" >> " + physical_base_ld_script))
# The kernel build environment:
env = Environment(CC = 'arm-none-linux-gnueabi-gcc',
# We don't use -nostdinc because sometimes we need standard headers,
# such as stdarg.h e.g. for variable args, as in printk().
CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', '-Werror' ],
LINKFLAGS = ['-nostdlib', '-T' + ld_script, "-L" + libc_libpath, "-L" + libl4_path, \
"-L" + libposix_path, "-L" + libmem_path],
ASFLAGS = ['-D__ASSEMBLY__'],
PROGSUFFIX = '.axf', # The suffix to use for final executable
ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path
LIBS = [libc_name, 'libl4', 'libmm', 'libmc', 'libkm', 'libposix', \
'gcc', libc_name], # libgcc.a - This is required for division routines.
CPPFLAGS = "-D__USERSPACE__",
CPPPATH = ['#include', libl4_incpath, libc_incpath, kernel_incpath, \
libmem_incpath, libposix_incpath])
def create_symlinks(arch):
arch_path = "include/arch"
arch_path2 ="src/arch"
if os.path.exists(arch_path):
os.system("rm %s" % (arch_path))
os.system("ln -s %s %s" % ("arch-" + arch, arch_path))
if os.path.exists(arch_path2):
os.system("rm %s" % (arch_path2))
os.system("ln -s %s %s" % ("arch-" + arch, arch_path2))
arch, subarch, plat = extract_arch_subarch_plat(config_h)
create_symlinks(arch) # Creates symlinks to architecture specific directories.
src = [glob("src/*.c"), glob("src/lib/*.c"), glob("src/lib/elf/*.c"), glob("*.c"), glob("src/arch/*.c")]
objs = env.Object(src)
physical_base = env.Command(physical_base_ld_script, prev_image, get_physical_base)
crt0_copied = env.Command("crt0.o", libc_crt0, copy_crt0)
task = env.Program(task_name, objs + [crt0_copied])
env.Alias(task_name, task)
env.Depends(task, physical_base)

View File

@@ -1,15 +1,19 @@
/*
* This is just to allocate some memory as a block device.
*/
#include <init.h>
#include <l4/macros.h>
#include <bootdesc.h>
#include <memfs/memfs.h>
extern char _start_bdev[];
extern char _end_bdev[];
__attribute__((section(".data.memfs"))) char blockdevice[MEMFS_TOTAL_SIZE];
#include <l4lib/arch/syslib.h>
void *vfs_rootdev_open(void)
{
return (void *)_start_bdev;
struct svc_image *rootfs_img = bootdesc_get_image_byname("rootfs");
unsigned long rootfs_size = rootfs_img->phys_end - rootfs_img->phys_start;
BUG_ON(rootfs_size < MEMFS_TOTAL_SIZE);
/* Map filesystem blocks to virtual memory */
return l4_map_helper((void *)rootfs_img->phys_start, __pfn(rootfs_size));
}

View File

@@ -1,5 +1,5 @@
/*
* FS0 Initialisation.
* Filesystem initialisation.
*
* Copyright (C) 2007 Bahadir Balban
*/
@@ -51,7 +51,7 @@ void vfs_register_filesystems(void)
/*
* Filesystem initialisation.
*/
int initialise(void)
int vfs_init(void)
{
void *rootdev_blocks;
struct superblock *root_sb;
@@ -79,10 +79,6 @@ int initialise(void)
printf("%s: Mounted memfs root filesystem.\n", __TASKNAME__);
/*
* Initialisation is done. From here on, we can start
* serving filesystem requests.
*/
return 0;
}

View File

@@ -15,7 +15,8 @@ struct bootdesc {
struct svc_image images[];
} __attribute__((__packed__));
struct initdata;
void read_bootdesc(struct initdata *initdata);
void read_boot_params();
struct svc_image *bootdesc_get_image_byname(char *);
#endif /* __BOOTDESC_H__ */

View File

@@ -38,7 +38,7 @@ struct capability {
extern struct cap_list capability_list;
struct initdata;
int read_kernel_capabilities(struct initdata *);
void copy_boot_capabilities(struct initdata *initdata);
int read_pager_capabilities();
void copy_boot_capabilities();
#endif /* __MM0_CAPABILITY_H__ */

View File

@@ -29,7 +29,7 @@ struct initdata {
extern struct initdata initdata;
void init_pager(void);
void init(void);
/* TODO: Remove this stuff from here. */
int init_devzero(void);

View File

@@ -31,13 +31,7 @@ SECTIONS
/* rodata is needed else your strings will link at physical! */
.rodata : AT (ADDR(.rodata) - pager_offset) { *(.rodata) }
.rodata1 : AT (ADDR(.rodata1) - pager_offset) { *(.rodata1) }
.data : AT (ADDR(.data) - pager_offset)
{
*(.data)
_start_bdev = .;
*(.data.memfs)
_end_bdev = .;
}
.data : AT (ADDR(.data) - pager_offset) { *(.data) }
.bss : AT (ADDR(.bss) - pager_offset) { *(.bss) }
. = ALIGN(4K);
. += 0x2000; /* BSS doesnt increment link counter??? */

View File

@@ -12,7 +12,7 @@
void init_mm_descriptors(struct page_bitmap *page_map,
struct bootdesc *bootdesc, struct membank *membank);
void init_physmem(struct initdata *initdata, struct membank *membank);
void init_physmem(void);
int pager_address_pool_init(void);
void *pager_new_address(int npages);

View File

@@ -31,15 +31,13 @@ struct membank {
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);
void init_physmem_primary();
void init_physmem_secondary(struct membank *membank);
#endif /* __PAGER_PHYSMEM_H__ */

View File

@@ -87,4 +87,6 @@ struct vnode *generic_vnode_lookup(struct vnode *thisnode, struct pathdata *p,
struct vnode *vfs_lookup_bypath(struct pathdata *p);
struct vnode *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum);
int vfs_init(void);
#endif /* __VFS_H__ */

View File

@@ -153,10 +153,6 @@ void handle_requests(void)
else
return; /* else we're done */
}
case L4_IPC_TAG_BRK: {
// ret = sys_brk(sender, (void *)mr[0]);
// break;
}
/* FIXME: Fix all these syscalls to read any buffer data from the caller task's utcb. */
/* FS0 System calls */
@@ -189,86 +185,11 @@ void handle_requests(void)
}
}
#if 0
/*
* Executes the given function in a new thread in the current
* address space but on a brand new stack.
*/
int self_spawn(void)
{
struct task_ids ids;
struct tcb *self, *self_child;
unsigned long stack, stack_size;
BUG_ON(!(self = find_task(self_tid())));
ids.tid = TASK_ID_INVALID;
ids.spid = self->spid;
ids.tgid = self->tgid;
/* Create a new L4 thread in current thread's address space. */
self_child = task_create(self, &ids, THREAD_SAME_SPACE,
TCB_SHARED_VM | TCB_SHARED_FILES);
if (IS_ERR(self_child = tcb_alloc_init(TCB_SHARED_VM
| TCB_SHARED_FILES)))
BUG();
/*
* Create a new utcb. Every pager thread will
* need its own utcb to answer calls.
*/
self_child->utcb = utcb_vaddr_new();
/* Map utcb to child */
task_map_prefault_utcb(self_child, self_child);
/*
* Set up a child stack by mmapping an anonymous region.
*/
stack_size = self->stack_end - self->stack_start;
if (IS_ERR(stack = do_mmap(0, 0, self, 0,
VM_READ | VM_WRITE | VMA_ANONYMOUS
| VMA_PRIVATE | VMA_GROWSDOWN,
__pfn(stack_size)))) {
printf("%s: Error spawning %s, Error code: %d\n",
__FUNCTION__, __TASKNAME__, (int)stack);
BUG();
}
/* Modify stack marker of child tcb */
self_child->stack_end = stack;
self_child->stack_start = stack - stack_size;
/* Prefault child stack */
for (int i = 0; i < __pfn(stack_size); i++)
prefault_page(self_child,
self_child->stack_start + __pfn_to_addr(i),
VM_READ | VM_WRITE);
/* Copy current stack to child */
memcpy((void *)self_child->stack_start,
(void *)self->stack_start, stack_size);
/* TODO: Modify registers ???, it depends on what state is copied in C0 */
/* TODO: Notify vfs ??? */
task_add_global(self_child);
if (l4_thread_control(THREAD_CREATE | THREAD_CREATE_SAMESPC, ids)
l4_thread_control(THREAD_RUN, &ids);
return 0;
}
#endif
void main(void)
{
printf("\n%s: Started with thread id %d\n", __TASKNAME__, self_tid());
/* Initialise the memory, server tasks, mmap and start them. */
init_pager();
init();
printf("%s: Memory/Process manager initialized. Listening requests.\n", __TASKNAME__);
while (1) {

View File

@@ -12,7 +12,15 @@
extern unsigned long _end[];
extern unsigned long pager_offset;
void read_bootdesc(struct initdata *initdata)
struct svc_image *bootdesc_get_image_byname(char *name)
{
for (int i = 0; i < initdata.bootdesc->total_images; i++)
if (!strncmp(initdata.bootdesc->images[i].name, name, strlen(name)))
return &initdata.bootdesc->images[i];
return 0;
}
void read_boot_params()
{
int npages;
struct bootdesc *bootdesc;
@@ -24,16 +32,15 @@ void read_bootdesc(struct initdata *initdata)
/* Check if bootdesc is on an unmapped page */
if (is_page_aligned(bootdesc))
l4_map_helper(bootdesc - pager_offset, PAGE_SIZE);
l4_map_helper(bootdesc - pager_offset, 1);
/* Allocate bootdesc sized structure */
initdata->bootdesc = alloc_bootmem(bootdesc->desc_size, 0);
initdata.bootdesc = alloc_bootmem(bootdesc->desc_size, 0);
/* Copy bootdesc to initdata */
memcpy(initdata->bootdesc, bootdesc,
memcpy(initdata.bootdesc, bootdesc,
bootdesc->desc_size);
if (npages > 0)
l4_unmap_helper((void *)page_align_up(_end),
PAGE_SIZE * npages);
l4_unmap_helper((void *)page_align_up(_end), npages);
}

View File

@@ -12,74 +12,3 @@
#include <l4/generic/cap-types.h> /* TODO: Move this to API */
#include <lib/malloc.h>
struct cap_list capability_list;
__initdata static struct capability *caparray;
__initdata static int total_caps = 0;
/* Copy all init-memory allocated capabilities */
void copy_boot_capabilities(struct initdata *initdata)
{
struct capability *cap;
for (int i = 0; i < total_caps; i++) {
cap = kzalloc(sizeof(struct capability));
/* This copies kernel-allocated unique cap id as well */
memcpy(cap, &caparray[i], sizeof(struct capability));
/* Initialize capability list */
link_init(&cap->list);
/* Add capability to global cap list */
list_insert(&capability_list.caps, &cap->list);
}
}
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;
}
total_caps = ncaps;
/* 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

@@ -589,8 +589,6 @@ int vfs_write(unsigned long vnum, unsigned long file_offset,
return ret;
}
/* Writes updated file stats back to vfs. (e.g. new file size) */
int vfs_update_file_stats(struct vm_file *f)
{

View File

@@ -3,15 +3,20 @@
*
* Copyright (C) 2007, 2008 Bahadir Balban
*/
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <mm/alloc_page.h>
#include <lib/malloc.h>
#include <lib/bit.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/arch/syslib.h>
#include <l4lib/utcb.h>
#include <l4/lib/list.h>
#include <l4/generic/cap-types.h> /* TODO: Move this to API */
#include <l4/api/capability.h>
#include <stdio.h>
#include <string.h>
#include <mm/alloc_page.h>
#include <lib/malloc.h>
#include <lib/bit.h>
#include <task.h>
#include <shm.h>
#include <file.h>
@@ -21,22 +26,30 @@
#include <utcb.h>
#include <bootm.h>
#include <vfs.h>
#include <init.h>
#include <memory.h>
#include <capability.h>
/* A separate list than the generic file list that keeps just the boot files */
LINK_DECLARE(boot_file_list);
extern unsigned long _start_init[];
extern unsigned long _end_init[];
/* 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);
}
}
/* Physical memory descriptors */
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 */
/* Capability descriptor list */
struct cap_list capability_list;
__initdata static struct capability *caparray;
__initdata static int total_caps = 0;
void print_pfn_range(int pfn, int size)
{
@@ -45,36 +58,6 @@ void print_pfn_range(int pfn, int size)
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
@@ -133,115 +116,83 @@ int mm0_task_init(struct vm_file *f, unsigned long task_start,
return 0;
}
struct vm_file *initdata_next_bootfile(struct initdata *initdata)
/* Copy all init-memory allocated capabilities */
void copy_boot_capabilities()
{
struct vm_file *file, *n;
list_foreach_removable_struct(file, n,
&initdata->boot_file_list,
list) {
list_remove_init(&file->list);
return file;
struct capability *cap;
for (int i = 0; i < total_caps; i++) {
cap = kzalloc(sizeof(struct capability));
/* This copies kernel-allocated unique cap id as well */
memcpy(cap, &caparray[i], sizeof(struct capability));
/* Initialize capability list */
link_init(&cap->list);
/* Add capability to global cap list */
list_insert(&capability_list.caps, &cap->list);
}
return 0;
}
/*
* Reads boot files from init data, determines their task ids if they
* match with particular servers, and starts the tasks.
*/
int start_boot_tasks(struct initdata *initdata)
int read_pager_capabilities()
{
struct vm_file *file = 0, *fs0_file = 0, *mm0_file = 0, *n;
struct tcb *fs0_task;
struct svc_image *img;
struct task_ids ids;
struct link other_files;
int total = 0;
int ncaps;
int err;
link_init(&other_files);
/* 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;
}
total_caps = ncaps;
/* Separate out special server tasks and regular files */
do {
file = initdata_next_bootfile(initdata);
/* Allocate array of caps from boot memory */
caparray = alloc_bootmem(sizeof(struct capability) * ncaps, 0);
if (file) {
BUG_ON(file->type != VM_FILE_BOOTFILE);
img = file->priv_data;
if (img->name[0] == 'm' &&
img->name[1] == 'm' &&
img->name[2] == '0')
mm0_file = file;
else if (img->name[0] == 'f' &&
img->name[1] == 's' &&
img->name[2] == '0')
fs0_file = file;
else
list_insert(&file->list, &other_files);
} else
break;
} while (1);
if (!mm0_file || !fs0_file) {
printf("%s: FATAL: Could not find images for %s, and/or %s\n",
__PAGERNAME__, __PAGERNAME__, __VFSNAME__);
BUG();
/* 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;
}
/* MM0 needs partial initialisation since it's already running. */
// printf("%s: Initialising mm0 tcb.\n", __TASKNAME__);
ids.tid = PAGER_TID;
ids.spid = PAGER_TID;
ids.tgid = PAGER_TID;
if (mm0_task_init(mm0_file, INITTASK_AREA_START,
INITTASK_AREA_END, &ids) < 0)
BUG();
total++;
/* Initialise vfs with its predefined id */
ids.tid = VFS_TID;
ids.spid = VFS_TID;
ids.tgid = VFS_TID;
// printf("%s: Initialising fs0\n",__TASKNAME__);
BUG_ON((IS_ERR(fs0_task = boottask_exec(fs0_file, USER_AREA_START,
USER_AREA_END, &ids))));
total++;
/* Initialise other tasks */
list_foreach_removable_struct(file, n, &other_files, list) {
ids.tid = TASK_ID_INVALID;
ids.spid = TASK_ID_INVALID;
ids.tgid = TASK_ID_INVALID;
list_remove_init(&file->list);
BUG_ON(IS_ERR(boottask_exec(file, USER_AREA_START,
USER_AREA_END, &ids)));
total++;
}
if (!total) {
printf("%s: Could not start any tasks.\n",
__TASKNAME__);
BUG();
/* 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;
}
extern unsigned long _start_init[];
extern unsigned long _end_init[];
error:
BUG();
}
/*
* Copy all necessary data from initmem to real memory,
* release initdata and any init memory used
*/
void copy_release_initdata(struct initdata *initdata)
void release_initdata()
{
/*
* Copy boot capabilities to a list of
* real capabilities
*/
copy_boot_capabilities(initdata);
copy_boot_capabilities();
/* Free and unmap init memory:
*
@@ -255,48 +206,215 @@ void copy_release_initdata(struct initdata *initdata)
self_tid());
}
void init_mm(struct initdata *initdata)
static void init_page_map(struct page_bitmap *pmap, unsigned long pfn_start, unsigned long pfn_end)
{
/* Initialise the page and bank descriptors */
init_physmem_primary(initdata);
pmap->pfn_start = pfn_start;
pmap->pfn_end = pfn_end;
set_page_map(pmap, pfn_start, pfn_end - pfn_start, 0);
}
init_physmem_secondary(initdata, membank);
/*
* 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;
/* Initialise the page allocator on first bank. */
init_page_allocator(membank[0].free, membank[0].end);
/* Initialise the zero page */
init_devzero();
/* Initialise in-memory boot files */
init_boot_files(initdata);
if (shm_pool_init() < 0) {
printf("SHM initialisation failed.\n");
BUG();
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 (utcb_pool_init() < 0) {
printf("SHM initialisation failed.\n");
BUG();
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 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;
/* Test that page/phys macros work */
BUG_ON(phys_to_page(page_to_phys(&page_array[5])) != &page_array[5])
}
void init_pager(void)
/* Fills in the physmem structure with free physical memory information */
void init_physmem_primary()
{
unsigned long pfn_start, pfn_end, pfn_images_end = 0;
struct bootdesc *bootdesc = initdata.bootdesc;
/* Allocate page map structure */
initdata.page_map = alloc_bootmem(sizeof(struct page_bitmap) +
((initdata.physmem->end -
initdata.physmem->start)
>> 5) + 1, 0);
/* Initialise page map from physmem capability */
init_page_map(initdata.page_map,
initdata.physmem->start,
initdata.physmem->end);
/* 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(initdata.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);
}
void init_physmem(void)
{
init_physmem_primary();
init_physmem_secondary(membank);
init_page_allocator(membank[0].free, membank[0].end);
}
void init_execve(char *path)
{
/*
* Find executable, and execute it by creating a new process
* rather than replacing the current image (which is the pager!)
*/
}
/*
* To be removed later: This file copies in-memory elf image to the
* initialized and formatted in-memory memfs filesystem.
*/
void copy_init_process(void)
{
//int fd = sys_open(find_task(self_tid()), "/test0", O_WRITE, 0)
//sys_write(find_task(self_tid()), fd, __test0_start, __test0_end - __test0_start);
//sys_close(find_task(self_tid()), fd);
}
void start_init_process(void)
{
/* Copy raw test0 elf image from memory to memfs first */
copy_init_process();
init_execve("/test0");
}
void init(void)
{
read_pager_capabilities();
pager_address_pool_init();
read_kernel_capabilities(&initdata);
read_boot_params();
read_bootdesc(&initdata);
init_physmem();
init_mm(&initdata);
init_devzero();
start_boot_tasks(&initdata);
shm_pool_init();
copy_release_initdata(&initdata);
utcb_pool_init();
vfs_init();
start_init_process();
release_initdata();
mm0_test_global_vm_integrity();
}

View File

@@ -19,157 +19,4 @@
#include <physmem.h>
#include <bootm.h>
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(struct page_bitmap *pmap, unsigned long pfn_start, unsigned long pfn_end)
{
pmap->pfn_start = pfn_start;
pmap->pfn_end = pfn_end;
set_page_map(pmap, 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;
/* Test that page/phys macros work */
BUG_ON(phys_to_page(page_to_phys(&page_array[5])) != &page_array[5])
}
/* 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;
/* Allocate page map structure */
initdata->page_map = alloc_bootmem(sizeof(struct page_bitmap) +
((initdata->physmem->end -
initdata->physmem->start)
>> 5) + 1, 0);
/* Initialise page map from physmem capability */
init_page_map(initdata->page_map,
initdata->physmem->start,
initdata->physmem->end);
/* 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(initdata->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

@@ -0,0 +1,46 @@
# -*- mode: python; coding: utf-8; -*-
# Codezero -- a microkernel for embedded systems.
#
# Copyright © 2009 B Labs Ltd
import os.path
import sys, subprocess, shutil
from os.path import *
Import('config', 'environment', 'previmage')
e = environment.Clone()
sys.path.append('../../../')
from config.projpaths import *
from config.configuration import *
from tools.pyelf.lmanext import *
rootfs_lds_in = \
'''
/*
* Linker script that embeds an empty root filesystem.
* This is to be replaced by a real rootfs image later.
*/
SECTIONS
{
. = %s;
.bss : { *(.bss) }
}
'''
def generate_rootfs_lds(target, source, env):
with open(source[1].path, 'r') as lds_in:
with open(target[0].path, 'w+') as lds_out:
linker_script = lds_in.read()
lds_out.write(linker_script % next_available_lma(source[0].path))
rootfs_lds = e.Command('rootfs.lds', [previmage, 'rootfs.lds.in'], generate_rootfs_lds)
e.Append(LINKFLAGS = '-T' + rootfs_lds[0].path)
rootfs_img = e.Program('rootfs.elf', 'rootfs.c')
Depends(rootfs_img, rootfs_lds)
Return('rootfs_img')

View File

@@ -0,0 +1,2 @@
SECTION(".bss") char empty_image[SZ_4MB];

View File

@@ -0,0 +1,9 @@
/*
* Linker script that embeds an empty root filesystem.
* This is to be replaced by a real rootfs image later.
*/
SECTIONS
{
. = %s;
.bss : { *(.bss) }
}

View File

@@ -118,7 +118,7 @@ int main(void)
load_container_images((unsigned long)_start_containers,
(unsigned long)_end_containers);
printf("elf-loader:\tkernel entry point is %lx\n", *kernel_entry);
printf("elf-loader:\tkernel entry point is 0x%lx\n", *kernel_entry);
arch_start_kernel(kernel_entry);
printf("elf-loader:\tKernel start failed! Looping endless.\n");