summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLizzy Fleckenstein <lizzy@vlhl.dev>2024-01-09 20:56:07 +0100
committerLizzy Fleckenstein <lizzy@vlhl.dev>2024-01-09 21:00:24 +0100
commit59f22bc7ce5bbadf62722f3db5c93b45e86e4cca (patch)
treec5771b21f6c12f3e58cbb6c6dda8df3bc4b23798
parent33bb4187103c49c81fbf7c6f18ebcfd4c4d66fd2 (diff)
downloadcuddles-59f22bc7ce5bbadf62722f3db5c93b45e86e4cca.tar.xz
use ELF for kernel
-rw-r--r--.gitignore2
-rw-r--r--Makefile52
-rw-r--r--stage2/main.asm69
-rw-r--r--stage2/paging.asm5
-rw-r--r--stage3.ld9
-rw-r--r--stage3/debug.c97
-rw-r--r--stage3/init.c3
-rw-r--r--stage3/isr.lua13
-rw-r--r--stage3/main.c6
-rw-r--r--stage3/paging.asm15
-rw-r--r--stage3/watchdog.lua4
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)