mirror of
https://github.com/drasko/codezero.git
synced 2026-01-20 23:03:16 +01:00
Few more fixes.
Boot files and tasks are now initialised together. Theads can ask for particular space and thread ids, if they're unused. This enables us to get predefined ids for known tasks such as the VFS task. Fixes to README Other minor fixes.
This commit is contained in:
20
README
20
README
@@ -33,8 +33,8 @@ the project is written from scratch, so the name emphasises that.
|
||||
|
||||
Design & Features:
|
||||
|
||||
Codezero microkernel: Based on L4 microkernel principles, there are only a few
|
||||
system calls and the microkernel provides purely mechanism; threads and address
|
||||
Based on L4 microkernel principles, there are only a few system calls in
|
||||
Codezero. These system calls provide purely mechanism; threads and address
|
||||
spaces, and the methods of inter-process communication between them. Anything
|
||||
beyond these are policy and they are implemented in the userspace. Due to this
|
||||
rigorously simple design the same microkernel can be used to design completely
|
||||
@@ -42,13 +42,13 @@ different operating systems. In terms of other features, the microkernel is
|
||||
preemptive, and smp-ready. Currently only synchronous communication is
|
||||
implemented, but this will change in the near future.
|
||||
|
||||
MM0: Implements memory management. It contains memory and page allocators. It
|
||||
implements demand paging by managing page faults, physical pages and their
|
||||
file/task associations.
|
||||
MM0 is the systm task that implements memory management. It contains memory and
|
||||
page allocators. It implements demand paging by managing page faults, physical
|
||||
pages and their file/task associations.
|
||||
|
||||
FS0: Implements a simple, modern virtual filesystem layer. Since it abstracts
|
||||
the low-level filesystem details, it is a relatively easy job to port a new
|
||||
filesystem to be used under FS0.
|
||||
FS0 is the system task implements a simple, modern virtual filesystem layer.
|
||||
Since it abstracts the low-level filesystem details, it is a relatively easy job
|
||||
to port a new filesystem to be used under FS0.
|
||||
|
||||
|
||||
License:
|
||||
@@ -65,9 +65,9 @@ party source code is open source in the OSI definition. Please check these
|
||||
directories for their respective licenses.
|
||||
|
||||
|
||||
Why yet another Posix (micro) kernel?
|
||||
Why yet another POSIX microkernel?
|
||||
|
||||
There are many open source Posix operating systems with advanced features such
|
||||
There are many open source POSIX operating systems with advanced features such
|
||||
as *BSD and Linux. However these were originally not designed for embedded
|
||||
systems. Unix itself and all the tools built upon weren't meant for using on
|
||||
small devices. Accordingly, these operating systems contain a lot of historical
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
unsigned int __clz(unsigned int bitvector);
|
||||
int find_and_set_first_free_bit(u32 *word, unsigned int lastbit);
|
||||
int check_and_clear_bit(u32 *word, int bit);
|
||||
int check_and_set_bit(u32 *word, int bit);
|
||||
|
||||
|
||||
/* Set */
|
||||
|
||||
@@ -11,5 +11,6 @@ struct id_pool {
|
||||
struct id_pool *id_pool_new_init(int mapsize);
|
||||
int id_new(struct id_pool *pool);
|
||||
int id_del(struct id_pool *pool, int id);
|
||||
int id_get(struct id_pool *pool, int id);
|
||||
|
||||
#endif /* __IDPOOL_H__ */
|
||||
|
||||
@@ -83,11 +83,29 @@ int thread_create(struct task_ids *ids)
|
||||
copy_pgd_kern_all(new->pgd);
|
||||
|
||||
/* Get new space id */
|
||||
ids->spid = id_new(space_id_pool);
|
||||
if (ids->spid == TASK_ID_INVALID) {
|
||||
ids->spid = id_new(space_id_pool);
|
||||
printk("Got new space id: %d\n", ids->spid);
|
||||
} else {
|
||||
printk("Try new space id: %d\n", ids->spid);
|
||||
if ((ids->spid = id_get(space_id_pool, ids->spid)) < 0)
|
||||
ids->spid = id_new(space_id_pool);
|
||||
else
|
||||
printk("Success.\n");
|
||||
}
|
||||
|
||||
spc_found:
|
||||
/* Get a new thread id */
|
||||
ids->tid = id_new(thread_id_pool);
|
||||
if (ids->tid == TASK_ID_INVALID) {
|
||||
ids->tid = id_new(thread_id_pool);
|
||||
printk("Got new thread id: %d\n", ids->tid);
|
||||
} else {
|
||||
printk("Try new thread id: %d\n", ids->tid);
|
||||
if ((ids->tid = id_get(thread_id_pool, ids->tid)) < 0)
|
||||
ids->tid = id_new(thread_id_pool);
|
||||
else
|
||||
printk("Success.\n");
|
||||
}
|
||||
|
||||
/* Set all ids */
|
||||
set_task_ids(new, ids);
|
||||
|
||||
@@ -250,7 +250,7 @@ void switch_to_user(struct ktcb *task)
|
||||
jump(task);
|
||||
}
|
||||
|
||||
void init_inittask(char *name, struct task_ids *ids)
|
||||
void init_pager(char *name, struct task_ids *ids)
|
||||
{
|
||||
struct svc_image *taskimg = 0;
|
||||
struct ktcb *task;
|
||||
@@ -262,7 +262,7 @@ void init_inittask(char *name, struct task_ids *ids)
|
||||
* This also solves the problem of freeing the bootstack and making use
|
||||
* of the initial kspace pgd.
|
||||
*/
|
||||
if (!strcmp(name, "mm0"))
|
||||
if (!strcmp(name, __PAGERNAME__))
|
||||
task = current; /* mm0 is the mockup current during init */
|
||||
else
|
||||
task = (struct ktcb *)zalloc_page();
|
||||
@@ -341,7 +341,7 @@ void init_tasks()
|
||||
* This must come last so that other tasks can copy its pgd before it
|
||||
* modifies it for its own specifics.
|
||||
*/
|
||||
init_inittask("mm0", &ids);
|
||||
init_pager(__PAGERNAME__, &ids);
|
||||
}
|
||||
|
||||
void start_kernel(void)
|
||||
|
||||
@@ -50,3 +50,15 @@ int check_and_clear_bit(u32 *word, int bit)
|
||||
}
|
||||
}
|
||||
|
||||
int check_and_set_bit(u32 *word, int bit)
|
||||
{
|
||||
/* Check that bit was clear */
|
||||
if (!(word[BITWISE_GETWORD(bit)] & BITWISE_GETBIT(bit))) {
|
||||
word[BITWISE_GETWORD(bit)] |= BITWISE_GETBIT(bit);
|
||||
return 0;
|
||||
} else {
|
||||
//printf("Trying to set already set bit\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,3 +33,14 @@ int id_del(struct id_pool *pool, int id)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return a specific id, if available */
|
||||
int id_get(struct id_pool *pool, int id)
|
||||
{
|
||||
int ret = check_and_set_bit(pool->bitmap, id);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ static inline struct superblock *vfs_alloc_superblock(void)
|
||||
{
|
||||
struct superblock *sb = kmalloc(sizeof(struct superblock));
|
||||
INIT_LIST_HEAD(&sb->list);
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <init.h>
|
||||
#include <fs.h>
|
||||
#include <vfs.h>
|
||||
#include <task.h>
|
||||
#include <stdio.h>
|
||||
#include <memfs/memfs.h>
|
||||
#include <memfs/vnode.h>
|
||||
#include <lib/idpool.h>
|
||||
@@ -138,11 +140,16 @@ struct superblock *memfs_get_superblock(void *block)
|
||||
struct memfs_superblock *sb = block;
|
||||
struct superblock *vfs_sb;
|
||||
|
||||
printf("%s: %s: Reading superblock.\n", __TASKNAME__, __FUNCTION__);
|
||||
/* We don't do sanity checks here, just confirm id. */
|
||||
if (!strcmp(sb->name, "memfs"))
|
||||
if (strcmp(sb->name, "memfs")) {
|
||||
printf("%s: Name does not match: %s\n", __FUNCTION__, sb->name);
|
||||
return 0;
|
||||
if (sb->magic != MEMFS_MAGIC)
|
||||
}
|
||||
if (sb->magic != MEMFS_MAGIC) {
|
||||
printf("%s: Magic number not match: %s\n", __FUNCTION__, sb->magic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate a vfs superblock. */
|
||||
vfs_sb = vfs_alloc_superblock();
|
||||
@@ -154,6 +161,10 @@ struct superblock *memfs_get_superblock(void *block)
|
||||
/* Registers sfs as an available filesystem type */
|
||||
void memfs_register_fstype(struct list_head *fslist)
|
||||
{
|
||||
/* Initialise superblock list for this fstype */
|
||||
INIT_LIST_HEAD(&memfs_fstype.sblist);
|
||||
|
||||
/* Add this fstype to list of available fstypes. */
|
||||
list_add(&memfs_fstype.list, fslist);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
#include INC_ARCH(bootdesc.h)
|
||||
#include <vm_area.h>
|
||||
|
||||
#define BOOTDESC_IMAGE_START 1
|
||||
|
||||
struct initdata {
|
||||
struct bootdesc *bootdesc;
|
||||
struct list_head boot_file_list;
|
||||
|
||||
@@ -34,7 +34,7 @@ void handle_requests(void)
|
||||
u32 tag;
|
||||
int err;
|
||||
|
||||
printf("%s: Initiating ipc.\n", __TASKNAME__);
|
||||
// printf("%s: Initiating ipc.\n", __TASKNAME__);
|
||||
if ((err = l4_receive(L4_ANYTHREAD)) < 0) {
|
||||
printf("%s: %s: IPC Error: %d. Quitting...\n", __TASKNAME__,
|
||||
__FUNCTION__, err);
|
||||
@@ -55,7 +55,7 @@ void handle_requests(void)
|
||||
* A thread that wants to sync with us would have
|
||||
* started here.
|
||||
*/
|
||||
printf("%s: Synced with waiting thread.\n", __TASKNAME__);
|
||||
// printf("%s: Synced with waiting thread.\n", __TASKNAME__);
|
||||
break;
|
||||
|
||||
case L4_IPC_TAG_PFAULT:
|
||||
|
||||
@@ -50,44 +50,13 @@ void init_mm(struct initdata *initdata)
|
||||
l4_kmem_grant(__pfn(alloc_page(__pfn(SZ_1MB))), __pfn(SZ_1MB));
|
||||
}
|
||||
|
||||
/* Create temporary run-time files in memory to test with mmap */
|
||||
void init_boot_files(struct initdata *initdata)
|
||||
{
|
||||
struct vm_file *f;
|
||||
struct svc_image *img;
|
||||
struct bootdesc *bd = initdata->bootdesc;
|
||||
|
||||
INIT_LIST_HEAD(&initdata->boot_file_list);
|
||||
for (int i = BOOTDESC_IMAGE_START; i < bd->total_images; i++) {
|
||||
img = &bd->images[i];
|
||||
if (!(!strcmp(img->name, "fs0") || !strcmp(img->name, "test0")))
|
||||
continue; /* Img is not what we want */
|
||||
|
||||
f = kzalloc(sizeof(*f));
|
||||
INIT_LIST_HEAD(&f->list);
|
||||
INIT_LIST_HEAD(&f->page_cache_list);
|
||||
list_add(&f->list, &initdata->boot_file_list);
|
||||
|
||||
/*
|
||||
* For boot files, we use the physical address of the memory
|
||||
* file as its inode.
|
||||
*/
|
||||
f->inode.i_addr = img->phys_start;
|
||||
f->length = img->phys_end - img->phys_start;
|
||||
f->pager = &default_file_pager;
|
||||
}
|
||||
}
|
||||
|
||||
void initialise(void)
|
||||
{
|
||||
request_initdata(&initdata);
|
||||
|
||||
init_mm(&initdata);
|
||||
|
||||
init_boot_files(&initdata);
|
||||
// printf("INITTASK: Initialised mock-up bootfiles.\n");
|
||||
|
||||
init_pm(&initdata);
|
||||
// printf("INITTASK: Initialised the memory/process manager.\n");
|
||||
printf("%s: Initialised the memory/process manager.\n", __TASKNAME__);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <l4/types.h>
|
||||
#include <l4/lib/list.h>
|
||||
#include <l4/api/thread.h>
|
||||
#include <l4/api/kip.h>
|
||||
#include INC_GLUE(memory.h)
|
||||
#include <l4lib/arch/syscalls.h>
|
||||
#include <l4lib/arch/syslib.h>
|
||||
@@ -72,17 +73,62 @@ struct tcb *create_init_tcb(struct tcb_head *tcbs)
|
||||
return task;
|
||||
}
|
||||
|
||||
/* Create temporary run-time files in memory to test with mmap */
|
||||
struct vm_file *create_init_vmfile(struct list_head *vmfile_head)
|
||||
{
|
||||
struct vm_file *file = kzalloc(sizeof(*file));
|
||||
|
||||
INIT_LIST_HEAD(&file->list);
|
||||
INIT_LIST_HEAD(&file->page_cache_list);
|
||||
list_add(&file->list, vmfile_head);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs)
|
||||
{
|
||||
struct vm_file *file;
|
||||
int err;
|
||||
struct vm_file *file;
|
||||
struct svc_image *img;
|
||||
unsigned int sp, pc;
|
||||
struct tcb *task;
|
||||
struct task_ids ids;
|
||||
struct bootdesc *bd = initdata->bootdesc;
|
||||
|
||||
INIT_LIST_HEAD(&tcb_head.list);
|
||||
list_for_each_entry(file, &initdata->boot_file_list, list) {
|
||||
struct tcb *task = create_init_tcb(tcbs);
|
||||
unsigned int sp = align(USER_AREA_END - 1, 8);
|
||||
unsigned int pc = USER_AREA_START;
|
||||
struct task_ids ids = { .tid = task->tid, .spid = task->spid };
|
||||
INIT_LIST_HEAD(&initdata->boot_file_list);
|
||||
|
||||
for (int i = 0; i < bd->total_images; i++) {
|
||||
img = &bd->images[i];
|
||||
|
||||
/* Skip self */
|
||||
if (!strcmp(img->name, __PAGERNAME__))
|
||||
continue;
|
||||
|
||||
/* Set up task ids */
|
||||
if (!strcmp(img->name, __VFSNAME__)) {
|
||||
ids.tid = VFS_TID;
|
||||
ids.spid = VFS_TID;
|
||||
} else {
|
||||
ids.tid = -1;
|
||||
ids.spid = -1;
|
||||
}
|
||||
|
||||
/* Set up task's registers */
|
||||
sp = align(USER_AREA_END - 1, 8);
|
||||
pc = USER_AREA_START;
|
||||
|
||||
/* Create vm file and tcb */
|
||||
file = create_init_vmfile(&initdata->boot_file_list);
|
||||
task = create_init_tcb(tcbs);
|
||||
|
||||
/*
|
||||
* For boot files, we use the physical address of the memory
|
||||
* file as its mock-up inode.
|
||||
*/
|
||||
file->inode.i_addr = img->phys_start;
|
||||
file->length = img->phys_end - img->phys_start;
|
||||
file->pager = &default_file_pager;
|
||||
|
||||
/* mmap each task's physical image to task's address space. */
|
||||
if ((err = do_mmap(file, 0, task, USER_AREA_START,
|
||||
@@ -102,7 +148,7 @@ int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs)
|
||||
/* mmap each task's utcb as single page anonymous memory. */
|
||||
if ((err = do_mmap(0, 0, task, (unsigned long)__L4_ARM_Utcb(),
|
||||
VM_READ | VM_WRITE | VMA_ANON, 1) < 0)) {
|
||||
printf("do_mmap: Mapping stack failed with %d.\n", err);
|
||||
printf("do_mmap: Mapping utcb failed with %d.\n", err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -113,8 +159,8 @@ int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs)
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf("New task with id: %d, space id: %d\n", ids.tid, ids.spid);
|
||||
/* Use returned space and thread ids. */
|
||||
printf("New task with id: %d, space id: %d\n", ids.tid, ids.spid);
|
||||
task->tid = ids.tid;
|
||||
task->spid = ids.spid;
|
||||
|
||||
@@ -154,7 +200,9 @@ void send_task_data(l4id_t requester)
|
||||
int li, err;
|
||||
|
||||
if (requester != VFS_TID) {
|
||||
printf("Task data is not requested by FS0, ignoring.\n");
|
||||
printf("%s: Task data requested by %d, which is not "
|
||||
"FS0 id %d, ignoring.\n", __TASKNAME__, requester,
|
||||
VFS_TID);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
void wait_pager(l4id_t partner)
|
||||
{
|
||||
printf("%s: Syncing with pager.\n", __TASKNAME__);
|
||||
// printf("%s: Syncing with pager.\n", __TASKNAME__);
|
||||
for (int i = 0; i < 6; i++)
|
||||
write_mr(i, i);
|
||||
l4_send(partner, L4_IPC_TAG_WAIT);
|
||||
printf("Pager synced with us.\n");
|
||||
// printf("Pager synced with us.\n");
|
||||
}
|
||||
|
||||
void main(void)
|
||||
|
||||
Reference in New Issue
Block a user