diff options
author | Alex Auvolat <alex.auvolat@ens.fr> | 2014-12-06 20:30:32 +0100 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ens.fr> | 2014-12-06 20:30:32 +0100 |
commit | 0b5d6568c468075b6c1a2de065332b270345611b (patch) | |
tree | d2b9debc6eb90c5a43cac5aefd35d1550fe7b11b /kernel | |
parent | b38d90b5cacee9bfc775f1fa4b31c5863654c5e8 (diff) | |
download | macroscope-0b5d6568c468075b6c1a2de065332b270345611b.tar.gz macroscope-0b5d6568c468075b6c1a2de065332b270345611b.zip |
Refactor PF handlers and region freeing functions.
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/include/region.h | 17 | ||||
-rw-r--r-- | kernel/l0/kmain.c | 35 | ||||
-rw-r--r-- | kernel/l0/paging.c | 1 | ||||
-rw-r--r-- | kernel/l0/region.c | 82 |
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"); |