From 6a52d123672b7a00af6e22b4c138205be2042a94 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Sat, 6 Feb 2010 20:51:56 +0100 Subject: Reorganisation --- src/grapes/link.ld | 26 ----- src/grapes/test/Makefile | 30 ------ src/grapes/test/main.c | 8 -- src/kernel/Makefile | 38 +++++++ src/kernel/core/kmain.c | 63 +++++++++++ src/kernel/core/loader_.asm | 57 ++++++++++ src/kernel/core/monitor.c | 90 ++++++++++++++++ src/kernel/core/monitor.h | 12 +++ src/kernel/core/multiboot.h | 64 +++++++++++ src/kernel/core/sys.c | 41 ++++++++ src/kernel/core/sys.h | 17 +++ src/kernel/lib/bitset.c | 35 +++++++ src/kernel/lib/bitset.h | 19 ++++ src/kernel/lib/stdlib.c | 39 +++++++ src/kernel/lib/stdlib.h | 12 +++ src/kernel/lib/types.h | 15 +++ src/kernel/link.ld | 32 ++++++ src/kernel/linker/elf.c | 44 ++++++++ src/kernel/linker/elf.h | 63 +++++++++++ src/kernel/mem/gdt.c | 36 +++++++ src/kernel/mem/gdt.h | 23 ++++ src/kernel/mem/heap.c | 224 +++++++++++++++++++++++++++++++++++++++ src/kernel/mem/heap.h | 27 +++++ src/kernel/mem/mem.c | 95 +++++++++++++++++ src/kernel/mem/mem.h | 17 +++ src/kernel/mem/paging.c | 171 ++++++++++++++++++++++++++++++ src/kernel/mem/paging.h | 46 ++++++++ src/kernel/mem/seg.c | 73 +++++++++++++ src/kernel/mem/seg.h | 40 +++++++ src/kernel/task/idt.c | 191 +++++++++++++++++++++++++++++++++ src/kernel/task/idt.h | 33 ++++++ src/kernel/task/idt_.asm | 155 +++++++++++++++++++++++++++ src/kernel/task/syscall.c | 21 ++++ src/kernel/task/syscall.h | 9 ++ src/kernel/task/task.c | 245 +++++++++++++++++++++++++++++++++++++++++++ src/kernel/task/task.h | 55 ++++++++++ src/kernel/task/task_.asm | 10 ++ src/kernel/task/timer.c | 36 +++++++ src/kernel/task/timer.h | 10 ++ src/library/Makefile | 34 ++++++ src/library/grapes/syscall.c | 27 +++++ src/library/grapes/syscall.h | 10 ++ src/library/link.ld | 27 +++++ src/library/start.c | 6 ++ src/modules/test/Makefile | 32 ++++++ src/modules/test/main.c | 8 ++ src/stem/Makefile | 37 ------- src/stem/core/kmain.c | 63 ----------- src/stem/core/loader_.asm | 57 ---------- src/stem/core/monitor.c | 90 ---------------- src/stem/core/monitor.h | 12 --- src/stem/core/multiboot.h | 64 ----------- src/stem/core/sys.c | 41 -------- src/stem/core/sys.h | 17 --- src/stem/lib/bitset.c | 35 ------- src/stem/lib/bitset.h | 19 ---- src/stem/lib/stdlib.c | 39 ------- src/stem/lib/stdlib.h | 12 --- src/stem/lib/types.h | 15 --- src/stem/link.ld | 32 ------ src/stem/linker/elf.c | 44 -------- src/stem/linker/elf.h | 63 ----------- src/stem/mem/gdt.c | 36 ------- src/stem/mem/gdt.h | 23 ---- src/stem/mem/heap.c | 224 --------------------------------------- src/stem/mem/heap.h | 27 ----- src/stem/mem/mem.c | 95 ----------------- src/stem/mem/mem.h | 17 --- src/stem/mem/paging.c | 171 ------------------------------ src/stem/mem/paging.h | 46 -------- src/stem/mem/seg.c | 73 ------------- src/stem/mem/seg.h | 40 ------- src/stem/task/idt.c | 191 --------------------------------- src/stem/task/idt.h | 33 ------ src/stem/task/idt_.asm | 155 --------------------------- src/stem/task/syscall.c | 21 ---- src/stem/task/syscall.h | 9 -- src/stem/task/task.c | 245 ------------------------------------------- src/stem/task/task.h | 55 ---------- src/stem/task/task_.asm | 10 -- src/stem/task/timer.c | 36 ------- src/stem/task/timer.h | 10 -- 82 files changed, 2302 insertions(+), 2221 deletions(-) delete mode 100644 src/grapes/link.ld delete mode 100644 src/grapes/test/Makefile delete mode 100644 src/grapes/test/main.c create mode 100644 src/kernel/Makefile create mode 100644 src/kernel/core/kmain.c create mode 100644 src/kernel/core/loader_.asm create mode 100644 src/kernel/core/monitor.c create mode 100644 src/kernel/core/monitor.h create mode 100644 src/kernel/core/multiboot.h create mode 100644 src/kernel/core/sys.c create mode 100644 src/kernel/core/sys.h create mode 100644 src/kernel/lib/bitset.c create mode 100644 src/kernel/lib/bitset.h create mode 100644 src/kernel/lib/stdlib.c create mode 100644 src/kernel/lib/stdlib.h create mode 100644 src/kernel/lib/types.h create mode 100644 src/kernel/link.ld create mode 100644 src/kernel/linker/elf.c create mode 100644 src/kernel/linker/elf.h create mode 100644 src/kernel/mem/gdt.c create mode 100644 src/kernel/mem/gdt.h create mode 100644 src/kernel/mem/heap.c create mode 100644 src/kernel/mem/heap.h create mode 100644 src/kernel/mem/mem.c create mode 100644 src/kernel/mem/mem.h create mode 100644 src/kernel/mem/paging.c create mode 100644 src/kernel/mem/paging.h create mode 100644 src/kernel/mem/seg.c create mode 100644 src/kernel/mem/seg.h create mode 100644 src/kernel/task/idt.c create mode 100644 src/kernel/task/idt.h create mode 100644 src/kernel/task/idt_.asm create mode 100644 src/kernel/task/syscall.c create mode 100644 src/kernel/task/syscall.h create mode 100644 src/kernel/task/task.c create mode 100644 src/kernel/task/task.h create mode 100644 src/kernel/task/task_.asm create mode 100644 src/kernel/task/timer.c create mode 100644 src/kernel/task/timer.h create mode 100644 src/library/Makefile create mode 100644 src/library/grapes/syscall.c create mode 100644 src/library/grapes/syscall.h create mode 100644 src/library/link.ld create mode 100644 src/library/start.c create mode 100644 src/modules/test/Makefile create mode 100644 src/modules/test/main.c delete mode 100644 src/stem/Makefile delete mode 100644 src/stem/core/kmain.c delete mode 100644 src/stem/core/loader_.asm delete mode 100644 src/stem/core/monitor.c delete mode 100644 src/stem/core/monitor.h delete mode 100644 src/stem/core/multiboot.h delete mode 100644 src/stem/core/sys.c delete mode 100644 src/stem/core/sys.h delete mode 100644 src/stem/lib/bitset.c delete mode 100644 src/stem/lib/bitset.h delete mode 100644 src/stem/lib/stdlib.c delete mode 100644 src/stem/lib/stdlib.h delete mode 100644 src/stem/lib/types.h delete mode 100644 src/stem/link.ld delete mode 100644 src/stem/linker/elf.c delete mode 100644 src/stem/linker/elf.h delete mode 100644 src/stem/mem/gdt.c delete mode 100644 src/stem/mem/gdt.h delete mode 100644 src/stem/mem/heap.c delete mode 100644 src/stem/mem/heap.h delete mode 100644 src/stem/mem/mem.c delete mode 100644 src/stem/mem/mem.h delete mode 100644 src/stem/mem/paging.c delete mode 100644 src/stem/mem/paging.h delete mode 100644 src/stem/mem/seg.c delete mode 100644 src/stem/mem/seg.h delete mode 100644 src/stem/task/idt.c delete mode 100644 src/stem/task/idt.h delete mode 100644 src/stem/task/idt_.asm delete mode 100644 src/stem/task/syscall.c delete mode 100644 src/stem/task/syscall.h delete mode 100644 src/stem/task/task.c delete mode 100644 src/stem/task/task.h delete mode 100644 src/stem/task/task_.asm delete mode 100644 src/stem/task/timer.c delete mode 100644 src/stem/task/timer.h (limited to 'src') diff --git a/src/grapes/link.ld b/src/grapes/link.ld deleted file mode 100644 index 7527b80..0000000 --- a/src/grapes/link.ld +++ /dev/null @@ -1,26 +0,0 @@ -ENTRY (start) - -SECTIONS{ - . = 0x10000000; - - .text : { - *(.text) - } - - .rodata ALIGN (0x1000) :{ - *(.rodata) - } - - .data ALIGN (0x1000) : { - *(.data) - } - - .bss : { - sbss = .; - *(COMMON) - *(.bss) - ebss = .; - } - - end = .; _end = .; __end = .; -} diff --git a/src/grapes/test/Makefile b/src/grapes/test/Makefile deleted file mode 100644 index ddcc36f..0000000 --- a/src/grapes/test/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -.PHONY: clean, mrproper - -CC = gcc -CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -Wall -Wextra - -LD = ld -LDFLAGS = -T ../link.ld - -Objects = main.o -Outfile = test - -all: $(Outfile) - echo "* Done with $(Outfile)" - -rebuild: mrproper all - -$(Outfile): $(Objects) - echo "* Linking $@..." - $(LD) $(LDFLAGS) -o $@ $^ - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ - -clean: - echo "* Removing objects..." - rm $(Objects) - -mrproper: clean - rm $(Outfile) - diff --git a/src/grapes/test/main.c b/src/grapes/test/main.c deleted file mode 100644 index 0413889..0000000 --- a/src/grapes/test/main.c +++ /dev/null @@ -1,8 +0,0 @@ -void printk(char *s) { - asm volatile("int $64" : : "a"(4), "b"(s)); -} - -void start() { - printk("Hi world !"); - asm volatile("int $64" : : "a"(3), "b"(0)); -} diff --git a/src/kernel/Makefile b/src/kernel/Makefile new file mode 100644 index 0000000..5af7f4b --- /dev/null +++ b/src/kernel/Makefile @@ -0,0 +1,38 @@ +.PHONY: clean, mrproper + +CC = gcc +CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -Wall -Wextra -I . -I ./lib + +LD = ld +LDFLAGS = -T link.ld + +ASM = nasm +AFLAGS = -f elf + +OBJECTS = core/loader_.o core/kmain.o core/sys.o \ + core/monitor.o task/timer.o \ + task/idt.o task/idt_.o task/task.o task/task_.o task/syscall.o \ + lib/stdlib.o lib/bitset.o \ + mem/mem.o mem/paging.o mem/gdt.o mem/heap.o mem/seg.o \ + linker/elf.o +OUT = kernel.elf + +all: $(OBJECTS) + echo "* Linking $(OUT)..." + $(LD) $(LDFLAGS) $(OBJECTS) -o $(OUT) -Map kernel.map + +clean: + rm $(OBJECTS) || exit 0 + rm *.o */*.o || exit 0 + rm *.map || exit 0 + +mrproper: clean + rm $(OUT) || exit 0 + +%.o: %.asm + echo "* Compiling $<..." + $(ASM) $(AFLAGS) -o $@ $< + +%.o: %.c + echo "* Compiling $<..." + $(CC) -c $< -o $@ $(CFLAGS) diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c new file mode 100644 index 0000000..ef92dff --- /dev/null +++ b/src/kernel/core/kmain.c @@ -0,0 +1,63 @@ +#include +#include "multiboot.h" +#include "monitor.h" +#include "sys.h" +#include +#include +#include +#include +#include +#include +#include + +void kmain(struct multiboot_info_t* mbd, int32_t magic) { + size_t totalRam = 0; + uint32_t i; + + mem_placementAddr = (size_t)&end; + mbd->cmdline += 0xE0000000; mbd->mods_addr += 0xE0000000; + struct module_t *mods = (struct module_t*)mbd->mods_addr; + for (i = 0; i < mbd->mods_count; i++) { + mods[i].mod_start += 0xE0000000; + mods[i].mod_end += 0xE0000000; + mods[i].string += 0xE0000000; + if (mods[i].mod_end > mem_placementAddr) + mem_placementAddr = (mods[i].mod_end & 0xFFFFF000) + 0x1000; + } + + monitor_clear(); + + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { + PANIC("wrong multiboot magic number."); + } + + monitor_write("Grapes kernel booting ...\n"); + + idt_init(); + + totalRam = ((mbd->mem_upper + mbd->mem_lower) * 1024); + paging_init(totalRam); + gdt_init(); + paging_cleanup(); + kheap_init(); + timer_init(20); + tasking_init(); + + monitor_write("Loading modules...\n"); + for (i = 0; i < mbd->mods_count; i++) { + monitor_write((char*)mods[i].string); + if (elf_check((uint8_t*)mods[i].mod_start)) { + monitor_write(" : Invalid ELF file\n"); + } else { + if (elf_exec((uint8_t*)mods[i].mod_start) == 0) { + monitor_write(" : Error loading\n"); + } else { + monitor_write(" : OK\n"); + } + } + } + + monitor_write("Passing control to loaded modules...\n"); + sti(); + tasking_switch(); +} diff --git a/src/kernel/core/loader_.asm b/src/kernel/core/loader_.asm new file mode 100644 index 0000000..d3b92cf --- /dev/null +++ b/src/kernel/core/loader_.asm @@ -0,0 +1,57 @@ +[GLOBAL loader] ; making entry point visible to linker +[EXTERN kmain] ; kmain is defined in kmain.c +[EXTERN tasking_tmpStack] ; a temporary 4k stack used by tasking, and used when setting up kernel stuff + +; setting up the Multiboot header - see GRUB docs for details +MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries +MEMINFO equ 1<<1 ; provide memory map +FLAGS equ MODULEALIGN | MEMINFO ; this is the Multiboot 'flag' field +MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header +CHECKSUM equ -(MAGIC + FLAGS) ; checksum required + +section .text +align 4 +MultiBootHeader: + dd MAGIC + dd FLAGS + dd CHECKSUM + +section .setup +loader: ;here, we load our false GDT, used for having the kernel in higher half + lgdt [trickgdt] + mov cx, 0x10; + mov ds, cx; + mov es, cx; + mov fs, cx; + mov gs, cx; + mov ss, cx; + + jmp 0x08:higherhalf + +section .text +higherhalf: ; now we're running in higher half + + mov esp, tasking_tmpStack+0x4000 ; set up the stack + push eax ; pass Multiboot magic number + add ebx, 0xE0000000 ; update the MB info structure so that it is in the new seg + push ebx ; pass Multiboot info structure + + call kmain ; call kernel proper + + cli ; disable interupts +hang: + hlt ; halt machine should kernel return + jmp hang + +[section .setup] ; this is included in the .setup section, so that it thinks it is at 0x00100000 + +trickgdt: ; our false GDT + dw gdt_end - gdt - 1 ; gdt limit + dd gdt ; gdt base + +gdt: + dd 0, 0 ; null GDT entry + db 0xFF, 0xFF, 0, 0, 0, 10011010b, 11001111b, 0x20 ; kernel code segment + db 0xFF, 0xFF, 0, 0, 0, 10010010b, 11001111b, 0x20 ; kernel data segment + +gdt_end: diff --git a/src/kernel/core/monitor.c b/src/kernel/core/monitor.c new file mode 100644 index 0000000..8c4744a --- /dev/null +++ b/src/kernel/core/monitor.c @@ -0,0 +1,90 @@ +#include "monitor.h" +#include "sys.h" + +static int cursor_x = 0, cursor_y = 0; +static uint16_t *video_memory = (uint16_t*)0xE00B8000; + +static void move_cursor() { + uint16_t cursor_location = cursor_y * 80 + cursor_x; + outb(0x3D4, 14); //Sending high cursor byte + outb(0x3D5, cursor_location >> 8); + outb(0x3D4, 15); //Sending high cursor byte + outb(0x3D5, cursor_location); +} + +static void scroll() { + uint8_t attribute_byte = (0 /* black */ << 4) | (7/* white */ & 0x0F); + uint16_t blank = (attribute_byte << 8) | 0x20; + + if (cursor_y >= 25) { + int i; + for (i = 0; i < 80*24; i++) { + video_memory[i] = video_memory[i+80]; + } + for (i = 80*24; i < 80*25; i++) { + video_memory[i] = blank; + } + cursor_y = 24; + } +} + +void monitor_put(char c) { + uint8_t fg = 7; //White + uint8_t bg = 0; //Black + + uint16_t attribute = (fg & 0x0F) | (bg << 4); + attribute = attribute << 8; + + if (c == 0x08 && cursor_x) { //Backspace + cursor_x--; + } else if (c == 0x09) { //Tab + cursor_x = (cursor_x + 8) & ~(8 - 1); + } else if (c == '\r') { //Carriage return + cursor_x = 0; + } else if (c == '\n') { //New line + cursor_x = 0; + cursor_y++; + } else if (c >= ' ') { //Any printable character + video_memory[cursor_y * 80 + cursor_x] = c | attribute; + cursor_x++; + } + if (cursor_x >= 80) { + cursor_x = 0; + cursor_y++; + } + + scroll(); + move_cursor(); +} + +void monitor_clear() { + uint8_t attribute_byte = (0 /* black */ << 4) | (15 /* white */ & 0x0F); + uint16_t blank = (attribute_byte << 8) | 0x20; + + int i; + + for (i = 0; i < 80*25; i++) { + video_memory[i] = blank; + } + + cursor_x = 0; cursor_y = 0; + move_cursor(); +} + +void monitor_write(char *s) { + while (*s) { + monitor_put(*(s++)); + } +} + +void monitor_writeHex(uint32_t v) { + int i; + + monitor_put('0'); monitor_put('x'); + char hexdigits[] = "0123456789abcdef"; + + for (i = 0; i < 8; i++) { + monitor_put(hexdigits[v >> 28]); + v = v << 4; + } +} diff --git a/src/kernel/core/monitor.h b/src/kernel/core/monitor.h new file mode 100644 index 0000000..3abe072 --- /dev/null +++ b/src/kernel/core/monitor.h @@ -0,0 +1,12 @@ +#ifndef DEF_MONITOR_H +#define DEF_MONITOR_H + +#include "types.h" + +void monitor_put(char c); +void monitor_clear(); +void monitor_write(char *s); +void monitor_writeHex(uint32_t v); + +#endif + diff --git a/src/kernel/core/multiboot.h b/src/kernel/core/multiboot.h new file mode 100644 index 0000000..908274c --- /dev/null +++ b/src/kernel/core/multiboot.h @@ -0,0 +1,64 @@ +#ifndef HDR_MULTIBOOT +#define HDR_MULTIBOOT +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +struct multiboot_header_t{ + unsigned long magic; + unsigned long flags; + unsigned long checksum; + unsigned long header_addr; + unsigned long load_addr; + unsigned long load_end_addr; + unsigned long bss_end_addr; + unsigned long entry_addr; +}; + +struct aout_symbol_table_t { + unsigned long tabsize; + unsigned long strsize; + unsigned long addr; + unsigned long reserved; +}; + +struct elf_section_header_table_t { + unsigned long num; + unsigned long size; + unsigned long addr; + unsigned long shndx; +}; + +struct multiboot_info_t { + unsigned long flags; + unsigned long mem_lower; + unsigned long mem_upper; + unsigned long boot_device; + unsigned long cmdline; + unsigned long mods_count; + unsigned long mods_addr; + union { + struct aout_symbol_table_t aout_sym; + struct elf_section_header_table_t elf_sec; + } u; + unsigned long mmap_length; + unsigned long mmap_addr; +}; + +struct module_t { + unsigned long mod_start; + unsigned long mod_end; + unsigned long string; + unsigned long reserved; +}; + +struct memory_map_t { + unsigned long size; + unsigned long base_addr_low; + unsigned long base_addr_high; + unsigned long length_low; + unsigned long length_high; + unsigned long type; +}; + +#endif + diff --git a/src/kernel/core/sys.c b/src/kernel/core/sys.c new file mode 100644 index 0000000..d31c20e --- /dev/null +++ b/src/kernel/core/sys.c @@ -0,0 +1,41 @@ +#include "sys.h" +#include "monitor.h" + +void outb(uint16_t port, uint8_t value) { + asm volatile("outb %1, %0" : : "dN"(port), "a"(value)); +} + +void outw(uint16_t port, uint16_t value) { + asm volatile("outw %1, %0" : : "dN"(port), "a"(value)); +} + +uint8_t inb(uint16_t port) { + uint8_t ret; + asm volatile("inb %1, %0" : "=a"(ret) : "dN"(port)); + return ret; +} + +uint16_t inw(uint16_t port) { + uint16_t ret; + asm volatile("inw %1, %0" : "=a"(ret) : "dN"(port)); + return ret; +} + +void panic(char* message, char* file, int line) { + monitor_write("\n>> PANIC: >>"); + monitor_write(message); monitor_write("<< in file "); monitor_write(file); + monitor_write("\nSystem halted T_T"); + asm volatile("cli; hlt"); +} + +static uint32_t if_locks = 1; + +void cli() { + asm volatile("cli"); + if_locks++; +} + +void sti() { + if (if_locks > 0) if_locks--; + if (if_locks == 0) asm volatile("sti"); +} diff --git a/src/kernel/core/sys.h b/src/kernel/core/sys.h new file mode 100644 index 0000000..76e3560 --- /dev/null +++ b/src/kernel/core/sys.h @@ -0,0 +1,17 @@ +#ifndef DEF_SYS_H +#define DEF_SYS_H + +#include "types.h" + +void outb(uint16_t port, uint8_t value); +void outw(uint16_t port, uint16_t value); +uint8_t inb(uint16_t port); +uint16_t inw(uint16_t port); + +#define PANIC(s) panic(s, __FILE__, __LINE__); +void panic(char* message, char* file, int line); + +void sti(); //GLOBAL SYSTEM MUTEX +void cli(); + +#endif diff --git a/src/kernel/lib/bitset.c b/src/kernel/lib/bitset.c new file mode 100644 index 0000000..a6d334b --- /dev/null +++ b/src/kernel/lib/bitset.c @@ -0,0 +1,35 @@ +#include "bitset.h" + +void bitset_set(struct bitset* t, uint32_t num) { + uint32_t idx = INDEX_FROM_BIT(num); + uint32_t off = OFFSET_FROM_BIT(num); + t->bits[idx] |= (0x1 << off); +} + +void bitset_clear(struct bitset* t, uint32_t num) { + uint32_t idx = INDEX_FROM_BIT(num); + uint32_t off = OFFSET_FROM_BIT(num); + t->bits[idx] &= ~(0x1 << off); +} + +uint32_t bitset_test(struct bitset* t, uint32_t num) { + uint32_t idx = INDEX_FROM_BIT(num); + uint32_t off = OFFSET_FROM_BIT(num); + return (t->bits[idx] & (0x1 << off)); +} + +uint32_t bitset_firstFree(struct bitset* t) { + uint32_t i, j; + for (i = 0; i < INDEX_FROM_BIT(t->size); i++) { + if (t->bits[i] != 0xFFFFFFFF) { + for (j = 0; j < 32; j++) { + uint32_t toTest = 0x1 << j; + if (!(t->bits[i] & toTest)) { + return i*4*8+j; + } + } + } + } + return (uint32_t) - 1; +} + diff --git a/src/kernel/lib/bitset.h b/src/kernel/lib/bitset.h new file mode 100644 index 0000000..fe9e8c2 --- /dev/null +++ b/src/kernel/lib/bitset.h @@ -0,0 +1,19 @@ +#ifndef DEF_BITSET_H +#define DEF_BITSET_H + +#include + +#define INDEX_FROM_BIT(a) (a/(8*4)) +#define OFFSET_FROM_BIT(a) (a%(8*4)) + +struct bitset { + uint32_t *bits; + uint32_t size; +}; + +void bitset_set(struct bitset* t, uint32_t num); +void bitset_clear(struct bitset* t, uint32_t num); +uint32_t bitset_test(struct bitset* t, uint32_t num); +uint32_t bitset_firstFree(struct bitset* t); + +#endif diff --git a/src/kernel/lib/stdlib.c b/src/kernel/lib/stdlib.c new file mode 100644 index 0000000..c5245e7 --- /dev/null +++ b/src/kernel/lib/stdlib.c @@ -0,0 +1,39 @@ +#include "stdlib.h" + +void *memcpy(void *vd, const void *vs, int count) { + uint8_t *dest = (uint8_t*)vd, *src = (uint8_t*)vs; + uint32_t f = count % 4, n = count / 4, i; + const uint32_t* s = (uint32_t*)src; + uint32_t* d = (uint32_t*)dest; + for (i = 0; i < n; i++) { + d[i] = s[i]; + } + if (f != 0) { + for (i = count - f; i < count; i++) { + dest[i] = src[i]; + } + } + return vd; +} + +uint8_t *memset(uint8_t *dest, uint8_t val, int count) { + int i; + for (i = 0; i < count; i++) { + dest[i] = val; + } + return dest; +} + +uint16_t *memsetw(uint16_t *dest, uint16_t val, int count) { + int i; + for (i = 0; i < count; i++) { + dest[i] = val; + } + return dest; +} + +int strlen(const char *str) { + int i = 0; + while (str[i++]); + return i; +} diff --git a/src/kernel/lib/stdlib.h b/src/kernel/lib/stdlib.h new file mode 100644 index 0000000..704c410 --- /dev/null +++ b/src/kernel/lib/stdlib.h @@ -0,0 +1,12 @@ +#ifndef DEF_STDLIB_H +#define DEF_STDLIB_H + +#include + +void *memcpy(void *dest, const void *src, int count); +uint8_t *memset(uint8_t *dest, uint8_t val, int count); +uint16_t *memsetw(uint16_t *dest, uint16_t val, int count); +int strlen(const char *str); + +#endif + diff --git a/src/kernel/lib/types.h b/src/kernel/lib/types.h new file mode 100644 index 0000000..b7b19ab --- /dev/null +++ b/src/kernel/lib/types.h @@ -0,0 +1,15 @@ +#ifndef DEF_TYPES_H +#define DEF_TYPES_H + +typedef unsigned long long uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short uint16_t; +typedef unsigned char uint8_t; +typedef long long int64_t; +typedef int int32_t; +typedef short int16_t; +typedef char int8_t; + +typedef unsigned int size_t; + +#endif diff --git a/src/kernel/link.ld b/src/kernel/link.ld new file mode 100644 index 0000000..1ce17cf --- /dev/null +++ b/src/kernel/link.ld @@ -0,0 +1,32 @@ +ENTRY (loader) + +SECTIONS{ + . = 0x00100000; + + .setup : { + *(.setup) + } + + . += 0xE0000000; + + .text : AT(ADDR(.text) - 0xE0000000) { + *(.text) + } + + .rodata ALIGN (0x1000) : AT(ADDR(.rodata) - 0xE0000000) { + *(.rodata) + } + + .data ALIGN (0x1000) : AT(ADDR(.data) - 0xE0000000) { + *(.data) + } + + .bss : AT(ADDR(.bss) - 0xE0000000) { + sbss = .; + *(COMMON) + *(.bss) + ebss = .; + } + + end = .; _end = .; __end = .; +} diff --git a/src/kernel/linker/elf.c b/src/kernel/linker/elf.c new file mode 100644 index 0000000..dc7481b --- /dev/null +++ b/src/kernel/linker/elf.c @@ -0,0 +1,44 @@ +#include "elf.h" +#include +#include +#include +#include + +int elf_check(uint8_t *data) { + struct elf_ehdr *h = (struct elf_ehdr*)data; + if (h->e_ident[0] == 0x7F && h->e_ident[1] == 'E' && h->e_ident[2] == 'L' && h->e_ident[3] == 'F') return 0; + return 1; +} + +thread_entry elf_load(uint8_t *data, struct process* process) { + struct elf_ehdr *ehdr = (struct elf_ehdr*)data; + struct elf_phdr *phdr; + int i; + if (elf_check(data)) return 0; + + pagedir_switch(process->pagedir); + + phdr = (struct elf_phdr*)((uint8_t*)(data + ehdr->e_phoff)); + for (i = 0; i < ehdr->e_phnum; i++) { + if (phdr[i].p_type == PT_LOAD) { + seg_map(simpleseg_make(phdr[i].p_vaddr, phdr[i].p_memsz, (phdr[i].p_flags & PF_W) != 0), process->pagedir); + memcpy((uint8_t*)phdr[i].p_vaddr, data + phdr[i].p_offset, phdr[i].p_filesz); + if (phdr[i].p_memsz > phdr[i].p_filesz) { + memset((uint8_t*)phdr[i].p_vaddr + phdr[i].p_memsz, 0, phdr[i].p_memsz - phdr[i].p_filesz); + } + } + } + return (thread_entry)ehdr->e_entry; +} + +struct process* elf_exec(uint8_t *data) { + if (elf_check(data)) return 0; + + struct process* p = process_new(0, 0, PL_DRIVER); + + thread_entry e = elf_load(data, p); + + thread_new(p, e, 0); + + return p; +} diff --git a/src/kernel/linker/elf.h b/src/kernel/linker/elf.h new file mode 100644 index 0000000..f84bb62 --- /dev/null +++ b/src/kernel/linker/elf.h @@ -0,0 +1,63 @@ +#ifndef DEF_ELF_H +#define DEF_ELF_H + +#include +#include + +/* elf_phdr_t :: p_type : program header entries types */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* elf_phdr_t :: p_flags : program header entries flags */ +#define PF_X (1 << 0) +#define PF_W (1 << 1) +#define PF_R (1 << 2) + +struct elf_ehdr { + uint8_t e_ident[16]; /* ELF identification */ + uint16_t e_type; /* 2 (exec file) */ + uint16_t e_machine; /* 3 (intel architecture) */ + uint32_t e_version; /* 1 */ + uint32_t e_entry; /* starting point */ + uint32_t e_phoff; /* program header table offset */ + uint32_t e_shoff; /* section header table offset */ + uint32_t e_flags; /* various flags */ + uint16_t e_ehsize; /* ELF header (this) size */ + + uint16_t e_phentsize; /* program header table entry size */ + uint16_t e_phnum; /* number of entries */ + + uint16_t e_shentsize; /* section header table entry size */ + uint16_t e_shnum; /* number of entries */ + + uint16_t e_shstrndx; /* index of the section name string table */ +}; + +struct elf_phdr { + uint32_t p_type; /* type of segment */ + uint32_t p_offset; + uint32_t p_vaddr; + uint32_t p_paddr; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +}; + +struct phdr { + struct elf_phdr h; + uint8_t* data; +}; + +int elf_check(uint8_t *data); //0 if ok, 1 if not a valid ELF +thread_entry elf_load(uint8_t *data, struct process* process); //Load an ELF to a process, return entry point +struct process* elf_exec(uint8_t *data); //Creates a new process and a thread for running ELF file + +#endif diff --git a/src/kernel/mem/gdt.c b/src/kernel/mem/gdt.c new file mode 100644 index 0000000..5aaad41 --- /dev/null +++ b/src/kernel/mem/gdt.c @@ -0,0 +1,36 @@ +#include "gdt.h" +#include +#include + +extern void gdt_flush(uint32_t); //ASM (idt_.asm) + +#define GDT_ENTRIES 5 + +static struct gdt_entry gdt_entries[GDT_ENTRIES]; +static struct gdt_ptr gdt_ptr; + +static void gdt_setGate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { + gdt_entries[num].base_low = (base & 0xFFFF); + gdt_entries[num].base_middle = (base >> 16) & 0xFF; + gdt_entries[num].base_high = (base >> 24) & 0xFF; + + gdt_entries[num].limit_low = (limit & 0xFFFF); + gdt_entries[num].granularity = (limit >> 16) & 0x0F; + gdt_entries[num].granularity |= gran & 0xF0; + gdt_entries[num].access = access; +} + +void gdt_init() { + gdt_ptr.limit = (sizeof(struct gdt_entry) * GDT_ENTRIES) - 1; + gdt_ptr.base = (uint32_t)&gdt_entries; + + gdt_setGate(0, 0, 0, 0, 0); //Null segment + gdt_setGate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); //Kernel code segment + gdt_setGate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); //Kernel data segment + gdt_setGate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); //User code segment + gdt_setGate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); //User data segment + + gdt_flush((uint32_t)&gdt_ptr); + + monitor_write("GDT ok\n"); +} diff --git a/src/kernel/mem/gdt.h b/src/kernel/mem/gdt.h new file mode 100644 index 0000000..aac16bb --- /dev/null +++ b/src/kernel/mem/gdt.h @@ -0,0 +1,23 @@ +#ifndef DEF_GDT_H +#define DEF_GDT_H + +#include + +struct gdt_entry { + uint16_t limit_low; + uint16_t base_low; + uint8_t base_middle; + uint8_t access; + uint8_t granularity; + uint8_t base_high; +} __attribute__((packed)); + +struct gdt_ptr { + uint16_t limit; + uint32_t base; +} __attribute__((packed)); + +void gdt_init(); + +#endif + diff --git a/src/kernel/mem/heap.c b/src/kernel/mem/heap.c new file mode 100644 index 0000000..b6d2cd4 --- /dev/null +++ b/src/kernel/mem/heap.c @@ -0,0 +1,224 @@ +#include "heap.h" +#include "paging.h" + +#define HEAP_MAGIC 0xBAD0BEEF +#define HEAP_MIN_SIZE 0x4000 + +/* ******************* HEADER ****************** */ + +static void heapIdx_insert(struct heap *heap, struct heap_header *e) { + if ((heap->idxused + sizeof(struct heap_header*) + (size_t)heap->idx) >= heap->start_addr) return; + + uint32_t iterator = 0, pos; + while (iterator < heap->idxused && heap->idx[iterator]->size < e->size) { + if (heap->idx[iterator] == e) return; + iterator++; + } + if (iterator == heap->idxused) { + heap->idx[heap->idxused++] = e; + } else { + pos = iterator; + iterator = heap->idxused; + while (iterator > pos) { + heap->idx[iterator] = heap->idx[iterator - 1]; + iterator--; + } + heap->idxused++; + heap->idx[pos] = e; + } +} + +static void heapIdx_remove(struct heap *heap, struct heap_header *e) { + uint32_t iterator; + for (iterator = 0; iterator < heap->idxused; iterator++) { + if (heap->idx[iterator] == e) break; + } + if (iterator == heap->idxused) return; + heap->idxused--; + while (iterator < heap->idxused) { + heap->idx[iterator] = heap->idx[iterator + 1]; + iterator++; + } +} + +/* ******************** CONTENTS ********************* */ + +void heap_create(struct heap *heap, size_t start, size_t idxsize, size_t datasize, size_t maxdatasize) { + uint32_t i; + + if (start & 0x0FFF) start = (start & 0xFFFFF000) + 0x1000; + + heap->start_addr = start + idxsize; + heap->end_addr = start + idxsize + datasize; + heap->max_end = start + idxsize + maxdatasize; + + for (i = start; i < heap->end_addr; i += 0x1000) { + page_map(pagedir_getPage(kernel_pagedir, i, 1), frame_alloc(), 0, 0); + } + + heap->idx = (struct heap_header**)start; + heap->idxused = 0; + + struct heap_header *hole = (struct heap_header*) heap->start_addr; + hole->size = (heap->end_addr - heap->start_addr); + hole->magic = HEAP_MAGIC; + hole->is_hole = 1; + + struct heap_footer *hole_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); + hole_footer->header = hole; + hole_footer->magic = HEAP_MAGIC; + + heapIdx_insert(heap, hole); +} + +static uint32_t heap_expand(struct heap *heap, size_t quantity) { + uint32_t i; + + if (quantity & 0x0FFF) { + quantity = (quantity & 0xFFFFF000) + 0x1000; + } + + if (heap->end_addr + quantity > heap->max_end) return 0; + + size_t newEnd = heap->end_addr + quantity; + + for (i = heap->end_addr; i < newEnd; i += 0x1000) { + page_map(pagedir_getPage(kernel_pagedir, i, 1), frame_alloc(), 0, 0); + } + + struct heap_footer *last_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); + struct heap_header *last_header = last_footer->header; + if (last_header->is_hole) { + heapIdx_remove(heap, last_header); + last_header->size += quantity; + + last_footer = (struct heap_footer*)(newEnd - sizeof(struct heap_footer)); + last_footer->magic = HEAP_MAGIC; + last_footer->header = last_header; + + heapIdx_insert(heap, last_header); + } else { + last_header = (struct heap_header*)heap->end_addr; + last_footer = (struct heap_footer*)(newEnd - sizeof(struct heap_footer)); + + last_header->is_hole = 1; + last_header->magic = HEAP_MAGIC; + last_header->size = quantity; + + last_footer->magic = HEAP_MAGIC; + last_footer->header = last_header; + + heapIdx_insert(heap, last_header); + } + + heap->end_addr = newEnd; + + return 1; +} + +static void heap_contract(struct heap *heap) { + struct heap_footer *last_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); + struct heap_header *last_header = last_footer->header; + + if (last_header->is_hole == 0) return; + + size_t quantity = 0; + while ((heap->end_addr - heap->start_addr) - quantity > HEAP_MIN_SIZE && + (last_header->size - quantity) > 0x1000) + quantity += 0x1000; + if (quantity == 0) return; + + size_t newEnd = heap->end_addr - quantity; + + heapIdx_remove(heap, last_header); + last_header->size -= quantity; + last_footer = (struct heap_footer*)((size_t)last_footer - quantity); + last_footer->magic = HEAP_MAGIC; + last_footer->header = last_header; + heapIdx_insert(heap, last_header); + + for (heap->end_addr -= 0x1000; heap->end_addr >= newEnd; heap->end_addr -= 0x1000) { + page_unmapFree(pagedir_getPage(kernel_pagedir, heap->end_addr, 0)); + } +} + +void* heap_alloc(struct heap *heap, size_t sz) { + size_t newsize = sz + sizeof(struct heap_header) + sizeof(struct heap_footer); + uint32_t iterator = 0; + + while (iterator < heap->idxused) { + if (heap->idx[iterator]->size >= newsize) break; + iterator++; + } + + if (iterator == heap->idxused) { //No hole is big enough + if (heap_expand(heap, (sz & 0xFFFFF000) + 0x1000) == 0) return 0; //FAILED + return heap_alloc(heap, sz); + } + + struct heap_header *loc = heap->idx[iterator]; + struct heap_footer *footer = (struct heap_footer*)((size_t)loc + loc->size - sizeof(struct heap_footer)); + loc->is_hole = 0; + heapIdx_remove(heap, loc); + + //If we have enough space to create a USEFUL new hole next to the allocated block, do it. + //If we do not, we might return a block that is a few bytes bigger than neede. + if (loc->size > (newsize + sizeof(struct heap_header) + sizeof(struct heap_footer))) { + loc->size = newsize; + + //Write footer for block we return + struct heap_footer *newfooter = (struct heap_footer*)((size_t)loc + newsize - sizeof(struct heap_footer)); + newfooter->header = loc; + newfooter->magic = HEAP_MAGIC; + + //Write header for new hole we create + struct heap_header *nextloc = (struct heap_header*)((size_t)loc + newsize); + nextloc->is_hole = 1; + nextloc->magic = HEAP_MAGIC; + nextloc->size = ((size_t)footer - (size_t)nextloc + sizeof(struct heap_footer)); + footer->header = nextloc; //Update footer + footer->magic = HEAP_MAGIC; + + heapIdx_insert(heap, nextloc); + } + + return (void*)((size_t)loc + sizeof(struct heap_header)); +} + +void heap_free(struct heap *heap, void* ptr) { + if (ptr == 0) return; + if ((size_t)ptr < heap->start_addr || (size_t)ptr > heap->end_addr) return; + + struct heap_header *header = (struct heap_header*)((size_t)ptr - sizeof(struct heap_header)); + struct heap_footer *footer = (struct heap_footer*)((size_t)header + header->size - sizeof(struct heap_footer)); + if (header->magic != HEAP_MAGIC || footer->magic != HEAP_MAGIC) return; + + //Unify left + struct heap_footer *prev_footer = (struct heap_footer*)((size_t)header - sizeof(struct heap_footer)); + if (prev_footer->magic == HEAP_MAGIC && prev_footer->header->is_hole) { + header = prev_footer->header; + heapIdx_remove(heap, header); + + footer->header = header; + header->size = ((size_t)footer - (size_t)header + sizeof(struct heap_footer)); + } + + //Unify right + struct heap_header *next_header = (struct heap_header*)((size_t)footer + sizeof(struct heap_footer)); + if (next_header->magic == HEAP_MAGIC && next_header->is_hole) { + heapIdx_remove(heap, next_header); + footer = (struct heap_footer*)((size_t)footer + next_header->size); + + footer->header = header; + header->size = ((size_t)footer - (size_t)header + sizeof(struct heap_footer)); + } + + header->is_hole = 1; + + heapIdx_insert(heap, header); + + if ((size_t)footer == (heap->end_addr - sizeof(struct heap_footer)) && + header->size >= 0x2000 && (heap->end_addr - heap->start_addr > HEAP_MIN_SIZE)) { + heap_contract(heap); + } +} diff --git a/src/kernel/mem/heap.h b/src/kernel/mem/heap.h new file mode 100644 index 0000000..39ba37e --- /dev/null +++ b/src/kernel/mem/heap.h @@ -0,0 +1,27 @@ +#ifndef DEF_HEAP_H +#define DEF_HEAP_H + +#include "types.h" + +struct heap_header { + uint32_t magic; + uint32_t is_hole; + size_t size; +}; + +struct heap_footer { + uint32_t magic; + struct heap_header *header; +}; + +struct heap { + struct heap_header **idx; + uint32_t idxused; + size_t start_addr, end_addr, max_end; +}; + +void heap_create(struct heap *heap, size_t start, size_t idxsize, size_t datasize, size_t maxdatasize); +void* heap_alloc(struct heap *heap, size_t sz); +void heap_free(struct heap *heap, void* ptr); + +#endif diff --git a/src/kernel/mem/mem.c b/src/kernel/mem/mem.c new file mode 100644 index 0000000..2f7e1c8 --- /dev/null +++ b/src/kernel/mem/mem.c @@ -0,0 +1,95 @@ +#include "mem.h" +#include +#include +#include "paging.h" +#include "heap.h" + +#define FREEPAGESTOKEEP 5 + +#define KHEAP_IDXSIZE 0x1000 +#define KHEAP_INITSIZE 0x8000 +#define KHEAP_MAXSIZE 0x08000000 + +size_t mem_placementAddr; +static uint32_t kheap_working = 0; + + +// ****************************** +// PAGE ALLOCATION +// **************************** +static struct freepage { + size_t virt, phys; +} freepages[FREEPAGESTOKEEP]; +uint32_t freepagecount = 0; + +static void get_free_pages() { + static uint32_t locked = 0; + uint32_t i; + if (locked) return; + locked = 1; + while (freepagecount < FREEPAGESTOKEEP) { + if (kheap_working) { + for (i = 0xFFFFF000; i >= 0xF0000000; i -= 0x1000) { + if (pagedir_getPage(kernel_pagedir, i, 1)->frame == 0) break; + } + freepages[freepagecount].virt = i; + freepages[freepagecount].phys = frame_alloc() * 0x1000; + page_map(pagedir_getPage(kernel_pagedir, i, 0), freepages[freepagecount].phys / 0x1000, 0, 0); + freepagecount++; + } else { + if (mem_placementAddr & 0xFFFFF000) { + mem_placementAddr &= 0xFFFFF000; + mem_placementAddr += 0x1000; + } + freepages[freepagecount].virt = (size_t)kmalloc(0x1000); + freepages[freepagecount].phys = freepages[freepagecount].virt - 0xE0000000; + freepagecount++; + } + } + locked = 0; +} + +void* kmalloc_page(size_t *phys) { + cli(); + get_free_pages(); + freepagecount--; + *phys = freepages[freepagecount].phys; + size_t tmp = freepages[freepagecount].virt; + sti(); + return (void*)tmp; +} + +void kfree_page(void* ptr) { + size_t addr = (size_t)ptr; + if (kheap_working) { //With this we can know if paging works + page_unmapFree(pagedir_getPage(kernel_pagedir, addr, 0)); + } +} + +//*********************************** +// NORMAL MEMORY ALLOCATION +// ************************* + +static struct heap kheap; + +void kheap_init() { + heap_create(&kheap, (mem_placementAddr & 0xFFFFF000) + 0x1000, KHEAP_IDXSIZE, KHEAP_INITSIZE, KHEAP_MAXSIZE); + kheap_working = 1; + monitor_write("Kernel heap ok\n"); +} + +void* kmalloc(size_t size) { + if (kheap_working) { + return heap_alloc(&kheap, size); + } else { + size_t tmp = mem_placementAddr; + mem_placementAddr += size; + return (void*)tmp; + } +} + +void kfree(void* ptr) { + if (kheap_working) { + heap_free(&kheap, ptr); + } +} diff --git a/src/kernel/mem/mem.h b/src/kernel/mem/mem.h new file mode 100644 index 0000000..5417d5f --- /dev/null +++ b/src/kernel/mem/mem.h @@ -0,0 +1,17 @@ +#ifndef DEF_MEM_H +#define DEF_MEM_H + +#include + +void* kmalloc_page(size_t *phys); +void kfree_page(void* page); +void* kmalloc(size_t size); +void kfree(void* ptr); + +void kheap_init(); + +extern size_t mem_placementAddr; +extern void end; //Symbol defined by linker : end of kernel code + +#endif + diff --git a/src/kernel/mem/paging.c b/src/kernel/mem/paging.c new file mode 100644 index 0000000..27ce043 --- /dev/null +++ b/src/kernel/mem/paging.c @@ -0,0 +1,171 @@ +#include "paging.h" +#include +#include +#include +#include "mem.h" +#include "seg.h" +#include +#include + +static struct bitset frames; + +struct page_directory *kernel_pagedir, *current_pagedir; + +/* ACCESSOR FUNCTIONS FOR STATIC BITSET */ +uint32_t frame_alloc() { + uint32_t free = bitset_firstFree(&frames); + bitset_set(&frames, free); + return free; +} + +void frame_free(uint32_t id) { + bitset_clear(&frames, id); +} + + +void paging_init(size_t totalRam) { + uint32_t i; + + frames.size = totalRam / 0x1000; + frames.bits = kmalloc(INDEX_FROM_BIT(frames.size)); + + kernel_pagedir = kmalloc(sizeof(struct page_directory)); + kernel_pagedir->mappedSegs = 0; + kernel_pagedir->tablesPhysical = kmalloc_page(&kernel_pagedir->physicalAddr); + for (i = 0; i < 1024; i++) { + kernel_pagedir->tables[i] = 0; + kernel_pagedir->tablesPhysical[i] = 0; + } + + for (i = 0xE0000000; i < mem_placementAddr; i += 0x1000) { + page_map(pagedir_getPage(kernel_pagedir, i, 1), frame_alloc(), 0, 0); + } + for (i = 0; i < (mem_placementAddr - 0xE0000000) / 0x100000; i++) { + kernel_pagedir->tablesPhysical[i] = kernel_pagedir->tablesPhysical[i + 896]; + kernel_pagedir->tables[i] = kernel_pagedir->tables[i + 896]; + } + + monitor_write("Page dir is at: "); + monitor_writeHex(kernel_pagedir->physicalAddr); + pagedir_switch(kernel_pagedir); + monitor_write("\nPaging started\n"); +} + +void paging_cleanup() { + uint32_t i; + for (i = 0; i < (mem_placementAddr - 0xE0000000) / 0x100000; i++) { + kernel_pagedir->tablesPhysical[i] = 0; + kernel_pagedir->tables[i] = 0; + } + monitor_write("Pages cleaned up\n"); +} + +void pagedir_switch(struct page_directory *pd) { + current_pagedir = pd; + asm volatile("mov %0, %%cr3" : : "r"(pd->physicalAddr)); + uint32_t cr0; + asm volatile("mov %%cr0, %0" : "=r"(cr0)); + cr0 |= 0x80000000; + asm volatile("mov %0, %%cr0" : : "r"(cr0)); +} + +struct page_directory *pagedir_new() { + uint32_t i; + + struct page_directory *pd = kmalloc(sizeof(struct page_directory)); + pd->tablesPhysical = kmalloc_page(&pd->physicalAddr); + pd->mappedSegs = 0; + + for (i = 0; i < 1024; i++) { + pd->tables[i] = 0; pd->tablesPhysical[i] = 0; + } + + for (i = 896; i < 1024; i++) { + pd->tables[i] = kernel_pagedir->tables[i]; + pd->tablesPhysical[i] = kernel_pagedir->tablesPhysical[i]; + } + + return pd; +} + +void pagedir_delete(struct page_directory *pd) { + uint32_t i; + //Unmap segments + while (pd->mappedSegs != 0) seg_unmap(pd->mappedSegs); + //Cleanup page tables + for (i = 0; i < 896; i++) { + kfree_page(pd->tables[i]); + } + kfree_page(pd->tablesPhysical); + kfree(pd); +} + +uint32_t paging_fault(struct registers *regs) { + size_t addr; + struct segment_map *seg = 0; + asm volatile("mov %%cr2, %0" : "=r"(addr)); + + seg = current_pagedir->mappedSegs; + while (seg) { + if (seg->start <= addr && seg->start + seg->len > addr) break; + seg = seg->next; + } + + if (seg != 0) { + if (seg->seg->handle_fault(seg, addr, (regs->err_code & 0x2) && (regs->eip < 0xE0000000)) != 0) seg = 0; + } + + if (seg == 0) { + monitor_write("(paging.c:119) Unhandled Page Fault "); + if (regs->err_code & 0x1) monitor_write("present "); + if (regs->err_code & 0x2) monitor_write("write "); + if (regs->err_code & 0x4) monitor_write("user "); + if (regs->err_code & 0x8) monitor_write("rsvd "); + if (regs->err_code & 0x10) monitor_write("instructionfetch "); + monitor_write("@"); monitor_writeHex(addr); monitor_write("\n"); + return 1; + } + return 0; +} + +struct page *pagedir_getPage(struct page_directory *pd, uint32_t address, int make) { + address /= 0x1000; + uint32_t table_idx = address / 1024; + + if (pd->tables[table_idx]) { + return &pd->tables[table_idx]->pages[address % 1024]; + } else if (make) { + pd->tables[table_idx] = kmalloc_page(pd->tablesPhysical + table_idx); + if (table_idx >= 896) + tasking_updateKernelPagetable(table_idx, pd->tables[table_idx], pd->tablesPhysical[table_idx]); + memset((uint8_t*)pd->tables[table_idx], 0, 0x1000); + pd->tablesPhysical[table_idx] |= 0x07; + return &pd->tables[table_idx]->pages[address % 1024]; + } else { + return 0; + } +} + +void page_map(struct page *page, uint32_t frame, uint32_t user, uint32_t rw) { + if (page != 0 && page->frame == 0 && page->present == 0) { + page->present = 1; + page->rw = (rw ? 1 : 0); + page->user = (user ? 1 : 0); + page->frame = frame; + } +} + +void page_unmap(struct page *page) { + if (page != 0) { + page->frame = 0; + page->present = 0; + } +} + +void page_unmapFree(struct page *page) { + if (page != 0) { + if (page->frame != 0) frame_free(page->frame); + page->frame = 0; + page->present = 0; + } +} diff --git a/src/kernel/mem/paging.h b/src/kernel/mem/paging.h new file mode 100644 index 0000000..cb76cd6 --- /dev/null +++ b/src/kernel/mem/paging.h @@ -0,0 +1,46 @@ +#ifndef DEF_PAGING_H +#define DEF_PAGING_H + +#include +#include + +struct page { + uint32_t present : 1; //Page mapped to a frame ? + uint32_t rw : 1; //Page read/write ? + uint32_t user : 1; //Page user readable ? + uint32_t accessed : 1; //Was page accessed ? + uint32_t dirty : 1; //Was page modified ? + uint32_t unused : 7; + uint32_t frame : 20; //Frame address (physical address) +}; + +struct page_table { + struct page pages[1024]; +}; + +struct segment_map; +struct page_directory { + struct page_table *tables[1024]; //Virtual addresses of page tables + uint32_t *tablesPhysical; //Pointer to the virtual address of the page directory (contain phys addr of pt) + uint32_t physicalAddr; //Physical address of info above + struct segment_map *mappedSegs; +}; + +extern struct page_directory *kernel_pagedir; + +uint32_t frame_alloc(); +void frame_free(uint32_t id); + +void paging_init(size_t totalRam); +void paging_cleanup(); +void pagedir_switch(struct page_directory *pd); +struct page_directory *pagedir_new(); //Creates a brand new empty page directory for a process, with kernel pages +void pagedir_delete(struct page_directory *pagedir); +struct page *pagedir_getPage(struct page_directory *pd, uint32_t address, int make); +void page_map(struct page *page, uint32_t frame, uint32_t user, uint32_t rw); +void page_unmap(struct page *page); +void page_unmapFree(struct page *page); + +uint32_t paging_fault(struct registers *regs); //returns a boolean : 1 if unhandled, 0 if ok + +#endif diff --git a/src/kernel/mem/seg.c b/src/kernel/mem/seg.c new file mode 100644 index 0000000..1452d61 --- /dev/null +++ b/src/kernel/mem/seg.c @@ -0,0 +1,73 @@ +#include "seg.h" +#include "mem.h" + +struct segment_map *seg_map(struct segment* seg, struct page_directory *pagedir) { + struct segment_map *sm = seg->map(seg, pagedir); + if (sm == 0) return 0; + seg->mappings++; + sm->seg = seg; + sm->pagedir = pagedir; + sm->next = pagedir->mappedSegs; + pagedir->mappedSegs = sm; + return sm; +} + +void seg_unmap(struct segment_map *map) { + map->seg->unmap(map); + if (map->pagedir->mappedSegs == map) { + map->pagedir->mappedSegs = map->pagedir->mappedSegs->next; + } else { + struct segment_map *m = map->pagedir->mappedSegs; + while (m->next != 0 && m->next != map) m = m->next; + if (m->next == map) m->next = map->next; + } + map->seg->mappings--; + if (map->seg->mappings == 0) { + map->seg->delete(map->seg); + kfree(map->seg->seg_data); + kfree(map->seg); + } + kfree (map); +} + +// ************************************ SIMPLESEG stuff ************* + +struct segment* simpleseg_make(size_t start, size_t len, int writable) { + struct simpleseg *ss = kmalloc(sizeof(struct simpleseg)); + struct segment *se = kmalloc(sizeof(struct segment)); + se->seg_data = ss; + se->mappings = 0; + se->map = simpleseg_map; + se->unmap = simpleseg_unmap; + se->delete = simpleseg_delete; + se->handle_fault = simpleseg_handleFault; + ss->writable = writable; ss->start = start; ss->len = len; + return se; +} + +struct segment_map* simpleseg_map(struct segment* seg, struct page_directory* pagedir) { + struct segment_map *sm = kmalloc(sizeof(struct segment_map)); + sm->start = ((struct simpleseg*)(seg->seg_data))->start; + sm->len = ((struct simpleseg*)(seg->seg_data))->len; + return sm; +} + +void simpleseg_unmap(struct segment_map* sm) { + size_t i; + for (i = sm->start; i < sm->start + sm->len; i += 0x1000) { + page_unmapFree(pagedir_getPage(sm->pagedir, i, 0)); + } +} + +int simpleseg_handleFault(struct segment_map* sm, size_t addr, int write) { + struct simpleseg *ss = sm->seg->seg_data; + if (write && !ss->writable) return 1; + addr &= 0xFFFFF000; + struct page *p = pagedir_getPage(sm->pagedir, addr, 1); + if (p->frame != 0) return 1; + page_map(p, frame_alloc(), 1, ss->writable); + return 0; +} + +void simpleseg_delete(struct segment* seg) { +} diff --git a/src/kernel/mem/seg.h b/src/kernel/mem/seg.h new file mode 100644 index 0000000..022d38e --- /dev/null +++ b/src/kernel/mem/seg.h @@ -0,0 +1,40 @@ +#ifndef DEF_SEG_H +#define DEF_SEG_H + +#include "paging.h" + +struct segment_map; +struct segment { + void* seg_data; + int mappings; + + struct segment_map* (*map)(struct segment* seg, struct page_directory* pagedir); + void (*unmap)(struct segment_map*); + void (*delete)(struct segment* seg); + int (*handle_fault)(struct segment_map* map, size_t addr, int write); //0 if ok, 1 if segfault +}; + +struct segment_map { + struct segment* seg; + struct page_directory* pagedir; + size_t start, len; + struct segment_map *next; +}; + +struct segment_map *seg_map(struct segment* seg, struct page_directory* pagedir); +void seg_unmap(struct segment_map* map); + +/// ************************************* SIMPLESEG stuff ***************** + +struct simpleseg { + int writable; + size_t start, len; +}; + +struct segment* simpleseg_make(size_t start, size_t len, int writable); +struct segment_map* simpleseg_map(struct segment* seg, struct page_directory* pagedir); +void simpleseg_unmap(struct segment_map*); +void simpleseg_delete(struct segment *seg); +int simpleseg_handleFault(struct segment_map* map, size_t addr, int write); + +#endif diff --git a/src/kernel/task/idt.c b/src/kernel/task/idt.c new file mode 100644 index 0000000..360ac91 --- /dev/null +++ b/src/kernel/task/idt.c @@ -0,0 +1,191 @@ +#include "idt.h" +#include +#include +#include +#include "task.h" +#include "syscall.h" + +#include + +extern void isr0(); +extern void isr1(); +extern void isr2(); +extern void isr3(); +extern void isr4(); +extern void isr5(); +extern void isr6(); +extern void isr7(); +extern void isr8(); +extern void isr9(); +extern void isr10(); +extern void isr11(); +extern void isr12(); +extern void isr13(); +extern void isr14(); +extern void isr15(); +extern void isr16(); +extern void isr17(); +extern void isr18(); +extern void isr19(); +extern void isr20(); +extern void isr21(); +extern void isr22(); +extern void isr23(); +extern void isr24(); +extern void isr25(); +extern void isr26(); +extern void isr27(); +extern void isr28(); +extern void isr29(); +extern void isr30(); +extern void isr31(); + +extern void irq0(); +extern void irq1(); +extern void irq2(); +extern void irq3(); +extern void irq4(); +extern void irq5(); +extern void irq6(); +extern void irq7(); +extern void irq8(); +extern void irq9(); +extern void irq10(); +extern void irq11(); +extern void irq12(); +extern void irq13(); +extern void irq14(); +extern void irq15(); + +extern void syscall64(); + +extern void idt_flush(int32_t ptr); + +struct idt_entry idt_entries[256]; +struct idt_ptr idt_ptr; + +static int_callback irq_handlers[16] = {0}; + +void idt_isrHandler(struct registers regs) { + if ((regs.int_no == 14 && paging_fault(®s) != 0) || regs.int_no != 14) { + if (tasking_handleException(®s) == 0) { + monitor_write(" >> >> SOMETHING BAD HAPPENNED << <<\n"); + monitor_write("Unhandled exception "); + monitor_writeHex(regs.int_no); + monitor_write(" @"); monitor_writeHex(regs.eip); + monitor_put('\n'); + PANIC("unhandled exception"); + } + } +} + +void idt_irqHandler(struct registers regs) { + uint32_t doSwitch = 0; + doSwitch |= (regs.int_no == 32); //IRQ0 = timer + if (regs.err_code > 7) { + outb(0xA0, 0x20); + } + outb(0x20, 0x20); + if (irq_handlers[regs.err_code] != 0) { + irq_handlers[regs.err_code](®s); + } else { + monitor_write("Unhandled IRQ "); monitor_writeHex(regs.int_no - 32); monitor_write("\n"); + } + if (doSwitch) tasking_switch(); +} + +void idt_syscallHandler(struct registers regs) { + if (syscalls[regs.eax] != 0) { + syscalls[regs.eax](®s); + } else { + PANIC("unhandled syscall"); + } +} + +static void idt_setGate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) { + idt_entries[num].base_lo = base & 0xFFFF; + idt_entries[num].base_hi = (base >> 16) & 0xFFFF; + + idt_entries[num].sel = sel; + idt_entries[num].always0 = 0; + idt_entries[num].flags = flags; +} + +void idt_init() { + idt_ptr.limit = (sizeof(struct idt_entry) * 256) - 1; + idt_ptr.base = (uint32_t)&idt_entries; + + memset((uint8_t*)&idt_entries, 0, sizeof(struct idt_entry) * 256); + + //Remap the IRQ table + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0x21, 0x20); + outb(0xA1, 0x28); + outb(0x21, 0x04); + outb(0xA1, 0x02); + outb(0x21, 0x01); + outb(0xA1, 0x01); + outb(0x21, 0x0); + outb(0xA1, 0x0); + + idt_setGate(0, (int32_t)isr0, 0x08, 0x8E); + idt_setGate(1, (int32_t)isr1, 0x08, 0x8E); + idt_setGate(2, (int32_t)isr2, 0x08, 0x8E); + idt_setGate(3, (int32_t)isr3, 0x08, 0x8E); + idt_setGate(4, (int32_t)isr4, 0x08, 0x8E); + idt_setGate(5, (int32_t)isr5, 0x08, 0x8E); + idt_setGate(6, (int32_t)isr6, 0x08, 0x8E); + idt_setGate(7, (int32_t)isr7, 0x08, 0x8E); + idt_setGate(8, (int32_t)isr8, 0x08, 0x8E); + idt_setGate(9, (int32_t)isr9, 0x08, 0x8E); + idt_setGate(10, (int32_t)isr10, 0x08, 0x8E); + idt_setGate(11, (int32_t)isr11, 0x08, 0x8E); + idt_setGate(12, (int32_t)isr12, 0x08, 0x8E); + idt_setGate(13, (int32_t)isr13, 0x08, 0x8E); + idt_setGate(14, (int32_t)isr14, 0x08, 0x8E); + idt_setGate(15, (int32_t)isr15, 0x08, 0x8E); + idt_setGate(16, (int32_t)isr16, 0x08, 0x8E); + idt_setGate(17, (int32_t)isr17, 0x08, 0x8E); + idt_setGate(18, (int32_t)isr18, 0x08, 0x8E); + idt_setGate(19, (int32_t)isr19, 0x08, 0x8E); + idt_setGate(20, (int32_t)isr20, 0x08, 0x8E); + idt_setGate(21, (int32_t)isr21, 0x08, 0x8E); + idt_setGate(22, (int32_t)isr22, 0x08, 0x8E); + idt_setGate(23, (int32_t)isr23, 0x08, 0x8E); + idt_setGate(24, (int32_t)isr24, 0x08, 0x8E); + idt_setGate(25, (int32_t)isr25, 0x08, 0x8E); + idt_setGate(26, (int32_t)isr26, 0x08, 0x8E); + idt_setGate(27, (int32_t)isr27, 0x08, 0x8E); + idt_setGate(28, (int32_t)isr28, 0x08, 0x8E); + idt_setGate(29, (int32_t)isr29, 0x08, 0x8E); + idt_setGate(30, (int32_t)isr30, 0x08, 0x8E); + idt_setGate(31, (int32_t)isr31, 0x08, 0x8E); + + idt_setGate(32, (int32_t)irq0, 0x08, 0x8E); + idt_setGate(33, (int32_t)irq1, 0x08, 0x8E); + idt_setGate(34, (int32_t)irq2, 0x08, 0x8E); + idt_setGate(35, (int32_t)irq3, 0x08, 0x8E); + idt_setGate(36, (int32_t)irq4, 0x08, 0x8E); + idt_setGate(37, (int32_t)irq5, 0x08, 0x8E); + idt_setGate(38, (int32_t)irq6, 0x08, 0x8E); + idt_setGate(39, (int32_t)irq7, 0x08, 0x8E); + idt_setGate(40, (int32_t)irq8, 0x08, 0x8E); + idt_setGate(41, (int32_t)irq9, 0x08, 0x8E); + idt_setGate(42, (int32_t)irq10, 0x08, 0x8E); + idt_setGate(43, (int32_t)irq11, 0x08, 0x8E); + idt_setGate(44, (int32_t)irq12, 0x08, 0x8E); + idt_setGate(45, (int32_t)irq13, 0x08, 0x8E); + idt_setGate(46, (int32_t)irq14, 0x08, 0x8E); + idt_setGate(47, (int32_t)irq15, 0x08, 0x8E); + + idt_setGate(64, (int32_t)syscall64, 0x08, 0x8E); + + idt_flush((int32_t)&idt_ptr); + + monitor_write("IDT ok\n"); +} + +void idt_handleIrq(int number, int_callback func) { + irq_handlers[number] = func; +} diff --git a/src/kernel/task/idt.h b/src/kernel/task/idt.h new file mode 100644 index 0000000..bb89013 --- /dev/null +++ b/src/kernel/task/idt.h @@ -0,0 +1,33 @@ +#ifndef DEF_IDT_H +#define DEF_IDT_H + +#include + +struct idt_entry { + uint16_t base_lo; //Low part of address to jump to + uint16_t sel; //Kernel segment selector + uint8_t always0; + uint8_t flags; //Flags + uint16_t base_hi; //High part of address to jump to +} __attribute__((packed)); + +struct idt_ptr { + uint16_t limit; + uint32_t base; +} __attribute__((packed)); + +struct registers { + uint32_t cr3; //page directory physical address + uint32_t ds; // Data segment selector + uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha. + uint32_t int_no, err_code; // Interrupt number and error code (if applicable) + uint32_t eip, cs, eflags, useresp, ss; // Pushed by the processor automatically. +}; + +typedef void (*int_callback)(struct registers*); + +void idt_init(); +void idt_handleIrq(int number, int_callback func); + +#endif + diff --git a/src/kernel/task/idt_.asm b/src/kernel/task/idt_.asm new file mode 100644 index 0000000..63d1570 --- /dev/null +++ b/src/kernel/task/idt_.asm @@ -0,0 +1,155 @@ +; UNRELATED + +[GLOBAL gdt_flush] + +gdt_flush: + mov eax, [esp+4] + lgdt [eax] + + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp 0x08:.flush + +.flush: + ret + +; RELATED + +[GLOBAL idt_flush] +idt_flush: + mov eax, [esp+4] ; Get the pointer to the IDT, passed as a parameter. + lidt [eax] ; Load the IDT pointer. + ret + +;************************************************************************************ + +%macro COMMONSTUB 1 +[EXTERN idt_%1Handler] +%1_common_stub: + pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax + + mov ax, ds ; Lower 16-bits of eax = ds. + push eax ; save the data segment descriptor + + mov ax, 0x10 ; load the kernel data segment descriptor + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + mov eax, cr3 + push eax + + call idt_%1Handler + + pop eax + mov cr3, eax + + pop eax ; reload the original data segment descriptor + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + popa ; Pops edi,esi,ebp... + add esp, 8 ; Cleans up the pushed error code and pushed ISR number + sti + iret +%endmacro + +COMMONSTUB isr +COMMONSTUB irq +COMMONSTUB syscall + +;************************************************************************************ + +%macro ISR_NOERRCODE 1 ; define a macro, taking one parameter + [GLOBAL isr%1] ; %1 accesses the first parameter. + isr%1: + cli + push byte 0 + push byte %1 + jmp isr_common_stub +%endmacro + +%macro ISR_ERRCODE 1 + [GLOBAL isr%1] + isr%1: + cli + push byte %1 + jmp isr_common_stub +%endmacro + +%macro IRQ 2 + [GLOBAL irq%1] + irq%1: + cli + push byte %1 ;push irq number + push byte %2 ;push int number + jmp irq_common_stub +%endmacro + +%macro SYSCALL 1 + [GLOBAL syscall%1] + syscall%1: + cli + push byte 0 + push byte %1 + jmp syscall_common_stub +%endmacro + +ISR_NOERRCODE 0 +ISR_NOERRCODE 1 +ISR_NOERRCODE 2 +ISR_NOERRCODE 3 +ISR_NOERRCODE 4 +ISR_NOERRCODE 5 +ISR_NOERRCODE 6 +ISR_NOERRCODE 7 +ISR_ERRCODE 8 +ISR_NOERRCODE 9 +ISR_ERRCODE 10 +ISR_ERRCODE 11 +ISR_ERRCODE 12 +ISR_ERRCODE 13 +ISR_ERRCODE 14 +ISR_NOERRCODE 15 +ISR_NOERRCODE 16 +ISR_NOERRCODE 17 +ISR_NOERRCODE 18 +ISR_NOERRCODE 19 +ISR_NOERRCODE 20 +ISR_NOERRCODE 21 +ISR_NOERRCODE 22 +ISR_NOERRCODE 23 +ISR_NOERRCODE 24 +ISR_NOERRCODE 25 +ISR_NOERRCODE 26 +ISR_NOERRCODE 27 +ISR_NOERRCODE 28 +ISR_NOERRCODE 29 +ISR_NOERRCODE 30 +ISR_NOERRCODE 31 + +IRQ 0, 32 +IRQ 1, 33 +IRQ 2, 34 +IRQ 3, 35 +IRQ 4, 36 +IRQ 5, 37 +IRQ 6, 38 +IRQ 7, 39 +IRQ 8, 40 +IRQ 9, 41 +IRQ 10, 42 +IRQ 11, 43 +IRQ 12, 44 +IRQ 13, 45 +IRQ 14, 46 +IRQ 15, 47 + +SYSCALL 64 diff --git a/src/kernel/task/syscall.c b/src/kernel/task/syscall.c new file mode 100644 index 0000000..5aab011 --- /dev/null +++ b/src/kernel/task/syscall.c @@ -0,0 +1,21 @@ +#include "syscall.h" + +#define CALL0(name, scname) static void scname(struct registers* r) { r->eax = name(); } +#define CALL1(name, scname) static void scname(struct registers* r) { \ + r->eax = name(r->ebx); } +#define CALL2(name, scname) static void scname(struct registers* r) { \ + r->eax = name(r->ebx, r->ecx); } + +CALL0(thread_exit, thread_exit_sc); +CALL0(tasking_switch, schedule_sc); +CALL1(thread_sleep, thread_sleep_sc); +CALL1(process_exit, process_exit_sc); +CALL1(monitor_write, printk_sc); + +int_callback syscalls[] = { + thread_exit_sc, + schedule_sc, + thread_sleep_sc, + process_exit_sc, + printk_sc, + 0 }; diff --git a/src/kernel/task/syscall.h b/src/kernel/task/syscall.h new file mode 100644 index 0000000..54af108 --- /dev/null +++ b/src/kernel/task/syscall.h @@ -0,0 +1,9 @@ +#ifndef DEF_SYSCALL_H +#define DEF_SYSCALL_H + +#include "idt.h" + +extern int_callback syscalls[]; + +#endif + diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c new file mode 100644 index 0000000..804adc2 --- /dev/null +++ b/src/kernel/task/task.c @@ -0,0 +1,245 @@ +#include "task.h" +#include +#include +#include +#include "timer.h" + +#define KSTACKSIZE 0x8000 + +//Static routines for handling threads exiting and all cleanup +static void thread_exit_stackJmp(uint32_t reason); +static void thread_exit2(uint32_t reason); +static void thread_delete(struct thread *th); +static void process_delete(struct process *pr); + +//From task_.asm +extern uint32_t read_eip(); +extern void task_idle(void*); + +static uint32_t thread_runnable(struct thread *th); + +static uint32_t nextpid = 1; + +struct process *processes = 0, *kernel_process; +struct thread *threads = 0, *current_thread = 0, *idle_thread; + +uint32_t tasking_tmpStack[0x4000]; + +void tasking_init() { + cli(); + kernel_process = kmalloc(sizeof(struct process)); //This process must be hidden to users + kernel_process->pid = kernel_process->uid = kernel_process->threads = 0; + kernel_process->privilege = PL_KERNEL; + kernel_process->parent = kernel_process; + kernel_process->pagedir = kernel_pagedir; + kernel_process->next = 0; + current_thread = 0; + idle_thread = thread_new(kernel_process, task_idle, 0); + threads = 0; //Do not include idle thread in threads + sti(); + monitor_write("Tasking set up\n"); +} + +static struct thread *thread_next() { + if (current_thread == 0 || current_thread == idle_thread) current_thread = threads; + struct thread *ret = current_thread; + while (1) { + ret = ret->next; + if (ret == 0) ret = threads; + if (thread_runnable(ret)) { + return ret; + } + if (ret == current_thread) return idle_thread; + } +} + +void tasking_switch() { + if (threads == 0) PANIC("No more threads to run !"); + asm volatile("cli"); + + uint32_t esp, ebp, eip; + + asm volatile("mov %%esp, %0" : "=r"(esp)); + asm volatile("mov %%ebp, %0" : "=r"(ebp)); + eip = read_eip(); + + if (eip == 0x12345) { + return; + } + + if (current_thread != 0) { + current_thread->esp = esp; + current_thread->ebp = ebp; + current_thread->eip = eip; + } + + current_thread = thread_next(); + + asm volatile(" \ + mov %0, %%ebp; \ + mov %1, %%esp; \ + mov %2, %%ecx; \ + mov $0x12345, %%eax; \ + jmp *%%ecx;" + : : "r"(current_thread->ebp), "r"(current_thread->esp), "r"(current_thread->eip)); +} + +void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablephysical) { + if (idx < 896) return; + struct process* it = processes; + while (it != 0) { + it->pagedir->tables[idx] = table; + it->pagedir->tablesPhysical[idx] = tablephysical; + it = it->next; + } +} + +uint32_t tasking_handleException(struct registers *regs) { + if (current_thread == 0) return 0; //No tasking yet + monitor_write("\n(task.c:99) Unhandled exception : "); + char *exception_messages[] = {"Division By Zero","Debug","Non Maskable Interrupt","Breakpoint", + "Into Detected Overflow","Out of Bounds","Invalid Opcode","No Coprocessor", "Double Fault", + "Coprocessor Segment Overrun","Bad TSS","Segment Not Present","Stack Fault","General Protection Fault", + "Page Fault","Unknown Interrupt","Coprocessor Fault","Alignment Check","Machine Check"}; + monitor_write(exception_messages[regs->int_no]); + monitor_write(" at "); monitor_writeHex(regs->eip); + monitor_write(" >>> Thread exiting.\n"); + thread_exit_stackJmp(EX_TH_EXCEPTION); + PANIC("This should never have happened. Please report this."); +} + +void thread_sleep(uint32_t msecs) { + if (current_thread == 0) return; + current_thread->state = TS_SLEEPING; + current_thread->timeWait = timer_time() + msecs; + asm volatile("int $64" : : "a"(1)); +} + +void thread_exit2(uint32_t reason) { //See EX_TH_* defines in task.h + /* + * if reason == EX_TH_NORMAL, it is just one thread exiting because it has to + * if reason == EX_TH_EXCEPTION, it is just one thread exiting because of an exception + * if reason is none of the two cases above, it is the whole process exiting (with error code = reason) + */ + struct thread *th = current_thread; + struct process *pr = th->process; + if ((reason == EX_TH_NORMAL || reason == EX_TH_EXCEPTION) && pr->threads > 1) { + thread_delete(th); + } else { + process_delete(pr); + } + sti(); + tasking_switch(); +} + +void thread_exit_stackJmp(uint32_t reason) { + uint32_t *stack; + cli(); + stack = tasking_tmpStack + 0x4000; + stack--; *stack = reason; + stack--; *stack = 0; + asm volatile(" \ + mov %0, %%esp; \ + mov %1, %%ebp; \ + mov %2, %%ecx; \ + mov %3, %%cr3; \ + jmp *%%ecx;" : : + "r"(stack), "r"(stack), "r"(thread_exit2), "r"(kernel_pagedir->physicalAddr)); +} + +void thread_exit() { + thread_exit_stackJmp(EX_TH_NORMAL); +} + +void process_exit(uint32_t retval) { + if (retval == EX_TH_NORMAL || retval == EX_TH_EXCEPTION) retval = EX_PR_EXCEPTION; + thread_exit_stackJmp(retval); +} + +static uint32_t thread_runnable(struct thread *t) { + if (t->state == TS_RUNNING) return 1; + if (t->state == TS_SLEEPING && timer_time() >= t->timeWait) return 1; + return 0; +} + +static void thread_run(struct thread *thread, thread_entry entry_point, void *data) { + pagedir_switch(thread->process->pagedir); //TODO : take into account privilege level + asm volatile("sti"); + entry_point(data); + thread_exit(0); +} + +struct thread *thread_new(struct process *proc, thread_entry entry_point, void *data) { + struct thread *t = kmalloc(sizeof(struct thread)); + t->process = proc; + proc->threads++; + t->kernelStack_addr = kmalloc(KSTACKSIZE); + t->kernelStack_size = KSTACKSIZE; + + uint32_t *stack = (uint32_t*)((size_t)t->kernelStack_addr + t->kernelStack_size); + + //Pass parameters + stack--; *stack = (uint32_t)data; + stack--; *stack = (uint32_t)entry_point; + stack--; *stack = (uint32_t)t; + stack--; *stack = 0; + t->esp = (uint32_t)stack; + t->ebp = t->esp + 8; + t->eip = (uint32_t)thread_run; + + t->state = TS_RUNNING; + + if (threads == 0) { + threads = t; + } else { + struct thread *i = threads; + while (i->next != 0) i = i->next; + i->next = t; + } + return t; +} + +struct process *process_new(struct process* parent, uint32_t uid, uint32_t privilege) { + struct process* p = kmalloc(sizeof(struct process)); + p->pid = (nextpid++); + p->uid = uid; + p->threads = 0; + p->privilege = privilege; + p->parent = parent; + p->pagedir = pagedir_new(); + p->next = processes; + processes = p; + return p; +} + +static void thread_delete(struct thread *th) { + kfree(th->kernelStack_addr); + th->process->threads--; + if (threads == th) { + threads = th->next; + } else { + struct thread *it = threads; + while (it->next != th && it->next != 0) it = it->next; + if (it->next == th) it->next = th->next; + } + kfree(th); +} + +static void process_delete(struct process *pr) { + struct thread *it; + while (threads != 0 && threads->process == pr) thread_delete(threads); + it = threads; + while (it != 0) { + while (it->next->process == pr) thread_delete(it->next); + it = it->next; + } + pagedir_delete(pr->pagedir); + if (processes == pr) { + processes = pr->next; + } else { + struct process *it = processes; + while (it != 0 && it->next != pr) it = it->next; + if (it != 0 && it->next == pr) it->next = pr->next; + } + kfree(pr); +} diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h new file mode 100644 index 0000000..c9f1794 --- /dev/null +++ b/src/kernel/task/task.h @@ -0,0 +1,55 @@ +#ifndef DEF_TASK_H +#define DEF_TASK_H + +#include +#include +#include "idt.h" + +#define TS_RUNNING 0 +#define TS_SLEEPING 1 //Sleeping for a defined amount of time +#define TS_WAIKWAIT 2 //Waiting to be waked up by something precise (thread currently blocked) + +#define PL_USER 3 +#define PL_SERVICE 2 +#define PL_DRIVER 1 +#define PL_KERNEL 0 + +#define EX_TH_NORMAL 0x10000 //ERROR code : just one thread exits, because it has to +#define EX_TH_EXCEPTION 0x10001 //ERROR code : just one thread exits, because of an unhandled exception +#define EX_PR_EXCEPTION 0x10002 //ERROR code : all process finishes, because of an unhandled exception + +typedef void (*thread_entry)(void*); + +struct process { + uint32_t pid, uid, privilege, threads; + struct process *parent; + struct page_directory *pagedir; + + struct process *next; //Forms a linked list +}; + +struct thread { + struct process *process; + uint32_t esp, ebp, eip; + uint8_t state; + uint32_t timeWait; + void* kernelStack_addr; + uint32_t kernelStack_size; + + struct thread *next; //Forms a linked list +}; + +extern struct thread *current_thread; + +void tasking_init(); +void tasking_switch(); +void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablePhysical); +uint32_t tasking_handleException(struct registers *regs); + +void thread_sleep(uint32_t msecs); +void thread_exit(); +void process_exit(uint32_t retval); +struct thread * thread_new(struct process *proc, thread_entry entry_point, void *data); +struct process* process_new(struct process *parent, uint32_t uid, uint32_t privilege); + +#endif diff --git a/src/kernel/task/task_.asm b/src/kernel/task/task_.asm new file mode 100644 index 0000000..ae45c68 --- /dev/null +++ b/src/kernel/task/task_.asm @@ -0,0 +1,10 @@ +[GLOBAL read_eip] +read_eip: + pop eax + jmp eax + +[GLOBAL task_idle] +task_idle: + sti + hlt + jmp task_idle diff --git a/src/kernel/task/timer.c b/src/kernel/task/timer.c new file mode 100644 index 0000000..8c1a2b8 --- /dev/null +++ b/src/kernel/task/timer.c @@ -0,0 +1,36 @@ +#include "timer.h" +#include "idt.h" +#include +#include + +static uint32_t tick = 0, frequency = 0, uptime = 0; + +void timer_callback(struct registers *regs) { + tick++; + if (tick == frequency) { + uptime++; + tick = 0; + } +} + +uint32_t timer_uptime() { return uptime; } + +uint32_t timer_time() { + return (uptime * 1000) + (tick * 1000 / frequency); +} + +void timer_init(uint32_t freq) { + frequency = freq; + + idt_handleIrq(0, timer_callback); + + uint32_t divisor = 1193180 / freq; + + outb(0x43, 0x36); //Command byte + + uint8_t l = (divisor & 0xFF), h = (divisor >> 8); + outb(0x40, l); + outb(0x40, h); + + monitor_write("Timer started\n"); +} diff --git a/src/kernel/task/timer.h b/src/kernel/task/timer.h new file mode 100644 index 0000000..4909245 --- /dev/null +++ b/src/kernel/task/timer.h @@ -0,0 +1,10 @@ +#ifndef DEF_TIMER_H +#define DEF_TIMER_H + +#include + +void timer_init(uint32_t frequency); +uint32_t timer_time(); //Returns miliseconds (approximate) since computer started +uint32_t timer_uptime(); //Same thing in seconds + +#endif diff --git a/src/library/Makefile b/src/library/Makefile new file mode 100644 index 0000000..c562dec --- /dev/null +++ b/src/library/Makefile @@ -0,0 +1,34 @@ +.PHONY: clean, mrproper + +CC = gcc +CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -Wall -Wextra + +LD = ld +LDFLAGS = -r + +Library = grapes.o +Objects = grapes/syscall.o \ + start.o + +all: $(Library) + echo "* Done with library $(Library)" + +rebuild: mrproper all + +$(Library): $(Objects) + echo "* Linking library $(Library)..." + $(LD) $(LDFLAGS) $^ -o $@ + +%.uo: %.c + echo "* Compiling $<..." + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + echo "* Removing object files..." + rm *.o || exit 0 + rm -rf $(Objects) || exit 0 + +mrproper: clean + echo "* Removing library..." + rm *.o || exit 0 + rm -rf $(Library) || exit 0 diff --git a/src/library/grapes/syscall.c b/src/library/grapes/syscall.c new file mode 100644 index 0000000..5a1a26e --- /dev/null +++ b/src/library/grapes/syscall.c @@ -0,0 +1,27 @@ +#include "syscall.h" + +static int call(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f) { + unsigned ret; + asm volatile("int $64" : "=a"(ret) : "a"(a), "b"(b), "c"(c), "d"(d), "S"(e), "D"(f)); + return ret; +} + +void thread_exit() { + call(0, 0, 0, 0, 0, 0); +} + +void schedule() { + call(1, 0, 0,0, 0, 0); +} + +void thread_sleep(int time) { + call(2, time, 0, 0, 0, 0); +} + +void process_exit(int retval) { + call(3, retval, 0, 0, 0, 0); +} + +void printk(char* str) { + call(4, (unsigned)str, 0, 0, 0, 0); +} diff --git a/src/library/grapes/syscall.h b/src/library/grapes/syscall.h new file mode 100644 index 0000000..9f4c280 --- /dev/null +++ b/src/library/grapes/syscall.h @@ -0,0 +1,10 @@ +#ifndef DEF_SYSCALL_H +#define DEF_SYSCALL_H + +void thread_exit(); +void schedule(); +void thread_sleep(int time); +void process_exit(int retval); +void printk(char* str); + +#endif diff --git a/src/library/link.ld b/src/library/link.ld new file mode 100644 index 0000000..17c944a --- /dev/null +++ b/src/library/link.ld @@ -0,0 +1,27 @@ +ENTRY (start) +INPUT (grapes.o) + +SECTIONS{ + . = 0x10000000; + + .text : { + *(.text) + } + + .rodata ALIGN (0x1000) :{ + *(.rodata) + } + + .data ALIGN (0x1000) : { + *(.data) + } + + .bss : { + sbss = .; + *(COMMON) + *(.bss) + ebss = .; + } + + end = .; _end = .; __end = .; +} diff --git a/src/library/start.c b/src/library/start.c new file mode 100644 index 0000000..9324ccb --- /dev/null +++ b/src/library/start.c @@ -0,0 +1,6 @@ +extern int main(); + +void start() { + int ret = main(); + asm volatile("int $64" : : "a"(3), "b"(ret)); +} diff --git a/src/modules/test/Makefile b/src/modules/test/Makefile new file mode 100644 index 0000000..105aa54 --- /dev/null +++ b/src/modules/test/Makefile @@ -0,0 +1,32 @@ +.PHONY: clean, mrproper + +CC = gcc +CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -Wall -Wextra -I ../../library + +LD = ld +LDFLAGS = -T ../../library/link.ld -L ../../library + +Objects = main.o +Outfile = test.elf + +all: $(Outfile) + echo "* Done with $(Outfile)" + +rebuild: mrproper all + +$(Outfile): $(Objects) + echo "* Linking $@..." + $(LD) $(LDFLAGS) -o $@ $^ + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + echo "* Removing objects..." + rm *.o || exit 0 + rm $(Objects) || exit 0 + +mrproper: clean + rm *.elf || exit 0 + rm $(Outfile) || exit 0 + diff --git a/src/modules/test/main.c b/src/modules/test/main.c new file mode 100644 index 0000000..3ac5cb5 --- /dev/null +++ b/src/modules/test/main.c @@ -0,0 +1,8 @@ +#include + +int main() { + printk("[module:test] Hi world !\n"); + thread_sleep(5000); + printk("[module:test] 5sec later...\n"); + return 0; +} diff --git a/src/stem/Makefile b/src/stem/Makefile deleted file mode 100644 index fe42ea3..0000000 --- a/src/stem/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -.PHONY: clean, mrproper - -CC = gcc -CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -Wall -Wextra -I . -I ./lib - -LD = ld -LDFLAGS = -T link.ld - -ASM = nasm -AFLAGS = -f elf - -OBJECTS = core/loader_.o core/kmain.o core/sys.o \ - core/monitor.o task/timer.o \ - task/idt.o task/idt_.o task/task.o task/task_.o task/syscall.o \ - lib/stdlib.o lib/bitset.o \ - mem/mem.o mem/paging.o mem/gdt.o mem/heap.o mem/seg.o \ - linker/elf.o -OUT = stem.elf - -all: $(OBJECTS) - echo "* Linking $(OUT)..." - $(LD) $(LDFLAGS) $(OBJECTS) -o $(OUT) -Map stem.map - -clean: - rm $(OBJECTS) || exit 0 - rm *.o */*.o || exit 0 - -mrproper: clean - rm $(OUT) || exit 0 - -%.o: %.asm - echo "* Compiling $<..." - $(ASM) $(AFLAGS) -o $@ $< - -%.o: %.c - echo "* Compiling $<..." - $(CC) -c $< -o $@ $(CFLAGS) diff --git a/src/stem/core/kmain.c b/src/stem/core/kmain.c deleted file mode 100644 index d6233db..0000000 --- a/src/stem/core/kmain.c +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include "multiboot.h" -#include "monitor.h" -#include "sys.h" -#include -#include -#include -#include -#include -#include -#include - -void kmain(struct multiboot_info_t* mbd, int32_t magic) { - size_t totalRam = 0; - uint32_t i; - - mem_placementAddr = (size_t)&end; - mbd->cmdline += 0xE0000000; mbd->mods_addr += 0xE0000000; - struct module_t *mods = (struct module_t*)mbd->mods_addr; - for (i = 0; i < mbd->mods_count; i++) { - mods[i].mod_start += 0xE0000000; - mods[i].mod_end += 0xE0000000; - mods[i].string += 0xE0000000; - if (mods[i].mod_end > mem_placementAddr) - mem_placementAddr = (mods[i].mod_end & 0xFFFFF000) + 0x1000; - } - - monitor_clear(); - - if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { - PANIC("wrong multiboot magic number."); - } - - monitor_write("Grapes::Stem is booting\n"); - - idt_init(); - - totalRam = ((mbd->mem_upper + mbd->mem_lower) * 1024); - paging_init(totalRam); - gdt_init(); - paging_cleanup(); - kheap_init(); - timer_init(20); - tasking_init(); - - monitor_write("Loading modules...\n"); - for (i = 0; i < mbd->mods_count; i++) { - monitor_write((char*)mods[i].string); - if (elf_check((uint8_t*)mods[i].mod_start)) { - monitor_write(" : Invalid ELF file\n"); - } else { - if (elf_exec((uint8_t*)mods[i].mod_start) == 0) { - monitor_write(" : Error loading\n"); - } else { - monitor_write(" : OK\n"); - } - } - } - - monitor_write("Passing controll to loaded modules...\n"); - sti(); - tasking_switch(); -} diff --git a/src/stem/core/loader_.asm b/src/stem/core/loader_.asm deleted file mode 100644 index d3b92cf..0000000 --- a/src/stem/core/loader_.asm +++ /dev/null @@ -1,57 +0,0 @@ -[GLOBAL loader] ; making entry point visible to linker -[EXTERN kmain] ; kmain is defined in kmain.c -[EXTERN tasking_tmpStack] ; a temporary 4k stack used by tasking, and used when setting up kernel stuff - -; setting up the Multiboot header - see GRUB docs for details -MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries -MEMINFO equ 1<<1 ; provide memory map -FLAGS equ MODULEALIGN | MEMINFO ; this is the Multiboot 'flag' field -MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header -CHECKSUM equ -(MAGIC + FLAGS) ; checksum required - -section .text -align 4 -MultiBootHeader: - dd MAGIC - dd FLAGS - dd CHECKSUM - -section .setup -loader: ;here, we load our false GDT, used for having the kernel in higher half - lgdt [trickgdt] - mov cx, 0x10; - mov ds, cx; - mov es, cx; - mov fs, cx; - mov gs, cx; - mov ss, cx; - - jmp 0x08:higherhalf - -section .text -higherhalf: ; now we're running in higher half - - mov esp, tasking_tmpStack+0x4000 ; set up the stack - push eax ; pass Multiboot magic number - add ebx, 0xE0000000 ; update the MB info structure so that it is in the new seg - push ebx ; pass Multiboot info structure - - call kmain ; call kernel proper - - cli ; disable interupts -hang: - hlt ; halt machine should kernel return - jmp hang - -[section .setup] ; this is included in the .setup section, so that it thinks it is at 0x00100000 - -trickgdt: ; our false GDT - dw gdt_end - gdt - 1 ; gdt limit - dd gdt ; gdt base - -gdt: - dd 0, 0 ; null GDT entry - db 0xFF, 0xFF, 0, 0, 0, 10011010b, 11001111b, 0x20 ; kernel code segment - db 0xFF, 0xFF, 0, 0, 0, 10010010b, 11001111b, 0x20 ; kernel data segment - -gdt_end: diff --git a/src/stem/core/monitor.c b/src/stem/core/monitor.c deleted file mode 100644 index 8c4744a..0000000 --- a/src/stem/core/monitor.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "monitor.h" -#include "sys.h" - -static int cursor_x = 0, cursor_y = 0; -static uint16_t *video_memory = (uint16_t*)0xE00B8000; - -static void move_cursor() { - uint16_t cursor_location = cursor_y * 80 + cursor_x; - outb(0x3D4, 14); //Sending high cursor byte - outb(0x3D5, cursor_location >> 8); - outb(0x3D4, 15); //Sending high cursor byte - outb(0x3D5, cursor_location); -} - -static void scroll() { - uint8_t attribute_byte = (0 /* black */ << 4) | (7/* white */ & 0x0F); - uint16_t blank = (attribute_byte << 8) | 0x20; - - if (cursor_y >= 25) { - int i; - for (i = 0; i < 80*24; i++) { - video_memory[i] = video_memory[i+80]; - } - for (i = 80*24; i < 80*25; i++) { - video_memory[i] = blank; - } - cursor_y = 24; - } -} - -void monitor_put(char c) { - uint8_t fg = 7; //White - uint8_t bg = 0; //Black - - uint16_t attribute = (fg & 0x0F) | (bg << 4); - attribute = attribute << 8; - - if (c == 0x08 && cursor_x) { //Backspace - cursor_x--; - } else if (c == 0x09) { //Tab - cursor_x = (cursor_x + 8) & ~(8 - 1); - } else if (c == '\r') { //Carriage return - cursor_x = 0; - } else if (c == '\n') { //New line - cursor_x = 0; - cursor_y++; - } else if (c >= ' ') { //Any printable character - video_memory[cursor_y * 80 + cursor_x] = c | attribute; - cursor_x++; - } - if (cursor_x >= 80) { - cursor_x = 0; - cursor_y++; - } - - scroll(); - move_cursor(); -} - -void monitor_clear() { - uint8_t attribute_byte = (0 /* black */ << 4) | (15 /* white */ & 0x0F); - uint16_t blank = (attribute_byte << 8) | 0x20; - - int i; - - for (i = 0; i < 80*25; i++) { - video_memory[i] = blank; - } - - cursor_x = 0; cursor_y = 0; - move_cursor(); -} - -void monitor_write(char *s) { - while (*s) { - monitor_put(*(s++)); - } -} - -void monitor_writeHex(uint32_t v) { - int i; - - monitor_put('0'); monitor_put('x'); - char hexdigits[] = "0123456789abcdef"; - - for (i = 0; i < 8; i++) { - monitor_put(hexdigits[v >> 28]); - v = v << 4; - } -} diff --git a/src/stem/core/monitor.h b/src/stem/core/monitor.h deleted file mode 100644 index 3abe072..0000000 --- a/src/stem/core/monitor.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef DEF_MONITOR_H -#define DEF_MONITOR_H - -#include "types.h" - -void monitor_put(char c); -void monitor_clear(); -void monitor_write(char *s); -void monitor_writeHex(uint32_t v); - -#endif - diff --git a/src/stem/core/multiboot.h b/src/stem/core/multiboot.h deleted file mode 100644 index 908274c..0000000 --- a/src/stem/core/multiboot.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef HDR_MULTIBOOT -#define HDR_MULTIBOOT -#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 -#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 - -struct multiboot_header_t{ - unsigned long magic; - unsigned long flags; - unsigned long checksum; - unsigned long header_addr; - unsigned long load_addr; - unsigned long load_end_addr; - unsigned long bss_end_addr; - unsigned long entry_addr; -}; - -struct aout_symbol_table_t { - unsigned long tabsize; - unsigned long strsize; - unsigned long addr; - unsigned long reserved; -}; - -struct elf_section_header_table_t { - unsigned long num; - unsigned long size; - unsigned long addr; - unsigned long shndx; -}; - -struct multiboot_info_t { - unsigned long flags; - unsigned long mem_lower; - unsigned long mem_upper; - unsigned long boot_device; - unsigned long cmdline; - unsigned long mods_count; - unsigned long mods_addr; - union { - struct aout_symbol_table_t aout_sym; - struct elf_section_header_table_t elf_sec; - } u; - unsigned long mmap_length; - unsigned long mmap_addr; -}; - -struct module_t { - unsigned long mod_start; - unsigned long mod_end; - unsigned long string; - unsigned long reserved; -}; - -struct memory_map_t { - unsigned long size; - unsigned long base_addr_low; - unsigned long base_addr_high; - unsigned long length_low; - unsigned long length_high; - unsigned long type; -}; - -#endif - diff --git a/src/stem/core/sys.c b/src/stem/core/sys.c deleted file mode 100644 index d31c20e..0000000 --- a/src/stem/core/sys.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "sys.h" -#include "monitor.h" - -void outb(uint16_t port, uint8_t value) { - asm volatile("outb %1, %0" : : "dN"(port), "a"(value)); -} - -void outw(uint16_t port, uint16_t value) { - asm volatile("outw %1, %0" : : "dN"(port), "a"(value)); -} - -uint8_t inb(uint16_t port) { - uint8_t ret; - asm volatile("inb %1, %0" : "=a"(ret) : "dN"(port)); - return ret; -} - -uint16_t inw(uint16_t port) { - uint16_t ret; - asm volatile("inw %1, %0" : "=a"(ret) : "dN"(port)); - return ret; -} - -void panic(char* message, char* file, int line) { - monitor_write("\n>> PANIC: >>"); - monitor_write(message); monitor_write("<< in file "); monitor_write(file); - monitor_write("\nSystem halted T_T"); - asm volatile("cli; hlt"); -} - -static uint32_t if_locks = 1; - -void cli() { - asm volatile("cli"); - if_locks++; -} - -void sti() { - if (if_locks > 0) if_locks--; - if (if_locks == 0) asm volatile("sti"); -} diff --git a/src/stem/core/sys.h b/src/stem/core/sys.h deleted file mode 100644 index 76e3560..0000000 --- a/src/stem/core/sys.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef DEF_SYS_H -#define DEF_SYS_H - -#include "types.h" - -void outb(uint16_t port, uint8_t value); -void outw(uint16_t port, uint16_t value); -uint8_t inb(uint16_t port); -uint16_t inw(uint16_t port); - -#define PANIC(s) panic(s, __FILE__, __LINE__); -void panic(char* message, char* file, int line); - -void sti(); //GLOBAL SYSTEM MUTEX -void cli(); - -#endif diff --git a/src/stem/lib/bitset.c b/src/stem/lib/bitset.c deleted file mode 100644 index a6d334b..0000000 --- a/src/stem/lib/bitset.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "bitset.h" - -void bitset_set(struct bitset* t, uint32_t num) { - uint32_t idx = INDEX_FROM_BIT(num); - uint32_t off = OFFSET_FROM_BIT(num); - t->bits[idx] |= (0x1 << off); -} - -void bitset_clear(struct bitset* t, uint32_t num) { - uint32_t idx = INDEX_FROM_BIT(num); - uint32_t off = OFFSET_FROM_BIT(num); - t->bits[idx] &= ~(0x1 << off); -} - -uint32_t bitset_test(struct bitset* t, uint32_t num) { - uint32_t idx = INDEX_FROM_BIT(num); - uint32_t off = OFFSET_FROM_BIT(num); - return (t->bits[idx] & (0x1 << off)); -} - -uint32_t bitset_firstFree(struct bitset* t) { - uint32_t i, j; - for (i = 0; i < INDEX_FROM_BIT(t->size); i++) { - if (t->bits[i] != 0xFFFFFFFF) { - for (j = 0; j < 32; j++) { - uint32_t toTest = 0x1 << j; - if (!(t->bits[i] & toTest)) { - return i*4*8+j; - } - } - } - } - return (uint32_t) - 1; -} - diff --git a/src/stem/lib/bitset.h b/src/stem/lib/bitset.h deleted file mode 100644 index fe9e8c2..0000000 --- a/src/stem/lib/bitset.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef DEF_BITSET_H -#define DEF_BITSET_H - -#include - -#define INDEX_FROM_BIT(a) (a/(8*4)) -#define OFFSET_FROM_BIT(a) (a%(8*4)) - -struct bitset { - uint32_t *bits; - uint32_t size; -}; - -void bitset_set(struct bitset* t, uint32_t num); -void bitset_clear(struct bitset* t, uint32_t num); -uint32_t bitset_test(struct bitset* t, uint32_t num); -uint32_t bitset_firstFree(struct bitset* t); - -#endif diff --git a/src/stem/lib/stdlib.c b/src/stem/lib/stdlib.c deleted file mode 100644 index c5245e7..0000000 --- a/src/stem/lib/stdlib.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "stdlib.h" - -void *memcpy(void *vd, const void *vs, int count) { - uint8_t *dest = (uint8_t*)vd, *src = (uint8_t*)vs; - uint32_t f = count % 4, n = count / 4, i; - const uint32_t* s = (uint32_t*)src; - uint32_t* d = (uint32_t*)dest; - for (i = 0; i < n; i++) { - d[i] = s[i]; - } - if (f != 0) { - for (i = count - f; i < count; i++) { - dest[i] = src[i]; - } - } - return vd; -} - -uint8_t *memset(uint8_t *dest, uint8_t val, int count) { - int i; - for (i = 0; i < count; i++) { - dest[i] = val; - } - return dest; -} - -uint16_t *memsetw(uint16_t *dest, uint16_t val, int count) { - int i; - for (i = 0; i < count; i++) { - dest[i] = val; - } - return dest; -} - -int strlen(const char *str) { - int i = 0; - while (str[i++]); - return i; -} diff --git a/src/stem/lib/stdlib.h b/src/stem/lib/stdlib.h deleted file mode 100644 index 704c410..0000000 --- a/src/stem/lib/stdlib.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef DEF_STDLIB_H -#define DEF_STDLIB_H - -#include - -void *memcpy(void *dest, const void *src, int count); -uint8_t *memset(uint8_t *dest, uint8_t val, int count); -uint16_t *memsetw(uint16_t *dest, uint16_t val, int count); -int strlen(const char *str); - -#endif - diff --git a/src/stem/lib/types.h b/src/stem/lib/types.h deleted file mode 100644 index b7b19ab..0000000 --- a/src/stem/lib/types.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DEF_TYPES_H -#define DEF_TYPES_H - -typedef unsigned long long uint64_t; -typedef unsigned int uint32_t; -typedef unsigned short uint16_t; -typedef unsigned char uint8_t; -typedef long long int64_t; -typedef int int32_t; -typedef short int16_t; -typedef char int8_t; - -typedef unsigned int size_t; - -#endif diff --git a/src/stem/link.ld b/src/stem/link.ld deleted file mode 100644 index 1ce17cf..0000000 --- a/src/stem/link.ld +++ /dev/null @@ -1,32 +0,0 @@ -ENTRY (loader) - -SECTIONS{ - . = 0x00100000; - - .setup : { - *(.setup) - } - - . += 0xE0000000; - - .text : AT(ADDR(.text) - 0xE0000000) { - *(.text) - } - - .rodata ALIGN (0x1000) : AT(ADDR(.rodata) - 0xE0000000) { - *(.rodata) - } - - .data ALIGN (0x1000) : AT(ADDR(.data) - 0xE0000000) { - *(.data) - } - - .bss : AT(ADDR(.bss) - 0xE0000000) { - sbss = .; - *(COMMON) - *(.bss) - ebss = .; - } - - end = .; _end = .; __end = .; -} diff --git a/src/stem/linker/elf.c b/src/stem/linker/elf.c deleted file mode 100644 index dc7481b..0000000 --- a/src/stem/linker/elf.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "elf.h" -#include -#include -#include -#include - -int elf_check(uint8_t *data) { - struct elf_ehdr *h = (struct elf_ehdr*)data; - if (h->e_ident[0] == 0x7F && h->e_ident[1] == 'E' && h->e_ident[2] == 'L' && h->e_ident[3] == 'F') return 0; - return 1; -} - -thread_entry elf_load(uint8_t *data, struct process* process) { - struct elf_ehdr *ehdr = (struct elf_ehdr*)data; - struct elf_phdr *phdr; - int i; - if (elf_check(data)) return 0; - - pagedir_switch(process->pagedir); - - phdr = (struct elf_phdr*)((uint8_t*)(data + ehdr->e_phoff)); - for (i = 0; i < ehdr->e_phnum; i++) { - if (phdr[i].p_type == PT_LOAD) { - seg_map(simpleseg_make(phdr[i].p_vaddr, phdr[i].p_memsz, (phdr[i].p_flags & PF_W) != 0), process->pagedir); - memcpy((uint8_t*)phdr[i].p_vaddr, data + phdr[i].p_offset, phdr[i].p_filesz); - if (phdr[i].p_memsz > phdr[i].p_filesz) { - memset((uint8_t*)phdr[i].p_vaddr + phdr[i].p_memsz, 0, phdr[i].p_memsz - phdr[i].p_filesz); - } - } - } - return (thread_entry)ehdr->e_entry; -} - -struct process* elf_exec(uint8_t *data) { - if (elf_check(data)) return 0; - - struct process* p = process_new(0, 0, PL_DRIVER); - - thread_entry e = elf_load(data, p); - - thread_new(p, e, 0); - - return p; -} diff --git a/src/stem/linker/elf.h b/src/stem/linker/elf.h deleted file mode 100644 index f84bb62..0000000 --- a/src/stem/linker/elf.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef DEF_ELF_H -#define DEF_ELF_H - -#include -#include - -/* elf_phdr_t :: p_type : program header entries types */ -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff - -/* elf_phdr_t :: p_flags : program header entries flags */ -#define PF_X (1 << 0) -#define PF_W (1 << 1) -#define PF_R (1 << 2) - -struct elf_ehdr { - uint8_t e_ident[16]; /* ELF identification */ - uint16_t e_type; /* 2 (exec file) */ - uint16_t e_machine; /* 3 (intel architecture) */ - uint32_t e_version; /* 1 */ - uint32_t e_entry; /* starting point */ - uint32_t e_phoff; /* program header table offset */ - uint32_t e_shoff; /* section header table offset */ - uint32_t e_flags; /* various flags */ - uint16_t e_ehsize; /* ELF header (this) size */ - - uint16_t e_phentsize; /* program header table entry size */ - uint16_t e_phnum; /* number of entries */ - - uint16_t e_shentsize; /* section header table entry size */ - uint16_t e_shnum; /* number of entries */ - - uint16_t e_shstrndx; /* index of the section name string table */ -}; - -struct elf_phdr { - uint32_t p_type; /* type of segment */ - uint32_t p_offset; - uint32_t p_vaddr; - uint32_t p_paddr; - uint32_t p_filesz; - uint32_t p_memsz; - uint32_t p_flags; - uint32_t p_align; -}; - -struct phdr { - struct elf_phdr h; - uint8_t* data; -}; - -int elf_check(uint8_t *data); //0 if ok, 1 if not a valid ELF -thread_entry elf_load(uint8_t *data, struct process* process); //Load an ELF to a process, return entry point -struct process* elf_exec(uint8_t *data); //Creates a new process and a thread for running ELF file - -#endif diff --git a/src/stem/mem/gdt.c b/src/stem/mem/gdt.c deleted file mode 100644 index 5aaad41..0000000 --- a/src/stem/mem/gdt.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "gdt.h" -#include -#include - -extern void gdt_flush(uint32_t); //ASM (idt_.asm) - -#define GDT_ENTRIES 5 - -static struct gdt_entry gdt_entries[GDT_ENTRIES]; -static struct gdt_ptr gdt_ptr; - -static void gdt_setGate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { - gdt_entries[num].base_low = (base & 0xFFFF); - gdt_entries[num].base_middle = (base >> 16) & 0xFF; - gdt_entries[num].base_high = (base >> 24) & 0xFF; - - gdt_entries[num].limit_low = (limit & 0xFFFF); - gdt_entries[num].granularity = (limit >> 16) & 0x0F; - gdt_entries[num].granularity |= gran & 0xF0; - gdt_entries[num].access = access; -} - -void gdt_init() { - gdt_ptr.limit = (sizeof(struct gdt_entry) * GDT_ENTRIES) - 1; - gdt_ptr.base = (uint32_t)&gdt_entries; - - gdt_setGate(0, 0, 0, 0, 0); //Null segment - gdt_setGate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); //Kernel code segment - gdt_setGate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); //Kernel data segment - gdt_setGate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); //User code segment - gdt_setGate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); //User data segment - - gdt_flush((uint32_t)&gdt_ptr); - - monitor_write("GDT ok\n"); -} diff --git a/src/stem/mem/gdt.h b/src/stem/mem/gdt.h deleted file mode 100644 index aac16bb..0000000 --- a/src/stem/mem/gdt.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef DEF_GDT_H -#define DEF_GDT_H - -#include - -struct gdt_entry { - uint16_t limit_low; - uint16_t base_low; - uint8_t base_middle; - uint8_t access; - uint8_t granularity; - uint8_t base_high; -} __attribute__((packed)); - -struct gdt_ptr { - uint16_t limit; - uint32_t base; -} __attribute__((packed)); - -void gdt_init(); - -#endif - diff --git a/src/stem/mem/heap.c b/src/stem/mem/heap.c deleted file mode 100644 index b6d2cd4..0000000 --- a/src/stem/mem/heap.c +++ /dev/null @@ -1,224 +0,0 @@ -#include "heap.h" -#include "paging.h" - -#define HEAP_MAGIC 0xBAD0BEEF -#define HEAP_MIN_SIZE 0x4000 - -/* ******************* HEADER ****************** */ - -static void heapIdx_insert(struct heap *heap, struct heap_header *e) { - if ((heap->idxused + sizeof(struct heap_header*) + (size_t)heap->idx) >= heap->start_addr) return; - - uint32_t iterator = 0, pos; - while (iterator < heap->idxused && heap->idx[iterator]->size < e->size) { - if (heap->idx[iterator] == e) return; - iterator++; - } - if (iterator == heap->idxused) { - heap->idx[heap->idxused++] = e; - } else { - pos = iterator; - iterator = heap->idxused; - while (iterator > pos) { - heap->idx[iterator] = heap->idx[iterator - 1]; - iterator--; - } - heap->idxused++; - heap->idx[pos] = e; - } -} - -static void heapIdx_remove(struct heap *heap, struct heap_header *e) { - uint32_t iterator; - for (iterator = 0; iterator < heap->idxused; iterator++) { - if (heap->idx[iterator] == e) break; - } - if (iterator == heap->idxused) return; - heap->idxused--; - while (iterator < heap->idxused) { - heap->idx[iterator] = heap->idx[iterator + 1]; - iterator++; - } -} - -/* ******************** CONTENTS ********************* */ - -void heap_create(struct heap *heap, size_t start, size_t idxsize, size_t datasize, size_t maxdatasize) { - uint32_t i; - - if (start & 0x0FFF) start = (start & 0xFFFFF000) + 0x1000; - - heap->start_addr = start + idxsize; - heap->end_addr = start + idxsize + datasize; - heap->max_end = start + idxsize + maxdatasize; - - for (i = start; i < heap->end_addr; i += 0x1000) { - page_map(pagedir_getPage(kernel_pagedir, i, 1), frame_alloc(), 0, 0); - } - - heap->idx = (struct heap_header**)start; - heap->idxused = 0; - - struct heap_header *hole = (struct heap_header*) heap->start_addr; - hole->size = (heap->end_addr - heap->start_addr); - hole->magic = HEAP_MAGIC; - hole->is_hole = 1; - - struct heap_footer *hole_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); - hole_footer->header = hole; - hole_footer->magic = HEAP_MAGIC; - - heapIdx_insert(heap, hole); -} - -static uint32_t heap_expand(struct heap *heap, size_t quantity) { - uint32_t i; - - if (quantity & 0x0FFF) { - quantity = (quantity & 0xFFFFF000) + 0x1000; - } - - if (heap->end_addr + quantity > heap->max_end) return 0; - - size_t newEnd = heap->end_addr + quantity; - - for (i = heap->end_addr; i < newEnd; i += 0x1000) { - page_map(pagedir_getPage(kernel_pagedir, i, 1), frame_alloc(), 0, 0); - } - - struct heap_footer *last_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); - struct heap_header *last_header = last_footer->header; - if (last_header->is_hole) { - heapIdx_remove(heap, last_header); - last_header->size += quantity; - - last_footer = (struct heap_footer*)(newEnd - sizeof(struct heap_footer)); - last_footer->magic = HEAP_MAGIC; - last_footer->header = last_header; - - heapIdx_insert(heap, last_header); - } else { - last_header = (struct heap_header*)heap->end_addr; - last_footer = (struct heap_footer*)(newEnd - sizeof(struct heap_footer)); - - last_header->is_hole = 1; - last_header->magic = HEAP_MAGIC; - last_header->size = quantity; - - last_footer->magic = HEAP_MAGIC; - last_footer->header = last_header; - - heapIdx_insert(heap, last_header); - } - - heap->end_addr = newEnd; - - return 1; -} - -static void heap_contract(struct heap *heap) { - struct heap_footer *last_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); - struct heap_header *last_header = last_footer->header; - - if (last_header->is_hole == 0) return; - - size_t quantity = 0; - while ((heap->end_addr - heap->start_addr) - quantity > HEAP_MIN_SIZE && - (last_header->size - quantity) > 0x1000) - quantity += 0x1000; - if (quantity == 0) return; - - size_t newEnd = heap->end_addr - quantity; - - heapIdx_remove(heap, last_header); - last_header->size -= quantity; - last_footer = (struct heap_footer*)((size_t)last_footer - quantity); - last_footer->magic = HEAP_MAGIC; - last_footer->header = last_header; - heapIdx_insert(heap, last_header); - - for (heap->end_addr -= 0x1000; heap->end_addr >= newEnd; heap->end_addr -= 0x1000) { - page_unmapFree(pagedir_getPage(kernel_pagedir, heap->end_addr, 0)); - } -} - -void* heap_alloc(struct heap *heap, size_t sz) { - size_t newsize = sz + sizeof(struct heap_header) + sizeof(struct heap_footer); - uint32_t iterator = 0; - - while (iterator < heap->idxused) { - if (heap->idx[iterator]->size >= newsize) break; - iterator++; - } - - if (iterator == heap->idxused) { //No hole is big enough - if (heap_expand(heap, (sz & 0xFFFFF000) + 0x1000) == 0) return 0; //FAILED - return heap_alloc(heap, sz); - } - - struct heap_header *loc = heap->idx[iterator]; - struct heap_footer *footer = (struct heap_footer*)((size_t)loc + loc->size - sizeof(struct heap_footer)); - loc->is_hole = 0; - heapIdx_remove(heap, loc); - - //If we have enough space to create a USEFUL new hole next to the allocated block, do it. - //If we do not, we might return a block that is a few bytes bigger than neede. - if (loc->size > (newsize + sizeof(struct heap_header) + sizeof(struct heap_footer))) { - loc->size = newsize; - - //Write footer for block we return - struct heap_footer *newfooter = (struct heap_footer*)((size_t)loc + newsize - sizeof(struct heap_footer)); - newfooter->header = loc; - newfooter->magic = HEAP_MAGIC; - - //Write header for new hole we create - struct heap_header *nextloc = (struct heap_header*)((size_t)loc + newsize); - nextloc->is_hole = 1; - nextloc->magic = HEAP_MAGIC; - nextloc->size = ((size_t)footer - (size_t)nextloc + sizeof(struct heap_footer)); - footer->header = nextloc; //Update footer - footer->magic = HEAP_MAGIC; - - heapIdx_insert(heap, nextloc); - } - - return (void*)((size_t)loc + sizeof(struct heap_header)); -} - -void heap_free(struct heap *heap, void* ptr) { - if (ptr == 0) return; - if ((size_t)ptr < heap->start_addr || (size_t)ptr > heap->end_addr) return; - - struct heap_header *header = (struct heap_header*)((size_t)ptr - sizeof(struct heap_header)); - struct heap_footer *footer = (struct heap_footer*)((size_t)header + header->size - sizeof(struct heap_footer)); - if (header->magic != HEAP_MAGIC || footer->magic != HEAP_MAGIC) return; - - //Unify left - struct heap_footer *prev_footer = (struct heap_footer*)((size_t)header - sizeof(struct heap_footer)); - if (prev_footer->magic == HEAP_MAGIC && prev_footer->header->is_hole) { - header = prev_footer->header; - heapIdx_remove(heap, header); - - footer->header = header; - header->size = ((size_t)footer - (size_t)header + sizeof(struct heap_footer)); - } - - //Unify right - struct heap_header *next_header = (struct heap_header*)((size_t)footer + sizeof(struct heap_footer)); - if (next_header->magic == HEAP_MAGIC && next_header->is_hole) { - heapIdx_remove(heap, next_header); - footer = (struct heap_footer*)((size_t)footer + next_header->size); - - footer->header = header; - header->size = ((size_t)footer - (size_t)header + sizeof(struct heap_footer)); - } - - header->is_hole = 1; - - heapIdx_insert(heap, header); - - if ((size_t)footer == (heap->end_addr - sizeof(struct heap_footer)) && - header->size >= 0x2000 && (heap->end_addr - heap->start_addr > HEAP_MIN_SIZE)) { - heap_contract(heap); - } -} diff --git a/src/stem/mem/heap.h b/src/stem/mem/heap.h deleted file mode 100644 index 39ba37e..0000000 --- a/src/stem/mem/heap.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef DEF_HEAP_H -#define DEF_HEAP_H - -#include "types.h" - -struct heap_header { - uint32_t magic; - uint32_t is_hole; - size_t size; -}; - -struct heap_footer { - uint32_t magic; - struct heap_header *header; -}; - -struct heap { - struct heap_header **idx; - uint32_t idxused; - size_t start_addr, end_addr, max_end; -}; - -void heap_create(struct heap *heap, size_t start, size_t idxsize, size_t datasize, size_t maxdatasize); -void* heap_alloc(struct heap *heap, size_t sz); -void heap_free(struct heap *heap, void* ptr); - -#endif diff --git a/src/stem/mem/mem.c b/src/stem/mem/mem.c deleted file mode 100644 index 2f7e1c8..0000000 --- a/src/stem/mem/mem.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "mem.h" -#include -#include -#include "paging.h" -#include "heap.h" - -#define FREEPAGESTOKEEP 5 - -#define KHEAP_IDXSIZE 0x1000 -#define KHEAP_INITSIZE 0x8000 -#define KHEAP_MAXSIZE 0x08000000 - -size_t mem_placementAddr; -static uint32_t kheap_working = 0; - - -// ****************************** -// PAGE ALLOCATION -// **************************** -static struct freepage { - size_t virt, phys; -} freepages[FREEPAGESTOKEEP]; -uint32_t freepagecount = 0; - -static void get_free_pages() { - static uint32_t locked = 0; - uint32_t i; - if (locked) return; - locked = 1; - while (freepagecount < FREEPAGESTOKEEP) { - if (kheap_working) { - for (i = 0xFFFFF000; i >= 0xF0000000; i -= 0x1000) { - if (pagedir_getPage(kernel_pagedir, i, 1)->frame == 0) break; - } - freepages[freepagecount].virt = i; - freepages[freepagecount].phys = frame_alloc() * 0x1000; - page_map(pagedir_getPage(kernel_pagedir, i, 0), freepages[freepagecount].phys / 0x1000, 0, 0); - freepagecount++; - } else { - if (mem_placementAddr & 0xFFFFF000) { - mem_placementAddr &= 0xFFFFF000; - mem_placementAddr += 0x1000; - } - freepages[freepagecount].virt = (size_t)kmalloc(0x1000); - freepages[freepagecount].phys = freepages[freepagecount].virt - 0xE0000000; - freepagecount++; - } - } - locked = 0; -} - -void* kmalloc_page(size_t *phys) { - cli(); - get_free_pages(); - freepagecount--; - *phys = freepages[freepagecount].phys; - size_t tmp = freepages[freepagecount].virt; - sti(); - return (void*)tmp; -} - -void kfree_page(void* ptr) { - size_t addr = (size_t)ptr; - if (kheap_working) { //With this we can know if paging works - page_unmapFree(pagedir_getPage(kernel_pagedir, addr, 0)); - } -} - -//*********************************** -// NORMAL MEMORY ALLOCATION -// ************************* - -static struct heap kheap; - -void kheap_init() { - heap_create(&kheap, (mem_placementAddr & 0xFFFFF000) + 0x1000, KHEAP_IDXSIZE, KHEAP_INITSIZE, KHEAP_MAXSIZE); - kheap_working = 1; - monitor_write("Kernel heap ok\n"); -} - -void* kmalloc(size_t size) { - if (kheap_working) { - return heap_alloc(&kheap, size); - } else { - size_t tmp = mem_placementAddr; - mem_placementAddr += size; - return (void*)tmp; - } -} - -void kfree(void* ptr) { - if (kheap_working) { - heap_free(&kheap, ptr); - } -} diff --git a/src/stem/mem/mem.h b/src/stem/mem/mem.h deleted file mode 100644 index 5417d5f..0000000 --- a/src/stem/mem/mem.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef DEF_MEM_H -#define DEF_MEM_H - -#include - -void* kmalloc_page(size_t *phys); -void kfree_page(void* page); -void* kmalloc(size_t size); -void kfree(void* ptr); - -void kheap_init(); - -extern size_t mem_placementAddr; -extern void end; //Symbol defined by linker : end of kernel code - -#endif - diff --git a/src/stem/mem/paging.c b/src/stem/mem/paging.c deleted file mode 100644 index 27ce043..0000000 --- a/src/stem/mem/paging.c +++ /dev/null @@ -1,171 +0,0 @@ -#include "paging.h" -#include -#include -#include -#include "mem.h" -#include "seg.h" -#include -#include - -static struct bitset frames; - -struct page_directory *kernel_pagedir, *current_pagedir; - -/* ACCESSOR FUNCTIONS FOR STATIC BITSET */ -uint32_t frame_alloc() { - uint32_t free = bitset_firstFree(&frames); - bitset_set(&frames, free); - return free; -} - -void frame_free(uint32_t id) { - bitset_clear(&frames, id); -} - - -void paging_init(size_t totalRam) { - uint32_t i; - - frames.size = totalRam / 0x1000; - frames.bits = kmalloc(INDEX_FROM_BIT(frames.size)); - - kernel_pagedir = kmalloc(sizeof(struct page_directory)); - kernel_pagedir->mappedSegs = 0; - kernel_pagedir->tablesPhysical = kmalloc_page(&kernel_pagedir->physicalAddr); - for (i = 0; i < 1024; i++) { - kernel_pagedir->tables[i] = 0; - kernel_pagedir->tablesPhysical[i] = 0; - } - - for (i = 0xE0000000; i < mem_placementAddr; i += 0x1000) { - page_map(pagedir_getPage(kernel_pagedir, i, 1), frame_alloc(), 0, 0); - } - for (i = 0; i < (mem_placementAddr - 0xE0000000) / 0x100000; i++) { - kernel_pagedir->tablesPhysical[i] = kernel_pagedir->tablesPhysical[i + 896]; - kernel_pagedir->tables[i] = kernel_pagedir->tables[i + 896]; - } - - monitor_write("Page dir is at: "); - monitor_writeHex(kernel_pagedir->physicalAddr); - pagedir_switch(kernel_pagedir); - monitor_write("\nPaging started\n"); -} - -void paging_cleanup() { - uint32_t i; - for (i = 0; i < (mem_placementAddr - 0xE0000000) / 0x100000; i++) { - kernel_pagedir->tablesPhysical[i] = 0; - kernel_pagedir->tables[i] = 0; - } - monitor_write("Pages cleaned up\n"); -} - -void pagedir_switch(struct page_directory *pd) { - current_pagedir = pd; - asm volatile("mov %0, %%cr3" : : "r"(pd->physicalAddr)); - uint32_t cr0; - asm volatile("mov %%cr0, %0" : "=r"(cr0)); - cr0 |= 0x80000000; - asm volatile("mov %0, %%cr0" : : "r"(cr0)); -} - -struct page_directory *pagedir_new() { - uint32_t i; - - struct page_directory *pd = kmalloc(sizeof(struct page_directory)); - pd->tablesPhysical = kmalloc_page(&pd->physicalAddr); - pd->mappedSegs = 0; - - for (i = 0; i < 1024; i++) { - pd->tables[i] = 0; pd->tablesPhysical[i] = 0; - } - - for (i = 896; i < 1024; i++) { - pd->tables[i] = kernel_pagedir->tables[i]; - pd->tablesPhysical[i] = kernel_pagedir->tablesPhysical[i]; - } - - return pd; -} - -void pagedir_delete(struct page_directory *pd) { - uint32_t i; - //Unmap segments - while (pd->mappedSegs != 0) seg_unmap(pd->mappedSegs); - //Cleanup page tables - for (i = 0; i < 896; i++) { - kfree_page(pd->tables[i]); - } - kfree_page(pd->tablesPhysical); - kfree(pd); -} - -uint32_t paging_fault(struct registers *regs) { - size_t addr; - struct segment_map *seg = 0; - asm volatile("mov %%cr2, %0" : "=r"(addr)); - - seg = current_pagedir->mappedSegs; - while (seg) { - if (seg->start <= addr && seg->start + seg->len > addr) break; - seg = seg->next; - } - - if (seg != 0) { - if (seg->seg->handle_fault(seg, addr, (regs->err_code & 0x2) && (regs->eip < 0xE0000000)) != 0) seg = 0; - } - - if (seg == 0) { - monitor_write("(paging.c:119) Unhandled Page Fault "); - if (regs->err_code & 0x1) monitor_write("present "); - if (regs->err_code & 0x2) monitor_write("write "); - if (regs->err_code & 0x4) monitor_write("user "); - if (regs->err_code & 0x8) monitor_write("rsvd "); - if (regs->err_code & 0x10) monitor_write("instructionfetch "); - monitor_write("@"); monitor_writeHex(addr); monitor_write("\n"); - return 1; - } - return 0; -} - -struct page *pagedir_getPage(struct page_directory *pd, uint32_t address, int make) { - address /= 0x1000; - uint32_t table_idx = address / 1024; - - if (pd->tables[table_idx]) { - return &pd->tables[table_idx]->pages[address % 1024]; - } else if (make) { - pd->tables[table_idx] = kmalloc_page(pd->tablesPhysical + table_idx); - if (table_idx >= 896) - tasking_updateKernelPagetable(table_idx, pd->tables[table_idx], pd->tablesPhysical[table_idx]); - memset((uint8_t*)pd->tables[table_idx], 0, 0x1000); - pd->tablesPhysical[table_idx] |= 0x07; - return &pd->tables[table_idx]->pages[address % 1024]; - } else { - return 0; - } -} - -void page_map(struct page *page, uint32_t frame, uint32_t user, uint32_t rw) { - if (page != 0 && page->frame == 0 && page->present == 0) { - page->present = 1; - page->rw = (rw ? 1 : 0); - page->user = (user ? 1 : 0); - page->frame = frame; - } -} - -void page_unmap(struct page *page) { - if (page != 0) { - page->frame = 0; - page->present = 0; - } -} - -void page_unmapFree(struct page *page) { - if (page != 0) { - if (page->frame != 0) frame_free(page->frame); - page->frame = 0; - page->present = 0; - } -} diff --git a/src/stem/mem/paging.h b/src/stem/mem/paging.h deleted file mode 100644 index cb76cd6..0000000 --- a/src/stem/mem/paging.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef DEF_PAGING_H -#define DEF_PAGING_H - -#include -#include - -struct page { - uint32_t present : 1; //Page mapped to a frame ? - uint32_t rw : 1; //Page read/write ? - uint32_t user : 1; //Page user readable ? - uint32_t accessed : 1; //Was page accessed ? - uint32_t dirty : 1; //Was page modified ? - uint32_t unused : 7; - uint32_t frame : 20; //Frame address (physical address) -}; - -struct page_table { - struct page pages[1024]; -}; - -struct segment_map; -struct page_directory { - struct page_table *tables[1024]; //Virtual addresses of page tables - uint32_t *tablesPhysical; //Pointer to the virtual address of the page directory (contain phys addr of pt) - uint32_t physicalAddr; //Physical address of info above - struct segment_map *mappedSegs; -}; - -extern struct page_directory *kernel_pagedir; - -uint32_t frame_alloc(); -void frame_free(uint32_t id); - -void paging_init(size_t totalRam); -void paging_cleanup(); -void pagedir_switch(struct page_directory *pd); -struct page_directory *pagedir_new(); //Creates a brand new empty page directory for a process, with kernel pages -void pagedir_delete(struct page_directory *pagedir); -struct page *pagedir_getPage(struct page_directory *pd, uint32_t address, int make); -void page_map(struct page *page, uint32_t frame, uint32_t user, uint32_t rw); -void page_unmap(struct page *page); -void page_unmapFree(struct page *page); - -uint32_t paging_fault(struct registers *regs); //returns a boolean : 1 if unhandled, 0 if ok - -#endif diff --git a/src/stem/mem/seg.c b/src/stem/mem/seg.c deleted file mode 100644 index 1452d61..0000000 --- a/src/stem/mem/seg.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "seg.h" -#include "mem.h" - -struct segment_map *seg_map(struct segment* seg, struct page_directory *pagedir) { - struct segment_map *sm = seg->map(seg, pagedir); - if (sm == 0) return 0; - seg->mappings++; - sm->seg = seg; - sm->pagedir = pagedir; - sm->next = pagedir->mappedSegs; - pagedir->mappedSegs = sm; - return sm; -} - -void seg_unmap(struct segment_map *map) { - map->seg->unmap(map); - if (map->pagedir->mappedSegs == map) { - map->pagedir->mappedSegs = map->pagedir->mappedSegs->next; - } else { - struct segment_map *m = map->pagedir->mappedSegs; - while (m->next != 0 && m->next != map) m = m->next; - if (m->next == map) m->next = map->next; - } - map->seg->mappings--; - if (map->seg->mappings == 0) { - map->seg->delete(map->seg); - kfree(map->seg->seg_data); - kfree(map->seg); - } - kfree (map); -} - -// ************************************ SIMPLESEG stuff ************* - -struct segment* simpleseg_make(size_t start, size_t len, int writable) { - struct simpleseg *ss = kmalloc(sizeof(struct simpleseg)); - struct segment *se = kmalloc(sizeof(struct segment)); - se->seg_data = ss; - se->mappings = 0; - se->map = simpleseg_map; - se->unmap = simpleseg_unmap; - se->delete = simpleseg_delete; - se->handle_fault = simpleseg_handleFault; - ss->writable = writable; ss->start = start; ss->len = len; - return se; -} - -struct segment_map* simpleseg_map(struct segment* seg, struct page_directory* pagedir) { - struct segment_map *sm = kmalloc(sizeof(struct segment_map)); - sm->start = ((struct simpleseg*)(seg->seg_data))->start; - sm->len = ((struct simpleseg*)(seg->seg_data))->len; - return sm; -} - -void simpleseg_unmap(struct segment_map* sm) { - size_t i; - for (i = sm->start; i < sm->start + sm->len; i += 0x1000) { - page_unmapFree(pagedir_getPage(sm->pagedir, i, 0)); - } -} - -int simpleseg_handleFault(struct segment_map* sm, size_t addr, int write) { - struct simpleseg *ss = sm->seg->seg_data; - if (write && !ss->writable) return 1; - addr &= 0xFFFFF000; - struct page *p = pagedir_getPage(sm->pagedir, addr, 1); - if (p->frame != 0) return 1; - page_map(p, frame_alloc(), 1, ss->writable); - return 0; -} - -void simpleseg_delete(struct segment* seg) { -} diff --git a/src/stem/mem/seg.h b/src/stem/mem/seg.h deleted file mode 100644 index 022d38e..0000000 --- a/src/stem/mem/seg.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef DEF_SEG_H -#define DEF_SEG_H - -#include "paging.h" - -struct segment_map; -struct segment { - void* seg_data; - int mappings; - - struct segment_map* (*map)(struct segment* seg, struct page_directory* pagedir); - void (*unmap)(struct segment_map*); - void (*delete)(struct segment* seg); - int (*handle_fault)(struct segment_map* map, size_t addr, int write); //0 if ok, 1 if segfault -}; - -struct segment_map { - struct segment* seg; - struct page_directory* pagedir; - size_t start, len; - struct segment_map *next; -}; - -struct segment_map *seg_map(struct segment* seg, struct page_directory* pagedir); -void seg_unmap(struct segment_map* map); - -/// ************************************* SIMPLESEG stuff ***************** - -struct simpleseg { - int writable; - size_t start, len; -}; - -struct segment* simpleseg_make(size_t start, size_t len, int writable); -struct segment_map* simpleseg_map(struct segment* seg, struct page_directory* pagedir); -void simpleseg_unmap(struct segment_map*); -void simpleseg_delete(struct segment *seg); -int simpleseg_handleFault(struct segment_map* map, size_t addr, int write); - -#endif diff --git a/src/stem/task/idt.c b/src/stem/task/idt.c deleted file mode 100644 index 360ac91..0000000 --- a/src/stem/task/idt.c +++ /dev/null @@ -1,191 +0,0 @@ -#include "idt.h" -#include -#include -#include -#include "task.h" -#include "syscall.h" - -#include - -extern void isr0(); -extern void isr1(); -extern void isr2(); -extern void isr3(); -extern void isr4(); -extern void isr5(); -extern void isr6(); -extern void isr7(); -extern void isr8(); -extern void isr9(); -extern void isr10(); -extern void isr11(); -extern void isr12(); -extern void isr13(); -extern void isr14(); -extern void isr15(); -extern void isr16(); -extern void isr17(); -extern void isr18(); -extern void isr19(); -extern void isr20(); -extern void isr21(); -extern void isr22(); -extern void isr23(); -extern void isr24(); -extern void isr25(); -extern void isr26(); -extern void isr27(); -extern void isr28(); -extern void isr29(); -extern void isr30(); -extern void isr31(); - -extern void irq0(); -extern void irq1(); -extern void irq2(); -extern void irq3(); -extern void irq4(); -extern void irq5(); -extern void irq6(); -extern void irq7(); -extern void irq8(); -extern void irq9(); -extern void irq10(); -extern void irq11(); -extern void irq12(); -extern void irq13(); -extern void irq14(); -extern void irq15(); - -extern void syscall64(); - -extern void idt_flush(int32_t ptr); - -struct idt_entry idt_entries[256]; -struct idt_ptr idt_ptr; - -static int_callback irq_handlers[16] = {0}; - -void idt_isrHandler(struct registers regs) { - if ((regs.int_no == 14 && paging_fault(®s) != 0) || regs.int_no != 14) { - if (tasking_handleException(®s) == 0) { - monitor_write(" >> >> SOMETHING BAD HAPPENNED << <<\n"); - monitor_write("Unhandled exception "); - monitor_writeHex(regs.int_no); - monitor_write(" @"); monitor_writeHex(regs.eip); - monitor_put('\n'); - PANIC("unhandled exception"); - } - } -} - -void idt_irqHandler(struct registers regs) { - uint32_t doSwitch = 0; - doSwitch |= (regs.int_no == 32); //IRQ0 = timer - if (regs.err_code > 7) { - outb(0xA0, 0x20); - } - outb(0x20, 0x20); - if (irq_handlers[regs.err_code] != 0) { - irq_handlers[regs.err_code](®s); - } else { - monitor_write("Unhandled IRQ "); monitor_writeHex(regs.int_no - 32); monitor_write("\n"); - } - if (doSwitch) tasking_switch(); -} - -void idt_syscallHandler(struct registers regs) { - if (syscalls[regs.eax] != 0) { - syscalls[regs.eax](®s); - } else { - PANIC("unhandled syscall"); - } -} - -static void idt_setGate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) { - idt_entries[num].base_lo = base & 0xFFFF; - idt_entries[num].base_hi = (base >> 16) & 0xFFFF; - - idt_entries[num].sel = sel; - idt_entries[num].always0 = 0; - idt_entries[num].flags = flags; -} - -void idt_init() { - idt_ptr.limit = (sizeof(struct idt_entry) * 256) - 1; - idt_ptr.base = (uint32_t)&idt_entries; - - memset((uint8_t*)&idt_entries, 0, sizeof(struct idt_entry) * 256); - - //Remap the IRQ table - outb(0x20, 0x11); - outb(0xA0, 0x11); - outb(0x21, 0x20); - outb(0xA1, 0x28); - outb(0x21, 0x04); - outb(0xA1, 0x02); - outb(0x21, 0x01); - outb(0xA1, 0x01); - outb(0x21, 0x0); - outb(0xA1, 0x0); - - idt_setGate(0, (int32_t)isr0, 0x08, 0x8E); - idt_setGate(1, (int32_t)isr1, 0x08, 0x8E); - idt_setGate(2, (int32_t)isr2, 0x08, 0x8E); - idt_setGate(3, (int32_t)isr3, 0x08, 0x8E); - idt_setGate(4, (int32_t)isr4, 0x08, 0x8E); - idt_setGate(5, (int32_t)isr5, 0x08, 0x8E); - idt_setGate(6, (int32_t)isr6, 0x08, 0x8E); - idt_setGate(7, (int32_t)isr7, 0x08, 0x8E); - idt_setGate(8, (int32_t)isr8, 0x08, 0x8E); - idt_setGate(9, (int32_t)isr9, 0x08, 0x8E); - idt_setGate(10, (int32_t)isr10, 0x08, 0x8E); - idt_setGate(11, (int32_t)isr11, 0x08, 0x8E); - idt_setGate(12, (int32_t)isr12, 0x08, 0x8E); - idt_setGate(13, (int32_t)isr13, 0x08, 0x8E); - idt_setGate(14, (int32_t)isr14, 0x08, 0x8E); - idt_setGate(15, (int32_t)isr15, 0x08, 0x8E); - idt_setGate(16, (int32_t)isr16, 0x08, 0x8E); - idt_setGate(17, (int32_t)isr17, 0x08, 0x8E); - idt_setGate(18, (int32_t)isr18, 0x08, 0x8E); - idt_setGate(19, (int32_t)isr19, 0x08, 0x8E); - idt_setGate(20, (int32_t)isr20, 0x08, 0x8E); - idt_setGate(21, (int32_t)isr21, 0x08, 0x8E); - idt_setGate(22, (int32_t)isr22, 0x08, 0x8E); - idt_setGate(23, (int32_t)isr23, 0x08, 0x8E); - idt_setGate(24, (int32_t)isr24, 0x08, 0x8E); - idt_setGate(25, (int32_t)isr25, 0x08, 0x8E); - idt_setGate(26, (int32_t)isr26, 0x08, 0x8E); - idt_setGate(27, (int32_t)isr27, 0x08, 0x8E); - idt_setGate(28, (int32_t)isr28, 0x08, 0x8E); - idt_setGate(29, (int32_t)isr29, 0x08, 0x8E); - idt_setGate(30, (int32_t)isr30, 0x08, 0x8E); - idt_setGate(31, (int32_t)isr31, 0x08, 0x8E); - - idt_setGate(32, (int32_t)irq0, 0x08, 0x8E); - idt_setGate(33, (int32_t)irq1, 0x08, 0x8E); - idt_setGate(34, (int32_t)irq2, 0x08, 0x8E); - idt_setGate(35, (int32_t)irq3, 0x08, 0x8E); - idt_setGate(36, (int32_t)irq4, 0x08, 0x8E); - idt_setGate(37, (int32_t)irq5, 0x08, 0x8E); - idt_setGate(38, (int32_t)irq6, 0x08, 0x8E); - idt_setGate(39, (int32_t)irq7, 0x08, 0x8E); - idt_setGate(40, (int32_t)irq8, 0x08, 0x8E); - idt_setGate(41, (int32_t)irq9, 0x08, 0x8E); - idt_setGate(42, (int32_t)irq10, 0x08, 0x8E); - idt_setGate(43, (int32_t)irq11, 0x08, 0x8E); - idt_setGate(44, (int32_t)irq12, 0x08, 0x8E); - idt_setGate(45, (int32_t)irq13, 0x08, 0x8E); - idt_setGate(46, (int32_t)irq14, 0x08, 0x8E); - idt_setGate(47, (int32_t)irq15, 0x08, 0x8E); - - idt_setGate(64, (int32_t)syscall64, 0x08, 0x8E); - - idt_flush((int32_t)&idt_ptr); - - monitor_write("IDT ok\n"); -} - -void idt_handleIrq(int number, int_callback func) { - irq_handlers[number] = func; -} diff --git a/src/stem/task/idt.h b/src/stem/task/idt.h deleted file mode 100644 index bb89013..0000000 --- a/src/stem/task/idt.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef DEF_IDT_H -#define DEF_IDT_H - -#include - -struct idt_entry { - uint16_t base_lo; //Low part of address to jump to - uint16_t sel; //Kernel segment selector - uint8_t always0; - uint8_t flags; //Flags - uint16_t base_hi; //High part of address to jump to -} __attribute__((packed)); - -struct idt_ptr { - uint16_t limit; - uint32_t base; -} __attribute__((packed)); - -struct registers { - uint32_t cr3; //page directory physical address - uint32_t ds; // Data segment selector - uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha. - uint32_t int_no, err_code; // Interrupt number and error code (if applicable) - uint32_t eip, cs, eflags, useresp, ss; // Pushed by the processor automatically. -}; - -typedef void (*int_callback)(struct registers*); - -void idt_init(); -void idt_handleIrq(int number, int_callback func); - -#endif - diff --git a/src/stem/task/idt_.asm b/src/stem/task/idt_.asm deleted file mode 100644 index 63d1570..0000000 --- a/src/stem/task/idt_.asm +++ /dev/null @@ -1,155 +0,0 @@ -; UNRELATED - -[GLOBAL gdt_flush] - -gdt_flush: - mov eax, [esp+4] - lgdt [eax] - - mov ax, 0x10 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov ss, ax - jmp 0x08:.flush - -.flush: - ret - -; RELATED - -[GLOBAL idt_flush] -idt_flush: - mov eax, [esp+4] ; Get the pointer to the IDT, passed as a parameter. - lidt [eax] ; Load the IDT pointer. - ret - -;************************************************************************************ - -%macro COMMONSTUB 1 -[EXTERN idt_%1Handler] -%1_common_stub: - pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax - - mov ax, ds ; Lower 16-bits of eax = ds. - push eax ; save the data segment descriptor - - mov ax, 0x10 ; load the kernel data segment descriptor - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - mov eax, cr3 - push eax - - call idt_%1Handler - - pop eax - mov cr3, eax - - pop eax ; reload the original data segment descriptor - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - popa ; Pops edi,esi,ebp... - add esp, 8 ; Cleans up the pushed error code and pushed ISR number - sti - iret -%endmacro - -COMMONSTUB isr -COMMONSTUB irq -COMMONSTUB syscall - -;************************************************************************************ - -%macro ISR_NOERRCODE 1 ; define a macro, taking one parameter - [GLOBAL isr%1] ; %1 accesses the first parameter. - isr%1: - cli - push byte 0 - push byte %1 - jmp isr_common_stub -%endmacro - -%macro ISR_ERRCODE 1 - [GLOBAL isr%1] - isr%1: - cli - push byte %1 - jmp isr_common_stub -%endmacro - -%macro IRQ 2 - [GLOBAL irq%1] - irq%1: - cli - push byte %1 ;push irq number - push byte %2 ;push int number - jmp irq_common_stub -%endmacro - -%macro SYSCALL 1 - [GLOBAL syscall%1] - syscall%1: - cli - push byte 0 - push byte %1 - jmp syscall_common_stub -%endmacro - -ISR_NOERRCODE 0 -ISR_NOERRCODE 1 -ISR_NOERRCODE 2 -ISR_NOERRCODE 3 -ISR_NOERRCODE 4 -ISR_NOERRCODE 5 -ISR_NOERRCODE 6 -ISR_NOERRCODE 7 -ISR_ERRCODE 8 -ISR_NOERRCODE 9 -ISR_ERRCODE 10 -ISR_ERRCODE 11 -ISR_ERRCODE 12 -ISR_ERRCODE 13 -ISR_ERRCODE 14 -ISR_NOERRCODE 15 -ISR_NOERRCODE 16 -ISR_NOERRCODE 17 -ISR_NOERRCODE 18 -ISR_NOERRCODE 19 -ISR_NOERRCODE 20 -ISR_NOERRCODE 21 -ISR_NOERRCODE 22 -ISR_NOERRCODE 23 -ISR_NOERRCODE 24 -ISR_NOERRCODE 25 -ISR_NOERRCODE 26 -ISR_NOERRCODE 27 -ISR_NOERRCODE 28 -ISR_NOERRCODE 29 -ISR_NOERRCODE 30 -ISR_NOERRCODE 31 - -IRQ 0, 32 -IRQ 1, 33 -IRQ 2, 34 -IRQ 3, 35 -IRQ 4, 36 -IRQ 5, 37 -IRQ 6, 38 -IRQ 7, 39 -IRQ 8, 40 -IRQ 9, 41 -IRQ 10, 42 -IRQ 11, 43 -IRQ 12, 44 -IRQ 13, 45 -IRQ 14, 46 -IRQ 15, 47 - -SYSCALL 64 diff --git a/src/stem/task/syscall.c b/src/stem/task/syscall.c deleted file mode 100644 index 5aab011..0000000 --- a/src/stem/task/syscall.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "syscall.h" - -#define CALL0(name, scname) static void scname(struct registers* r) { r->eax = name(); } -#define CALL1(name, scname) static void scname(struct registers* r) { \ - r->eax = name(r->ebx); } -#define CALL2(name, scname) static void scname(struct registers* r) { \ - r->eax = name(r->ebx, r->ecx); } - -CALL0(thread_exit, thread_exit_sc); -CALL0(tasking_switch, schedule_sc); -CALL1(thread_sleep, thread_sleep_sc); -CALL1(process_exit, process_exit_sc); -CALL1(monitor_write, printk_sc); - -int_callback syscalls[] = { - thread_exit_sc, - schedule_sc, - thread_sleep_sc, - process_exit_sc, - printk_sc, - 0 }; diff --git a/src/stem/task/syscall.h b/src/stem/task/syscall.h deleted file mode 100644 index 54af108..0000000 --- a/src/stem/task/syscall.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef DEF_SYSCALL_H -#define DEF_SYSCALL_H - -#include "idt.h" - -extern int_callback syscalls[]; - -#endif - diff --git a/src/stem/task/task.c b/src/stem/task/task.c deleted file mode 100644 index 804adc2..0000000 --- a/src/stem/task/task.c +++ /dev/null @@ -1,245 +0,0 @@ -#include "task.h" -#include -#include -#include -#include "timer.h" - -#define KSTACKSIZE 0x8000 - -//Static routines for handling threads exiting and all cleanup -static void thread_exit_stackJmp(uint32_t reason); -static void thread_exit2(uint32_t reason); -static void thread_delete(struct thread *th); -static void process_delete(struct process *pr); - -//From task_.asm -extern uint32_t read_eip(); -extern void task_idle(void*); - -static uint32_t thread_runnable(struct thread *th); - -static uint32_t nextpid = 1; - -struct process *processes = 0, *kernel_process; -struct thread *threads = 0, *current_thread = 0, *idle_thread; - -uint32_t tasking_tmpStack[0x4000]; - -void tasking_init() { - cli(); - kernel_process = kmalloc(sizeof(struct process)); //This process must be hidden to users - kernel_process->pid = kernel_process->uid = kernel_process->threads = 0; - kernel_process->privilege = PL_KERNEL; - kernel_process->parent = kernel_process; - kernel_process->pagedir = kernel_pagedir; - kernel_process->next = 0; - current_thread = 0; - idle_thread = thread_new(kernel_process, task_idle, 0); - threads = 0; //Do not include idle thread in threads - sti(); - monitor_write("Tasking set up\n"); -} - -static struct thread *thread_next() { - if (current_thread == 0 || current_thread == idle_thread) current_thread = threads; - struct thread *ret = current_thread; - while (1) { - ret = ret->next; - if (ret == 0) ret = threads; - if (thread_runnable(ret)) { - return ret; - } - if (ret == current_thread) return idle_thread; - } -} - -void tasking_switch() { - if (threads == 0) PANIC("No more threads to run !"); - asm volatile("cli"); - - uint32_t esp, ebp, eip; - - asm volatile("mov %%esp, %0" : "=r"(esp)); - asm volatile("mov %%ebp, %0" : "=r"(ebp)); - eip = read_eip(); - - if (eip == 0x12345) { - return; - } - - if (current_thread != 0) { - current_thread->esp = esp; - current_thread->ebp = ebp; - current_thread->eip = eip; - } - - current_thread = thread_next(); - - asm volatile(" \ - mov %0, %%ebp; \ - mov %1, %%esp; \ - mov %2, %%ecx; \ - mov $0x12345, %%eax; \ - jmp *%%ecx;" - : : "r"(current_thread->ebp), "r"(current_thread->esp), "r"(current_thread->eip)); -} - -void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablephysical) { - if (idx < 896) return; - struct process* it = processes; - while (it != 0) { - it->pagedir->tables[idx] = table; - it->pagedir->tablesPhysical[idx] = tablephysical; - it = it->next; - } -} - -uint32_t tasking_handleException(struct registers *regs) { - if (current_thread == 0) return 0; //No tasking yet - monitor_write("\n(task.c:99) Unhandled exception : "); - char *exception_messages[] = {"Division By Zero","Debug","Non Maskable Interrupt","Breakpoint", - "Into Detected Overflow","Out of Bounds","Invalid Opcode","No Coprocessor", "Double Fault", - "Coprocessor Segment Overrun","Bad TSS","Segment Not Present","Stack Fault","General Protection Fault", - "Page Fault","Unknown Interrupt","Coprocessor Fault","Alignment Check","Machine Check"}; - monitor_write(exception_messages[regs->int_no]); - monitor_write(" at "); monitor_writeHex(regs->eip); - monitor_write(" >>> Thread exiting.\n"); - thread_exit_stackJmp(EX_TH_EXCEPTION); - PANIC("This should never have happened. Please report this."); -} - -void thread_sleep(uint32_t msecs) { - if (current_thread == 0) return; - current_thread->state = TS_SLEEPING; - current_thread->timeWait = timer_time() + msecs; - asm volatile("int $64" : : "a"(1)); -} - -void thread_exit2(uint32_t reason) { //See EX_TH_* defines in task.h - /* - * if reason == EX_TH_NORMAL, it is just one thread exiting because it has to - * if reason == EX_TH_EXCEPTION, it is just one thread exiting because of an exception - * if reason is none of the two cases above, it is the whole process exiting (with error code = reason) - */ - struct thread *th = current_thread; - struct process *pr = th->process; - if ((reason == EX_TH_NORMAL || reason == EX_TH_EXCEPTION) && pr->threads > 1) { - thread_delete(th); - } else { - process_delete(pr); - } - sti(); - tasking_switch(); -} - -void thread_exit_stackJmp(uint32_t reason) { - uint32_t *stack; - cli(); - stack = tasking_tmpStack + 0x4000; - stack--; *stack = reason; - stack--; *stack = 0; - asm volatile(" \ - mov %0, %%esp; \ - mov %1, %%ebp; \ - mov %2, %%ecx; \ - mov %3, %%cr3; \ - jmp *%%ecx;" : : - "r"(stack), "r"(stack), "r"(thread_exit2), "r"(kernel_pagedir->physicalAddr)); -} - -void thread_exit() { - thread_exit_stackJmp(EX_TH_NORMAL); -} - -void process_exit(uint32_t retval) { - if (retval == EX_TH_NORMAL || retval == EX_TH_EXCEPTION) retval = EX_PR_EXCEPTION; - thread_exit_stackJmp(retval); -} - -static uint32_t thread_runnable(struct thread *t) { - if (t->state == TS_RUNNING) return 1; - if (t->state == TS_SLEEPING && timer_time() >= t->timeWait) return 1; - return 0; -} - -static void thread_run(struct thread *thread, thread_entry entry_point, void *data) { - pagedir_switch(thread->process->pagedir); //TODO : take into account privilege level - asm volatile("sti"); - entry_point(data); - thread_exit(0); -} - -struct thread *thread_new(struct process *proc, thread_entry entry_point, void *data) { - struct thread *t = kmalloc(sizeof(struct thread)); - t->process = proc; - proc->threads++; - t->kernelStack_addr = kmalloc(KSTACKSIZE); - t->kernelStack_size = KSTACKSIZE; - - uint32_t *stack = (uint32_t*)((size_t)t->kernelStack_addr + t->kernelStack_size); - - //Pass parameters - stack--; *stack = (uint32_t)data; - stack--; *stack = (uint32_t)entry_point; - stack--; *stack = (uint32_t)t; - stack--; *stack = 0; - t->esp = (uint32_t)stack; - t->ebp = t->esp + 8; - t->eip = (uint32_t)thread_run; - - t->state = TS_RUNNING; - - if (threads == 0) { - threads = t; - } else { - struct thread *i = threads; - while (i->next != 0) i = i->next; - i->next = t; - } - return t; -} - -struct process *process_new(struct process* parent, uint32_t uid, uint32_t privilege) { - struct process* p = kmalloc(sizeof(struct process)); - p->pid = (nextpid++); - p->uid = uid; - p->threads = 0; - p->privilege = privilege; - p->parent = parent; - p->pagedir = pagedir_new(); - p->next = processes; - processes = p; - return p; -} - -static void thread_delete(struct thread *th) { - kfree(th->kernelStack_addr); - th->process->threads--; - if (threads == th) { - threads = th->next; - } else { - struct thread *it = threads; - while (it->next != th && it->next != 0) it = it->next; - if (it->next == th) it->next = th->next; - } - kfree(th); -} - -static void process_delete(struct process *pr) { - struct thread *it; - while (threads != 0 && threads->process == pr) thread_delete(threads); - it = threads; - while (it != 0) { - while (it->next->process == pr) thread_delete(it->next); - it = it->next; - } - pagedir_delete(pr->pagedir); - if (processes == pr) { - processes = pr->next; - } else { - struct process *it = processes; - while (it != 0 && it->next != pr) it = it->next; - if (it != 0 && it->next == pr) it->next = pr->next; - } - kfree(pr); -} diff --git a/src/stem/task/task.h b/src/stem/task/task.h deleted file mode 100644 index c9f1794..0000000 --- a/src/stem/task/task.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef DEF_TASK_H -#define DEF_TASK_H - -#include -#include -#include "idt.h" - -#define TS_RUNNING 0 -#define TS_SLEEPING 1 //Sleeping for a defined amount of time -#define TS_WAIKWAIT 2 //Waiting to be waked up by something precise (thread currently blocked) - -#define PL_USER 3 -#define PL_SERVICE 2 -#define PL_DRIVER 1 -#define PL_KERNEL 0 - -#define EX_TH_NORMAL 0x10000 //ERROR code : just one thread exits, because it has to -#define EX_TH_EXCEPTION 0x10001 //ERROR code : just one thread exits, because of an unhandled exception -#define EX_PR_EXCEPTION 0x10002 //ERROR code : all process finishes, because of an unhandled exception - -typedef void (*thread_entry)(void*); - -struct process { - uint32_t pid, uid, privilege, threads; - struct process *parent; - struct page_directory *pagedir; - - struct process *next; //Forms a linked list -}; - -struct thread { - struct process *process; - uint32_t esp, ebp, eip; - uint8_t state; - uint32_t timeWait; - void* kernelStack_addr; - uint32_t kernelStack_size; - - struct thread *next; //Forms a linked list -}; - -extern struct thread *current_thread; - -void tasking_init(); -void tasking_switch(); -void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablePhysical); -uint32_t tasking_handleException(struct registers *regs); - -void thread_sleep(uint32_t msecs); -void thread_exit(); -void process_exit(uint32_t retval); -struct thread * thread_new(struct process *proc, thread_entry entry_point, void *data); -struct process* process_new(struct process *parent, uint32_t uid, uint32_t privilege); - -#endif diff --git a/src/stem/task/task_.asm b/src/stem/task/task_.asm deleted file mode 100644 index ae45c68..0000000 --- a/src/stem/task/task_.asm +++ /dev/null @@ -1,10 +0,0 @@ -[GLOBAL read_eip] -read_eip: - pop eax - jmp eax - -[GLOBAL task_idle] -task_idle: - sti - hlt - jmp task_idle diff --git a/src/stem/task/timer.c b/src/stem/task/timer.c deleted file mode 100644 index 8c1a2b8..0000000 --- a/src/stem/task/timer.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "timer.h" -#include "idt.h" -#include -#include - -static uint32_t tick = 0, frequency = 0, uptime = 0; - -void timer_callback(struct registers *regs) { - tick++; - if (tick == frequency) { - uptime++; - tick = 0; - } -} - -uint32_t timer_uptime() { return uptime; } - -uint32_t timer_time() { - return (uptime * 1000) + (tick * 1000 / frequency); -} - -void timer_init(uint32_t freq) { - frequency = freq; - - idt_handleIrq(0, timer_callback); - - uint32_t divisor = 1193180 / freq; - - outb(0x43, 0x36); //Command byte - - uint8_t l = (divisor & 0xFF), h = (divisor >> 8); - outb(0x40, l); - outb(0x40, h); - - monitor_write("Timer started\n"); -} diff --git a/src/stem/task/timer.h b/src/stem/task/timer.h deleted file mode 100644 index 4909245..0000000 --- a/src/stem/task/timer.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef DEF_TIMER_H -#define DEF_TIMER_H - -#include - -void timer_init(uint32_t frequency); -uint32_t timer_time(); //Returns miliseconds (approximate) since computer started -uint32_t timer_uptime(); //Same thing in seconds - -#endif -- cgit v1.2.3