From 59f22bc7ce5bbadf62722f3db5c93b45e86e4cca Mon Sep 17 00:00:00 2001 From: Lizzy Fleckenstein Date: Tue, 9 Jan 2024 20:56:07 +0100 Subject: use ELF for kernel --- .gitignore | 2 +- Makefile | 52 ++++++++++++++++------------ stage2/main.asm | 69 ++++++++++++++++++++++++++++++++++--- stage2/paging.asm | 5 +-- stage3.ld | 9 ++--- stage3/debug.c | 97 ++++++++++++++++++++++++++++++----------------------- stage3/init.c | 3 +- stage3/isr.lua | 13 ++++--- stage3/main.c | 6 ++++ stage3/paging.asm | 15 +++++++-- stage3/watchdog.lua | 4 +++ 11 files changed, 188 insertions(+), 87 deletions(-) diff --git a/.gitignore b/.gitignore index 273eb2f..6b1ec60 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,8 @@ *.o *.d *.img -*.map *.dis.asm +*.elf .version-* bx_enh_dbg.ini stage3/isr.asm diff --git a/Makefile b/Makefile index 666898c..eea6f87 100644 --- a/Makefile +++ b/Makefile @@ -9,8 +9,15 @@ override CFLAGS += \ -nostartfiles \ -nodefaultlibs \ -Wall \ - -Wextra \ - -MMD + -Wextra + +override LDFLAGS += --no-warn-rwx-segment + +ifneq "$(DEBUG)" "0" + override CFLAGS += -g -fno-omit-frame-pointer -DDEBUG + override LDFLAGS += -g + override NASMFLAGS_KERNEL += -g +endif STAGE3_C = \ stage3/init.o \ @@ -44,41 +51,42 @@ STAGE3 = $(STAGE3_C) \ stage3/watchdog.o PAD_BOUNDARY = pad() { truncate -s $$(echo "($$(du -b $$1 | cut -f1)+$$2-1)/$$2*$$2" | bc) $$1; }; pad -DISAS = objdump -b binary -D -M intel -m i386:x86-64 stage3.bin --adjust-vma 0x9000 +DISAS = objdump -D -M intel -j .text stage3.elf -cuddles.img: stage1.bin stage2.bin stage3.bin fs.tar - cat stage{1,2,3}.bin fs.tar > cuddles.img +cuddles.img: stage1.bin stage23.bin fs.tar + cat stage{1,23}.bin fs.tar > cuddles.img $(PAD_BOUNDARY) cuddles.img 1048576 -stage1.bin: stage1/main.asm stage1/print.asm stage2.bin stage3.bin - nasm -f bin stage1/main.asm -o stage1.bin \ - -dKSIZE=$$(du -cb stage{2,3}.bin | tail -n1 | cut -f1) +stage1.bin: stage1/main.asm stage1/print.asm stage23.bin + nasm $(NASMFLAGS_BOOT) -f bin stage1/main.asm -o stage1.bin \ + -dKSIZE=$$(du -cb stage23.bin | tail -n1 | cut -f1) + +stage23.bin: stage2.bin stage3.elf + cat stage2.bin stage3.elf > stage23.bin + $(PAD_BOUNDARY) stage23.bin 512 stage2.bin: stage2/main.asm stage2/mmap.asm stage2/paging.asm stage2/vesa.asm stage1/print.asm - nasm -f bin stage2/main.asm -o stage2.bin - truncate -s 4608 stage2.bin + nasm $(NASMFLAGS_BOOT) -f bin stage2/main.asm -o stage2.bin -stage3.bin fs/dbg/kernel.map &: $(STAGE3) stage3.ld - mkdir -p fs/dbg/ - ld $(STAGE3) -T stage3.ld -Map=fs/dbg/kernel.map - $(PAD_BOUNDARY) stage3.bin 512 +stage3.elf: $(STAGE3) stage3.ld + ld $(LDFLAGS) $(STAGE3) -T stage3.ld -o stage3.elf -fs/dbg/kernel.dis.asm: stage3.bin +fs/dbg/kernel.dis.asm: stage3.elf mkdir -p fs/dbg/ $(DISAS) > fs/dbg/kernel.dis.asm stage3/%.o: stage3/%.asm - nasm -f elf64 $< -o $@ + nasm $(NASMFLAGS_KERNEL) -f elf64 $< -o $@ stage3/interrupts.o: stage3/interrupts.c - gcc $(CFLAGS) -mgeneral-regs-only -c $< -o $@ + gcc $(CFLAGS) -MMD -mgeneral-regs-only -c $< -o $@ stage3/pic.o: stage3/pic.c - gcc $(CFLAGS) -mgeneral-regs-only -c $< -o $@ + gcc $(CFLAGS) -MMD -mgeneral-regs-only -c $< -o $@ stage3/init.o: stage3/init.c - gcc $(CFLAGS) -mgeneral-regs-only -c $< -o $@ + gcc $(CFLAGS) -MMD -mgeneral-regs-only -c $< -o $@ stage3/%.o: stage3/%.c - gcc $(CFLAGS) -c $< -o $@ + gcc $(CFLAGS) -MMD -c $< -o $@ -include $(STAGE3_C:%.o=%.d) @@ -99,7 +107,7 @@ stage3/font.c: stage3/font_builtin.c stage3/font_builtin.c: fs/fonts/ter-u16n.cuddlefont xxd -i $< > $@ -fs.tar: $(shell find fs | sed 's/ /\\ /g') fs/dbg/kernel.map fs/dbg/kernel.dis.asm +fs.tar: $(shell find fs | sed 's/ /\\ /g') fs/dbg/kernel.dis.asm cd fs && tar --format=ustar -cf ../fs.tar * .PHONY: run clean flash disas qemu bochs @@ -123,5 +131,5 @@ clean: flash: cuddles.img dd if=cuddles.img of=$(DEV) -disas: stage3.bin +disas: stage3.elf $(DISAS) --disassembler-color=on diff --git a/stage2/main.asm b/stage2/main.asm index 3cfb5d2..5027546 100644 --- a/stage2/main.asm +++ b/stage2/main.asm @@ -44,8 +44,69 @@ long_mode: mov gs, ax mov ss, ax - ; align stack - and rsp, ~(0x0f) - sub rsp, 8 + mov eax, [kernel_elf] + cmp eax, [.elf] + jne .fail - ; kernel begins here + mov r8, [kernel_elf+32] ; program header pos + add r8, kernel_elf + + movzx rbx, word[kernel_elf+54] ; program header size + movzx rdx, word[kernel_elf+56] ; num of program headers + +.header: + cmp rdx, 0 + je .start + + mov edi, [r8] ; type + cmp edi, 0 + je .next + + cmp edi, 1 + je .load + + cmp edi, 2 + je .fail + + cmp edi, 3 + je .fail + + jmp .next + +.load: + ; zero out the segment + mov al, 0 + mov rdi, [r8+16] + mov rcx, [r8+40] + rep stosb + + ; load from file + mov rdi, [r8+16] + mov rsi, [r8+8] + add rsi, kernel_elf + mov rcx, [r8+32] + rep movsb + +.next: + + add r8, rbx + dec rdx + jmp .header + +.start: + ; more stack space + mov rsp, 0x80000 + xor rbp, rbp + + ; ELF entry point + mov rax, [kernel_elf+24] + call rax + +.fail: + cli + hlt + jmp $ + +.elf: db 0x7f, "ELF" + +kernel_elf: diff --git a/stage2/paging.asm b/stage2/paging.asm index cedc1e9..cd6ea1c 100644 --- a/stage2/paging.asm +++ b/stage2/paging.asm @@ -8,13 +8,14 @@ paging: .clr_buf: mov byte[di], 0 inc di - cmp di, PAGETABLE+0x4000 + cmp di, PAGETABLE+0x5000 jne .clr_buf ; init 3 page map levels mov dword[PAGETABLE+0x0000], PAGETABLE+0x1003 mov dword[PAGETABLE+0x1000], PAGETABLE+0x2003 mov dword[PAGETABLE+0x2000], PAGETABLE+0x3003 + mov dword[PAGETABLE+0x2008], PAGETABLE+0x4003 ; fill up level 4 page map mov eax, 3 @@ -23,7 +24,7 @@ paging: mov [di], eax add di, 8 add eax, 0x1000 - cmp eax, 0x100000 + cmp eax, 0x200000 jb .build_pt ; enable paging and long mode diff --git a/stage3.ld b/stage3.ld index 45a1486..e2d19d3 100644 --- a/stage3.ld +++ b/stage3.ld @@ -1,9 +1,4 @@ -OUTPUT(stage3.bin) -OUTPUT_FORMAT(binary) - -SECTIONS +MEMORY { - . = 0x9000; - .text : { *(.text) } - .data : { *(.bss .data .rodata) } + ram (rwx) : ORIGIN = 0x100000, LENGTH = 0x100000 } diff --git a/stage3/debug.c b/stage3/debug.c index 0621dbd..ed28fee 100644 --- a/stage3/debug.c +++ b/stage3/debug.c @@ -4,7 +4,6 @@ #include "halt.h" #include "debug.h" -static str dbg_map = NILS; static str dbg_disas = NILS; static str exception[32] = { @@ -37,56 +36,70 @@ static str exception[32] = { NILS, }; -static void dump_frame(interrupt_frame *frame) +static bool get_source(u64 code, str *func, str *linep) { - print(S("rip = ")); - print_hex(frame->rip); - - if (dbg_map.data != nil) { - str entry = NILS; - str iter = dbg_map; - while (iter.len > 0) { - str line = str_walk(&iter, S("\n")); - line = str_eat(line, S(" ")); - if (!str_start(line, S("0x"))) + if (dbg_disas.data == nil) + return false; + + *func = (str) NILS; + *linep = (str) NILS; + + str iter = dbg_disas; + while (iter.len > 0) { + str line = str_walk(&iter, S("\n")); + u64 func_addr; + usize adv; + if ((adv = str_parse_num(line, 16, &func_addr))) { + line = str_advance(line, adv); + if (line.len < 2 || line.data[0] != ' ' || line.data[1] != '<') continue; line = str_advance(line, 2); - + usize close = str_find(line, S(">")); + *func = (str) { .len = close, .data = line.data }; + } else { u64 addr; - usize adv = str_parse_num(line, 16, &addr); - if (adv == 0) + if (!str_parse_num(str_eat(line, S(" ")), 16, &addr)) continue; - line = str_advance(line, adv); - - if (addr > frame->rip) - break; - - line = str_eat(line, S(" ")); - if (line.len > 0) - entry = line; + *linep = line; + if (addr == code) + return true; } + } - if (entry.len > 0) { - print(S(" in ")); - print(entry); - } + return false; +} + +static void trace(u64 code, u64 base) +{ + if (base == 0) + return; + + str func, line; + if (get_source(code, &func, &line)) { + print(S("\t")); + print_hex(code); + print(S(" in ")); + print(func); + print(S("\n")); } - if (dbg_disas.data != nil) { - str iter = dbg_disas; - while (iter.len > 0) { - str line = str_walk(&iter, S("\n")); - u64 addr; - if (!str_parse_num(str_eat(line, S(" ")), 16, &addr)) - continue; - if (addr == frame->rip) { - print(S("\n")); - print(line); - break; - } - } + u64 *stack = (u64 *) base; + trace(stack[1], stack[0]); +} + +static void dump_frame(interrupt_frame *frame) +{ + str func, line; + if (get_source(frame->rip, &func, &line)) { + print(line); + print(S("\n")); } + print(S("backtrace:\n")); + trace(frame->rip, frame->rbp); + + print(S("rip = ")); + print_hex(frame->rip); print(S("\n")); struct { @@ -187,7 +200,7 @@ void debug_exception(interrupt_frame *frame) void debug_init() { - print(S("loading kernel debug info...\n")); - dbg_map = fs_read(S("dbg/kernel.map")); + print(S("loading kernel debug info... ")); dbg_disas = fs_read(S("dbg/kernel.dis.asm")); + print(S("done\n")); } diff --git a/stage3/init.c b/stage3/init.c index 2e26e19..c65f08b 100644 --- a/stage3/init.c +++ b/stage3/init.c @@ -1,7 +1,7 @@ #include "def.h" void kmain(); -void init() +void _start() { // enable SSE. long mode demands it is present u64 cr0; @@ -14,5 +14,6 @@ void init() u16 fpu_cw = 0x37a; asm volatile("fldcw %0"::"m"(fpu_cw)); + kmain(); } diff --git a/stage3/isr.lua b/stage3/isr.lua index 3c88c5e..4810f01 100644 --- a/stage3/isr.lua +++ b/stage3/isr.lua @@ -6,6 +6,13 @@ for _, x in pairs({8, 10, 11, 12, 13, 14, 17, 21, 29, 30}) do has_error_code[x] = true end +print("section .data") +print("idt_entries:") +for i = 0, 255 do + print("dq isr_"..i) +end + +print("section .text") for i = 0, 255 do print("isr_" .. i .. ":") print("cli") @@ -18,11 +25,6 @@ for i = 0, 255 do print("jmp isr_common") end -print("idt_entries:") -for i = 0, 255 do - print("dq isr_"..i) -end - print([[ isr_common: push r15 @@ -42,6 +44,7 @@ isr_common: push rax cld + xor rbp, rbp mov rdi, rsp call interrupt_handler diff --git a/stage3/main.c b/stage3/main.c index ae94abf..b796fd1 100644 --- a/stage3/main.c +++ b/stage3/main.c @@ -63,6 +63,12 @@ void kmain() heap_init(); #define MMAP for (MemRegion *mreg = (void *) 0x500; mreg->start != nil; mreg++) + MMAP { + if (mreg->start == (void *) 0x100000) { + mreg->start = (void *) 0x200000; + mreg->size -= 0x100000; + } + } // backup memory map usize n_mreg = 0; diff --git a/stage3/paging.asm b/stage3/paging.asm index 783649e..f58bb98 100644 --- a/stage3/paging.asm +++ b/stage3/paging.asm @@ -1,15 +1,24 @@ global page_region -section .text +%define PAGEBUFSIZE 0x10 * 0x1000 + +section .bss + +ALIGN(4096) +pagebuf_data: resb PAGEBUFSIZE + +section .data pagebuf_init: - .start: dq 0x5000 - .size: dq 0x2000 + .start: dq pagebuf_data + .size: dq PAGEBUFSIZE .used: dq 0 pagebuf: dq pagebuf_init next_page: dq 0 +section .text + ; allocate new page table buffer alloc: ; rsi = buffer (result) diff --git a/stage3/watchdog.lua b/stage3/watchdog.lua index dac4d57..8d3a206 100644 --- a/stage3/watchdog.lua +++ b/stage3/watchdog.lua @@ -12,9 +12,13 @@ local regs = { print("global watchdog") print("extern rand, watchdog_err") +print("section .bss") + print("regs_backup: resq 16") print("regs_rand: resq 16") +print("section .text") + print("watchdog:") local function iter_regs(f) -- cgit v1.2.3