aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex.auvolat@ens.fr>2014-12-06 20:30:32 +0100
committerAlex Auvolat <alex.auvolat@ens.fr>2014-12-06 20:30:32 +0100
commit0b5d6568c468075b6c1a2de065332b270345611b (patch)
treed2b9debc6eb90c5a43cac5aefd35d1550fe7b11b
parentb38d90b5cacee9bfc775f1fa4b31c5863654c5e8 (diff)
downloadkogata-0b5d6568c468075b6c1a2de065332b270345611b.tar.gz
kogata-0b5d6568c468075b6c1a2de065332b270345611b.zip
Refactor PF handlers and region freeing functions.
-rw-r--r--kernel/include/region.h17
-rw-r--r--kernel/l0/kmain.c35
-rw-r--r--kernel/l0/paging.c1
-rw-r--r--kernel/l0/region.c82
4 files changed, 87 insertions, 48 deletions
diff --git a/kernel/include/region.h b/kernel/include/region.h
index bc26bfe..4bc8917 100644
--- a/kernel/include/region.h
+++ b/kernel/include/region.h
@@ -8,9 +8,10 @@
// Region types
#define REGION_T_KERNEL_BASE 0x00000001 // base kernel code & data
#define REGION_T_DESCRIPTORS 0x00000002 // contains more region descriptors
-#define REGION_T_PAGETABLE 0x00000010 // used to map a page table/page directory
#define REGION_T_CORE_HEAP 0x00000100 // used for the core kernel heap
-#define REGION_T_PROC_HEAP 0x00000200 // used for a kernel process' heap
+#define REGION_T_KPROC_HEAP 0x00000200 // used for a kernel process' heap
+#define REGION_T_KPROC_STACK 0x00000400 // used for a kernel process' heap
+#define REGION_T_PROC_KSTACK 0x00000800 // used for a process' kernel heap
#define REGION_T_CACHE 0x00001000 // used for cache
#define REGION_T_HW 0x00002000 // used for hardware access
@@ -30,4 +31,16 @@ void* region_alloc(size_t size, uint32_t type, page_fault_handler_t pf); // retu
region_info_t *find_region(void* addr);
void region_free(void* addr);
+// some usefull PF handlers
+// stack_pf_handler : allocates new frames and panics on access to first page of region (stack overflow)
+void stack_pf_handler(pagedir_t *pd, struct region_info *r, void* addr);
+// default_allocator_pf_handler : just allocates new frames on page faults
+void default_allocator_pf_handler(pagedir_t *pd, struct region_info *r, void* addr);
+
+// some functions for freeing regions and frames
+// region_free_unmap_free : deletes a region and frees all frames that were mapped in it
+void region_free_unmap_free(void* addr);
+// region_free_unmap : deletes a region and unmaps all frames that were mapped in it, without freeing them
+void region_free_unmap(void* addr);
+
void dbg_print_region_stats();
diff --git a/kernel/l0/kmain.c b/kernel/l0/kmain.c
index 53afb6b..63ed6ac 100644
--- a/kernel/l0/kmain.c
+++ b/kernel/l0/kmain.c
@@ -18,39 +18,12 @@ void breakpoint_handler(registers_t *regs) {
BOCHS_BREAKPOINT;
}
-void test_pf_handler(pagedir_t *pd, region_info_t *i, void* addr) {
- dbg_printf(" {0x%p", addr);
-
- uint32_t f = frame_alloc(1);
- if (f == 0) PANIC("Out Of Memory");
- dbg_printf(" -> %i} ", f);
-
- int error = pd_map_page(addr, f, 1);
- if (error) PANIC("Could not map frame (OOM)");
-}
-
void* page_alloc_fun_for_kmalloc(size_t bytes) {
- void* addr = region_alloc(bytes, REGION_T_CORE_HEAP, test_pf_handler);
+ void* addr = region_alloc(bytes, REGION_T_CORE_HEAP, default_allocator_pf_handler);
dbg_printf("[alloc 0x%p for kmalloc : %p]\n", bytes, addr);
return addr;
}
-void page_free_fun_for_kmalloc(void* ptr) {
- dbg_printf("[Free 0x%p", ptr);
-
- region_info_t *i = find_region(ptr);
- ASSERT(i != 0 && i->type == REGION_T_CORE_HEAP);
- for (void* x = i->addr; x < i->addr + i->size; x += PAGE_SIZE) {
- uint32_t f = pd_get_frame(x);
- dbg_printf(" %i", f);
- if (f != 0) {
- pd_unmap_page(x);
- frame_free(f, 1);
- }
- }
- dbg_printf(" : ");
- region_free(ptr);
- dbg_printf("ok]\n");
-}
+
slab_type_t slab_sizes[] = {
{ "8B obj", 8, 2 },
{ "16B obj", 16, 2 },
@@ -128,7 +101,7 @@ void kmain(struct multiboot_info_t *mbd, int32_t mb_magic) {
// allocate a big region and try to write into it
const size_t n = 200;
- void* p0 = region_alloc(n * PAGE_SIZE, REGION_T_HW, test_pf_handler);
+ void* p0 = region_alloc(n * PAGE_SIZE, REGION_T_HW, default_allocator_pf_handler);
for (size_t i = 0; i < n; i++) {
uint32_t *x = (uint32_t*)(p0 + i * PAGE_SIZE);
dbg_printf("[%i : ", i);
@@ -157,7 +130,7 @@ void kmain(struct multiboot_info_t *mbd, int32_t mb_magic) {
// Test slab allocator !
mem_allocator_t *a =
create_slab_allocator(slab_sizes, page_alloc_fun_for_kmalloc,
- page_free_fun_for_kmalloc);
+ region_free_unmap_free);
dbg_printf("Created slab allocator at 0x%p\n", a);
dbg_print_region_stats();
const int m = 200;
diff --git a/kernel/l0/paging.c b/kernel/l0/paging.c
index d289712..811b677 100644
--- a/kernel/l0/paging.c
+++ b/kernel/l0/paging.c
@@ -80,6 +80,7 @@ void page_fault_handler(registers_t *regs) {
if (i->pf == 0) {
dbg_printf("Kernel pagefault in region with no handler at 0x%p\n", vaddr);
dbg_dump_registers(regs);
+ dbg_print_region_stats();
PANIC("Unhandled kernel space page fault");
}
i->pf(current_pd_d, i, vaddr);
diff --git a/kernel/l0/region.c b/kernel/l0/region.c
index 7b1d138..513af45 100644
--- a/kernel/l0/region.c
+++ b/kernel/l0/region.c
@@ -196,26 +196,26 @@ static void remove_used_region(descriptor_t *d) {
// =============== //
void region_allocator_init(void* kernel_data_end) {
- descriptor_t *u0 = &base_descriptors[0];
- u0->used.i.addr = (void*)K_HIGHHALF_ADDR;
- u0->used.i.size = PAGE_ALIGN_UP(kernel_data_end) - K_HIGHHALF_ADDR;
- u0->used.i.type = REGION_T_KERNEL_BASE;
- u0->used.i.pf = 0;
- u0->used.next_by_addr = 0;
- first_used_region = u0;
+ n_unused_descriptors = 0;
+ first_unused_descriptor = 0;
+ for (int i = 0; i < N_BASE_DESCRIPTORS; i++) {
+ add_unused_descriptor(&base_descriptors[i]);
+ }
- descriptor_t *f0 = &base_descriptors[1];
+ descriptor_t *f0 = get_unused_descriptor();
f0->free.addr = (void*)PAGE_ALIGN_UP(kernel_data_end);
f0->free.size = ((void*)LAST_KERNEL_ADDR - f0->free.addr);
f0->free.next_by_size = 0;
f0->free.first_bigger = 0;
first_free_region_by_size = first_free_region_by_addr = f0;
- n_unused_descriptors = 0;
- first_unused_descriptor = 0;
- for (int i = 2; i < N_BASE_DESCRIPTORS; i++) {
- add_unused_descriptor(&base_descriptors[i]);
- }
+ descriptor_t *u0 = get_unused_descriptor();
+ u0->used.i.addr = (void*)K_HIGHHALF_ADDR;
+ u0->used.i.size = PAGE_ALIGN_UP(kernel_data_end) - K_HIGHHALF_ADDR;
+ u0->used.i.type = REGION_T_KERNEL_BASE;
+ u0->used.i.pf = 0;
+ u0->used.next_by_addr = 0;
+ first_used_region = u0;
}
static void* region_alloc_inner(size_t size, uint32_t type, page_fault_handler_t pf, bool use_reserve) {
@@ -305,6 +305,57 @@ void region_free(void* addr) {
add_free_region(d);
}
+// ========================================================= //
+// HELPER FUNCTIONS : SIMPLE PF HANDLERS ; FREEING FUNCTIONS //
+// ========================================================= //
+
+void stack_pf_handler(pagedir_t *pd, struct region_info *r, void* addr) {
+ if (addr < r->addr + PAGE_SIZE) {
+ dbg_printf("Stack overflow at 0x%p.", addr);
+ dbg_print_region_stats();
+ PANIC("Stack overflow.");
+ }
+ default_allocator_pf_handler(pd, r, addr);
+}
+
+void default_allocator_pf_handler(pagedir_t *pd, struct region_info *r, void* addr) {
+ ASSERT(pd_get_frame(addr) == 0); // if error is of another type (RO, protected), we don't do anyting
+
+ uint32_t f = frame_alloc(1);
+ if (f == 0) PANIC("Out Of Memory");
+
+ int error = pd_map_page(addr, f, 1);
+ if (error) PANIC("Could not map frame (OOM)");
+}
+
+void region_free_unmap_free(void* ptr) {
+ region_info_t *i = find_region(ptr);
+ ASSERT(i != 0);
+
+ for (void* x = i->addr; x < i->addr + i->size; x += PAGE_SIZE) {
+ uint32_t f = pd_get_frame(x);
+ if (f != 0) {
+ pd_unmap_page(x);
+ frame_free(f, 1);
+ }
+ }
+ region_free(ptr);
+}
+
+void region_free_unmap(void* ptr) {
+ region_info_t *i = find_region(ptr);
+ ASSERT(i != 0);
+
+ for (void* x = i->addr; x < i->addr + i->size; x += PAGE_SIZE) {
+ pd_unmap_page(x);
+ }
+ region_free(ptr);
+}
+
+// =========================== //
+// DEBUG LOG PRINTING FUNCTION //
+// =========================== //
+
void dbg_print_region_stats() {
dbg_printf("/ Free kernel regions, by address:\n");
for (descriptor_t *d = first_free_region_by_addr; d != 0; d = d->free.next_by_addr) {
@@ -321,9 +372,10 @@ void dbg_print_region_stats() {
dbg_printf("| 0x%p - 0x%p", d->used.i.addr, d->used.i.addr + d->used.i.size);
if (d->used.i.type & REGION_T_KERNEL_BASE) dbg_printf(" Kernel code & base data");
if (d->used.i.type & REGION_T_DESCRIPTORS) dbg_printf(" Region descriptors");
- if (d->used.i.type & REGION_T_PAGETABLE) dbg_printf(" Mapped PD/PT");
if (d->used.i.type & REGION_T_CORE_HEAP) dbg_printf(" Core heap");
- if (d->used.i.type & REGION_T_PROC_HEAP) dbg_printf(" Kernel process heap");
+ if (d->used.i.type & REGION_T_KPROC_HEAP) dbg_printf(" Kernel process heap");
+ if (d->used.i.type & REGION_T_KPROC_STACK) dbg_printf(" Kernel process stack");
+ if (d->used.i.type & REGION_T_PROC_KSTACK) dbg_printf(" Process kernel stack");
if (d->used.i.type & REGION_T_CACHE) dbg_printf(" Cache");
if (d->used.i.type & REGION_T_HW) dbg_printf(" Hardware");
dbg_printf("\n");