diff --git a/README b/README index c846443..6e37d45 100644 --- a/README +++ b/README @@ -101,8 +101,8 @@ irrelevant to a new problem, and embedded systems tend to raise new problems often. Codezero is written from scratch to solely target embedded systems and as such the source code is %100 relevant. It is small and free from legacy code. -From a design perspective, due to these kernels having a monolithic design, they -may have issues with dependability due to much of the code sharing the same +From a design perspective, these kernels have a monolithic design, and as such +they may have issues with dependability due to much of the code sharing the same address space. This is an important issue on embedded systems since their operation is more sensitive to disruptions. Being a microkernel design, Codezero aims to defeat this problem and increase dependability. @@ -112,9 +112,9 @@ embedded devices. Most of them are proprietary, with their own users. Some of them are structurally too simplistic, and lack modern features such as paging. There ones that are well established, but Codezero will contrast them by providing an alternative that will follow the open source development principles -more closely. Many embedded systems still use older development methods and the -right open source methodology would prove favorable in the fast-paced nature of -development. +more closely. Many embedded software projects still use older development +methods and the right open source methodology would prove favorable in the +fast-paced nature of development. Finally, there are new ideas in literature that would improve systems software but aren't implemented either because they have no existing users or may break @@ -128,13 +128,13 @@ opportunity to incorporate the latest ideas in OS technology. Can you summarise all this? Why should I use Codezero, again? Codezero is an operating system that targets embedded systems. It supports the -most fundamental posix system calls. Different from other posix-like systems, +most fundamental posix features. Different from other posix-like systems, it is based on a microkernel design. It supports modern features such as demand-paging, virtual filesystem support. It has a cleanly separated set of -services, and it is small. Therefore it is a good candidate as systems software -to be used on embedded systems. Currently it has little or no users, and yet it -is about to become usable, therefore compared to systems with a saturated user -base it is possible to tailor it rapidly towards the needs of any users who want -to be the first to use it. +services, and it is small. For these reasons it is a good candidate as systems +software to be used on embedded systems. Currently it has little or no users, +therefore compared to systems with a saturated user base it is possible to +tailor it rapidly towards the needs of any users who want to be the first to +incorporate it to their needs. diff --git a/src/arch/arm/exception.c b/src/arch/arm/exception.c index 5e7d8fa..76ec162 100644 --- a/src/arch/arm/exception.c +++ b/src/arch/arm/exception.c @@ -17,7 +17,7 @@ #include INC_SUBARCH(mm.h) /* Abort debugging conditions */ -//#define DEBUG_ABORTS +// #define DEBUG_ABORTS #if defined (DEBUG_ABORTS) #define dbg_abort(...) dprintk(__VA_ARGS__) #else diff --git a/tasks/mm0/include/vm_area.h b/tasks/mm0/include/vm_area.h index 6e40343..203436b 100644 --- a/tasks/mm0/include/vm_area.h +++ b/tasks/mm0/include/vm_area.h @@ -14,6 +14,13 @@ #include #include +// #define DEBUG_FAULT_HANDLING +#ifdef DEBUG_FAULT_HANDLING +#define dprintf(...) printf(__VA_ARGS__) +#else +#define dprintf(...) +#endif + /* Protection flags */ #define VM_NONE (1 << 0) #define VM_READ (1 << 1) diff --git a/tasks/mm0/src/arch-arm/mm.c b/tasks/mm0/src/arch-arm/mm.c index c0f75ad..bffe25e 100644 --- a/tasks/mm0/src/arch-arm/mm.c +++ b/tasks/mm0/src/arch-arm/mm.c @@ -3,6 +3,7 @@ */ #include #include +#include /* Extracts generic protection flags from architecture-specific pte */ unsigned int vm_prot_flags(pte_t pte) @@ -24,6 +25,18 @@ unsigned int vm_prot_flags(pte_t pte) return vm_prot_flags; } +#if defined(DEBUG_FAULT_HANDLING) +void print_fault_params(struct fault_data *fault) +{ + printf("%s: Handling %s fault (%s abort) from %d. fault @ 0x%x\n", + __TASKNAME__, (fault->reason & VM_READ) ? "read" : "write", + is_prefetch_abort(fault->kdata->fsr) ? "prefetch" : "data", + fault->task->tid, fault->address); +} +#else +void print_fault_params(struct fault_data *fault) { } +#endif + /* * PTE STATES: @@ -52,9 +65,6 @@ void set_generic_fault_params(struct fault_data *fault) else BUG(); } - printf("%s: Handling %s fault (%s abort) from %d. fault @ 0x%x\n", - __TASKNAME__, (fault->reason & VM_READ) ? "read" : "write", - is_prefetch_abort(fault->kdata->fsr) ? "prefetch" : "data", - fault->task->tid, fault->address); + print_fault_params(fault); } diff --git a/tasks/mm0/src/fault.c b/tasks/mm0/src/fault.c index 604ca91..afaeeb8 100644 --- a/tasks/mm0/src/fault.c +++ b/tasks/mm0/src/fault.c @@ -19,13 +19,6 @@ #include #include -#define DEBUG_FAULT_HANDLING -#ifdef DEBUG_FAULT_HANDLING -#define dprint(...) printf(__VA_ARGS__) -#else -#define dprint(...) -#endif - unsigned long fault_to_file_offset(struct fault_data *fault) { /* Fault's offset in its vma */ @@ -284,8 +277,6 @@ int copy_on_write(struct fault_data *fault) __TASKNAME__, __FUNCTION__); BUG(); } - printf("Top object:\n"); - vm_object_print(vmo_link->obj); /* Is the object read-only? Create a shadow object if so. * @@ -298,7 +289,7 @@ int copy_on_write(struct fault_data *fault) if (!(vmo_link->obj->flags & VM_WRITE)) { if (!(shadow_link = vma_create_shadow())) return -ENOMEM; - printf("%s: Created a shadow.\n", __TASKNAME__); + dprintf("%s: Created a shadow.\n", __TASKNAME__); /* Initialise the shadow */ shadow = shadow_link->obj; shadow->refcnt = 1; @@ -322,7 +313,7 @@ int copy_on_write(struct fault_data *fault) /* Shadow is the copier object */ copier_link = shadow_link; } else { - printf("No shadows. Going to add to topmost r/w shadow object\n"); + dprintf("No shadows. Going to add to topmost r/w shadow object\n"); /* No new shadows, the topmost r/w vmo is the copier object */ copier_link = vmo_link; @@ -336,7 +327,7 @@ int copy_on_write(struct fault_data *fault) } /* Traverse the list of read-only vm objects and search for the page */ - while (!(page = vmo_link->obj->pager->ops.page_in(vmo_link->obj, + while (IS_ERR(page = vmo_link->obj->pager->ops.page_in(vmo_link->obj, file_offset))) { if (!(vmo_link = vma_next_link(&vmo_link->list, &vma->vm_obj_list))) { @@ -372,8 +363,8 @@ int copy_on_write(struct fault_data *fault) (void *)page_align(fault->address), 1, (reason & VM_READ) ? MAP_USR_RO_FLAGS : MAP_USR_RW_FLAGS, fault->task->tid); - printf("%s: Mapped 0x%x as writable to tid %d.\n", __TASKNAME__, - page_align(fault->address), fault->task->tid); + dprintf("%s: Mapped 0x%x as writable to tid %d.\n", __TASKNAME__, + page_align(fault->address), fault->task->tid); vm_object_print(new_page->owner); /* @@ -419,22 +410,31 @@ int __do_page_fault(struct fault_data *fault) struct vm_area *vma = fault->vma; unsigned long file_offset; struct vm_obj_link *vmo_link; - struct vm_object *vmo; struct page *page; /* Handle read */ if ((reason & VM_READ) && (pte_flags & VM_NONE)) { file_offset = fault_to_file_offset(fault); - BUG_ON(!(vmo_link = vma_next_link(&vma->vm_obj_list, - &vma->vm_obj_list))); - vmo = vmo_link->obj; - /* Get the page from its pager */ - if (IS_ERR(page = vmo->pager->ops.page_in(vmo, file_offset))) { - printf("%s: Could not obtain faulty page.\n", - __TASKNAME__); + /* Get the first object, either original file or a shadow */ + if (!(vmo_link = vma_next_link(&vma->vm_obj_list, &vma->vm_obj_list))) { + printf("%s:%s: No vm object in vma!\n", + __TASKNAME__, __FUNCTION__); BUG(); } + + /* Traverse the list of read-only vm objects and search for the page */ + while (IS_ERR(page = vmo_link->obj->pager->ops.page_in(vmo_link->obj, + file_offset))) { + if (!(vmo_link = vma_next_link(&vmo_link->list, + &vma->vm_obj_list))) { + printf("%s:%s: Traversed all shadows and the original " + "file's vm_object, but could not find the " + "faulty page in this vma.\n",__TASKNAME__, + __FUNCTION__); + BUG(); + } + } BUG_ON(!page); /* Map it to faulty task */ @@ -442,17 +442,17 @@ int __do_page_fault(struct fault_data *fault) (void *)page_align(fault->address), 1, (reason & VM_READ) ? MAP_USR_RO_FLAGS : MAP_USR_RW_FLAGS, fault->task->tid); - printf("%s: Mapped 0x%x as readable to tid %d.\n", __TASKNAME__, - page_align(fault->address), fault->task->tid); - vm_object_print(vmo); + dprintf("%s: Mapped 0x%x as readable to tid %d.\n", __TASKNAME__, + page_align(fault->address), fault->task->tid); + vm_object_print(vmo_link->obj); } /* Handle write */ if ((reason & VM_WRITE) && (pte_flags & VM_READ)) { /* Copy-on-write */ - if (vma_flags & VMA_PRIVATE) { + if (vma_flags & VMA_PRIVATE) copy_on_write(fault); - } + /* Regular files */ if ((vma_flags & VMA_SHARED) && !(vma_flags & VMA_ANONYMOUS)) { /* No regular files are mapped yet */ @@ -460,10 +460,10 @@ int __do_page_fault(struct fault_data *fault) file_offset = fault_to_file_offset(fault); BUG_ON(!(vmo_link = vma_next_link(&vma->vm_obj_list, &vma->vm_obj_list))); - vmo = vmo_link->obj; /* Get the page from its pager */ - if (IS_ERR(page = vmo->pager->ops.page_in(vmo, file_offset))) { + if (IS_ERR(page = vmo_link->obj->pager->ops.page_in(vmo_link->obj, + file_offset))) { printf("%s: Could not obtain faulty page.\n", __TASKNAME__); BUG(); @@ -475,11 +475,16 @@ int __do_page_fault(struct fault_data *fault) (void *)page_align(fault->address), 1, (reason & VM_READ) ? MAP_USR_RO_FLAGS : MAP_USR_RW_FLAGS, fault->task->tid); - printf("%s: Mapped 0x%x as writable to tid %d.\n", __TASKNAME__, - page_align(fault->address), fault->task->tid); - vm_object_print(vmo); + dprintf("%s: Mapped 0x%x as writable to tid %d.\n", __TASKNAME__, + page_align(fault->address), fault->task->tid); + vm_object_print(vmo_link->obj); } /* FIXME: Just do fs files for now, anon shm objects later. */ + /* Things to think about: + * - Is utcb a shm memory really? Then each task must map it in via + * shmget(). FS0 must map all user tasks' utcb via shmget() as well. + * For example to pass on pathnames etc. + */ BUG_ON((vma_flags & VMA_SHARED) && (vma_flags & VMA_ANONYMOUS)); } diff --git a/tasks/mm0/src/vm_object.c b/tasks/mm0/src/vm_object.c index cd99edf..fa442db 100644 --- a/tasks/mm0/src/vm_object.c +++ b/tasks/mm0/src/vm_object.c @@ -9,13 +9,23 @@ #include +// #define DEBUG_FAULT_HANDLING +#ifdef DEBUG_FAULT_HANDLING +#define dprintf(...) printf(__VA_ARGS__) +#else +#define dprintf(...) +#endif + +#if defined(DEBUG_FAULT_HANDLING) void print_cache_pages(struct vm_object *vmo) { struct page *p; - printf("Pages:\n======\n"); + if (!list_empty(&vmo->page_cache)) + printf("Pages:\n======\n"); + list_for_each_entry(p, &vmo->page_cache, list) { - printf("Page offset: 0x%x, virtual: 0x%x, refcnt: %d\n", p->offset, + dprintf("Page offset: 0x%x, virtual: 0x%x, refcnt: %d\n", p->offset, p->virtual, p->refcnt); } } @@ -38,6 +48,10 @@ void vm_object_print(struct vm_object *vmo) print_cache_pages(vmo); printf("\n"); } +#else +void print_cache_pages(struct vm_object *vmo) { } +void vm_object_print(struct vm_object *vmo) { } +#endif /* Global list of in-memory vm objects. */ LIST_HEAD(vm_object_list);