From d7aaba8c85cc71f3184cddcf20b740c5157c864d Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Sun, 7 Dec 2014 11:49:52 +0100 Subject: Refactor kmalloc & tests in kmain. --- kernel/Makefile | 2 +- kernel/include/idt.h | 2 + kernel/include/kmalloc.h | 14 +++++ kernel/l0/idt.c | 4 +- kernel/l0/kmain.c | 130 ++++++++++++++++++++--------------------------- kernel/l0/kmalloc.c | 52 +++++++++++++++++++ kernel/l0/paging.c | 4 +- kernel/l0/region.c | 2 + 8 files changed, 132 insertions(+), 78 deletions(-) create mode 100644 kernel/include/kmalloc.h create mode 100644 kernel/l0/kmalloc.c (limited to 'kernel') diff --git a/kernel/Makefile b/kernel/Makefile index 9619fb6..8b0095e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -12,7 +12,7 @@ LDFLAGS = -T linker.ld -ffreestanding -O2 -nostdlib -lgcc -Xlinker -Map=kernel.m OBJ = lib/string.o lib/printf.o lib/slab_alloc.o lib/mutex.o \ l0/loader.o l0/kmain.o l0/dbglog.o l0/sys.o \ l0/gdt.o l0/idt.o l0/interrupt.o \ - l0/frame.o l0/paging.o l0/region.o + l0/frame.o l0/paging.o l0/region.o l0/kmalloc.o OUT = kernel.bin all: $(OUT) diff --git a/kernel/include/idt.h b/kernel/include/idt.h index b697dc3..9415c8e 100644 --- a/kernel/include/idt.h +++ b/kernel/include/idt.h @@ -58,6 +58,8 @@ #define EX_INTEL_RESERVED_13 30 // No #define EX_INTEL_RESERVED_14 31 // No +#define EFLAGS_IF (0x1 << 9) + struct registers { uint32_t ds; // Data segment selector uint32_t edi, esi, ebp, useless_esp, ebx, edx, ecx, eax; // Pushed by pusha. diff --git a/kernel/include/kmalloc.h b/kernel/include/kmalloc.h new file mode 100644 index 0000000..a409865 --- /dev/null +++ b/kernel/include/kmalloc.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +// Kernel memory allocator : one slab allocator for shared memory +// Thread-safe. + +void kmalloc_setup(); + +void* kmalloc(size_t sz); +void kfree(void* ptr); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/kernel/l0/idt.c b/kernel/l0/idt.c index 8562636..2f244e3 100644 --- a/kernel/l0/idt.c +++ b/kernel/l0/idt.c @@ -222,7 +222,9 @@ void idt_init() { idt_ptr.base = (uint32_t)&idt_entries; asm volatile ("lidt %0"::"m"(idt_ptr):"memory"); - asm volatile ("sti"); // from now on we accept interruptions... although we don't do much with them + + // Some setup calls that come later on are not preemptible, + // so we wait until then to enable interrupts. } /* Sets up an IRQ handler for given IRQ. */ diff --git a/kernel/l0/kmain.c b/kernel/l0/kmain.c index b70c6f4..e6831b2 100644 --- a/kernel/l0/kmain.c +++ b/kernel/l0/kmain.c @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -18,66 +19,12 @@ void breakpoint_handler(registers_t *regs) { BOCHS_BREAKPOINT; } -void* page_alloc_fun_for_kmalloc(size_t bytes) { - 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 yield() { // multitasking not implemented yet dbg_printf("Warning : probable deadlock?\n"); } -slab_type_t slab_sizes[] = { - { "8B obj", 8, 2 }, - { "16B obj", 16, 2 }, - { "32B obj", 32, 2 }, - { "64B obj", 64, 4 }, - { "128B obj", 128, 4 }, - { "256B obj", 256, 4 }, - { "512B obj", 512, 8 }, - { "1KB obj", 1024, 8 }, - { "2KB obj", 2048, 16 }, - { "4KB obj", 4096, 16 }, - { 0, 0, 0 } -}; - - -void kmain(struct multiboot_info_t *mbd, int32_t mb_magic) { - dbglog_setup(); - - dbg_printf("Hello, kernel world!\n"); - dbg_printf("This is %s, version %s.\n", OS_NAME, OS_VERSION); - - ASSERT(mb_magic == MULTIBOOT_BOOTLOADER_MAGIC); - - gdt_init(); dbg_printf("GDT set up.\n"); - - idt_init(); dbg_printf("IDT set up.\n"); - idt_set_ex_handler(EX_BREAKPOINT, breakpoint_handler); - asm volatile("int $0x3"); // test breakpoint - - size_t total_ram = ((mbd->mem_upper + mbd->mem_lower) * 1024); - dbg_printf("Total ram: %d Kb\n", total_ram / 1024); - - // used for allocation of data structures before malloc is set up - // a pointer to this pointer is passed to the functions that might have - // to allocate memory ; they just increment it of the allocated quantity - void* kernel_data_end = &k_end_addr; - - frame_init_allocator(total_ram, &kernel_data_end); - dbg_printf("kernel_data_end: 0x%p\n", kernel_data_end); - dbg_print_frame_stats(); - - paging_setup(kernel_data_end); - dbg_printf("Paging seems to be working!\n"); - - BOCHS_BREAKPOINT; - - region_allocator_init(kernel_data_end); - dbg_print_region_stats(); - +void region_test1() { void* p = region_alloc(0x1000, REGION_T_HW, 0); dbg_printf("Allocated one-page region: 0x%p\n", p); dbg_print_region_stats(); @@ -102,20 +49,18 @@ void kmain(struct multiboot_info_t *mbd, int32_t mb_magic) { region_free(s); dbg_printf("Freed region 0x%p\n", s); dbg_print_region_stats(); - BOCHS_BREAKPOINT; +} +void region_test2() { // allocate a big region and try to write into it + dbg_printf("Begin region test 2..."); const size_t n = 200; 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); x[0] = 12; - dbg_printf(" : ."); x[1] = (i * 20422) % 122; - dbg_printf("]\n", i); } - BOCHS_BREAKPOINT; // unmap memory for (size_t i = 0; i < n; i++) { void* p = p0 + i * PAGE_SIZE; @@ -129,35 +74,72 @@ void kmain(struct multiboot_info_t *mbd, int32_t mb_magic) { frame_free(f, 1); } - region_free(s); - BOCHS_BREAKPOINT; + region_free(p0); + dbg_printf("OK\n"); +} - // Test slab allocator ! - mem_allocator_t *a = - create_slab_allocator(slab_sizes, page_alloc_fun_for_kmalloc, - region_free_unmap_free); - dbg_printf("Created slab allocator at 0x%p\n", a); +void kmalloc_test(void* kernel_data_end) { + // Test kmalloc ! dbg_print_region_stats(); + dbg_printf("Begin kmalloc test...\n"); const int m = 200; - uint16_t** ptr = slab_alloc(a, m * sizeof(uint32_t)); + uint16_t** ptr = kmalloc(m * sizeof(uint32_t)); for (int i = 0; i < m; i++) { size_t s = 1 << ((i * 7) % 11 + 2); - ptr[i] = (uint16_t*)slab_alloc(a, s); + ptr[i] = (uint16_t*)kmalloc(s); ASSERT((void*)ptr[i] >= kernel_data_end && (size_t)ptr[i] < 0xFFC00000); *ptr[i] = ((i * 211) % 1024); - dbg_printf("Alloc %i : 0x%p\n", s, ptr[i]); } + dbg_printf("Fully allocated.\n"); dbg_print_region_stats(); for (int i = 0; i < m; i++) { for (int j = i; j < m; j++) { ASSERT(*ptr[j] == (j * 211) % 1024); } - slab_free(a, ptr[i]); + kfree(ptr[i]); } + kfree(ptr); + dbg_printf("Kmalloc test OK.\n"); dbg_print_region_stats(); - dbg_printf("Destroying slab allocator...\n"); - destroy_slab_allocator(a); - dbg_print_region_stats(); +} + +void kmain(struct multiboot_info_t *mbd, int32_t mb_magic) { + dbglog_setup(); + + dbg_printf("Hello, kernel world!\n"); + dbg_printf("This is %s, version %s.\n", OS_NAME, OS_VERSION); + + ASSERT(mb_magic == MULTIBOOT_BOOTLOADER_MAGIC); + + gdt_init(); dbg_printf("GDT set up.\n"); + + idt_init(); dbg_printf("IDT set up.\n"); + idt_set_ex_handler(EX_BREAKPOINT, breakpoint_handler); + asm volatile("int $0x3"); // test breakpoint + + size_t total_ram = ((mbd->mem_upper + mbd->mem_lower) * 1024); + dbg_printf("Total ram: %d Kb\n", total_ram / 1024); + + // used for allocation of data structures before malloc is set up + // a pointer to this pointer is passed to the functions that might have + // to allocate memory ; they just increment it of the allocated quantity + void* kernel_data_end = &k_end_addr; + + frame_init_allocator(total_ram, &kernel_data_end); + dbg_printf("kernel_data_end: 0x%p\n", kernel_data_end); + dbg_print_frame_stats(); + + paging_setup(kernel_data_end); + dbg_printf("Paging seems to be working!\n"); + + BOCHS_BREAKPOINT; + + region_allocator_init(kernel_data_end); + region_test1(); + region_test2(); + + kmalloc_setup(); + kmalloc_test(kernel_data_end); PANIC("Reached kmain end! Falling off the edge."); diff --git a/kernel/l0/kmalloc.c b/kernel/l0/kmalloc.c new file mode 100644 index 0000000..a4ef8fe --- /dev/null +++ b/kernel/l0/kmalloc.c @@ -0,0 +1,52 @@ +#include + +#include +#include + +#include +#include +#include + +static void* page_alloc_fun_for_kmalloc(size_t bytes) { + void* addr = region_alloc(bytes, REGION_T_CORE_HEAP, default_allocator_pf_handler); + return addr; +} + +static slab_type_t slab_sizes[] = { + { "8B kmalloc objects", 8, 2 }, + { "16B kmalloc objects", 16, 2 }, + { "32B kmalloc objects", 32, 2 }, + { "64B kmalloc objects", 64, 4 }, + { "128B kmalloc objects", 128, 4 }, + { "256B kmalloc objects", 256, 4 }, + { "512B kmalloc objects", 512, 8 }, + { "1KB kmalloc objects", 1024, 8 }, + { "2KB kmalloc objects", 2048, 16 }, + { "4KB kmalloc objects", 4096, 16 }, + { 0, 0, 0 } +}; + +static mem_allocator_t *kernel_allocator = 0; +STATIC_MUTEX(kmalloc_mutex); + +void kmalloc_setup() { + kernel_allocator = + create_slab_allocator(slab_sizes, page_alloc_fun_for_kmalloc, + region_free_unmap_free); +} + +void* kmalloc(size_t sz) { + void* res = 0; + + mutex_lock(&kmalloc_mutex); + res = slab_alloc(kernel_allocator, sz); + mutex_unlock(&kmalloc_mutex); + + return res; +} + +void kfree(void* ptr) { + mutex_lock(&kmalloc_mutex); + slab_free(kernel_allocator, ptr); + mutex_unlock(&kmalloc_mutex); +} diff --git a/kernel/l0/paging.c b/kernel/l0/paging.c index 744424f..3f38997 100644 --- a/kernel/l0/paging.c +++ b/kernel/l0/paging.c @@ -60,7 +60,7 @@ void page_fault_handler(registers_t *regs) { invlpg(¤t_pt[pt]); return; } - asm volatile("sti"); // from now on we are preemptible + if (regs->eflags & EFLAGS_IF) asm volatile("sti"); // from now on we are preemptible if (vaddr >= (void*)&kernel_stack_protector && vaddr < (void*)&kernel_stack_protector + PAGE_SIZE) { dbg_printf("Kernel stack overflow at 0x%p\n", vaddr); @@ -87,7 +87,7 @@ void page_fault_handler(registers_t *regs) { } i->pf(current_pd_d, i, vaddr); } else { - asm volatile("sti"); // userspace PF handlers should always be preemptible + if (regs->eflags & EFLAGS_IF) asm volatile("sti"); // userspace PF handlers should always be preemptible dbg_printf("Userspace page fault at 0x%p\n", vaddr); PANIC("Unhandled userspace page fault"); diff --git a/kernel/l0/region.c b/kernel/l0/region.c index aa73a22..3691747 100644 --- a/kernel/l0/region.c +++ b/kernel/l0/region.c @@ -336,6 +336,8 @@ region_info_t *find_region(void* addr) { 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); + if (r->type & REGION_T_KPROC_STACK) dbg_printf(" (in kernel process stack)\n"); + if (r->type & REGION_T_PROC_KSTACK) dbg_printf(" (in process kernel stack)\n"); dbg_print_region_stats(); PANIC("Stack overflow."); } -- cgit v1.2.3