aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/include/idt.h2
-rw-r--r--kernel/include/kmalloc.h14
-rw-r--r--kernel/l0/idt.c4
-rw-r--r--kernel/l0/kmain.c130
-rw-r--r--kernel/l0/kmalloc.c52
-rw-r--r--kernel/l0/paging.c4
-rw-r--r--kernel/l0/region.c2
8 files changed, 132 insertions, 78 deletions
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 <stdint.h>
+#include <stddef.h>
+
+// 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 <frame.h>
#include <paging.h>
#include <region.h>
+#include <kmalloc.h>
#include <slab_alloc.h>
@@ -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 <kmalloc.h>
+
+#include <slab_alloc.h>
+#include <mutex.h>
+
+#include <frame.h>
+#include <paging.h>
+#include <region.h>
+
+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(&current_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.");
}