From 5481848e27fdd4fc859def9841a0283665531a46 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sun, 13 Sep 2020 17:12:29 -0400 Subject: fixed some paging bugs, added fault handlers and new programs --- src/kernel/elf.c | 14 ++++++++ src/kernel/fat.c | 15 ++++++--- src/kernel/idt.c | 54 +++++++++++++++++++++++++++++-- src/kernel/isrs.asm | 73 ++++++++++++++++++++++++++++++++++++++++-- src/kernel/main.c | 2 +- src/kernel/paging.c | 53 +++++++++++++----------------- src/kernel/paging.h | 4 --- src/kernel/pmap.c | 31 ++++++++++++++++-- src/kernel/task.c | 2 ++ src/kernel/task.h | 5 ++- src/kernel/vga.c | 2 ++ src/user/dumphex/dumphex.c | 29 +++++++++++++++++ src/user/dumptext/dumptext.c | 15 +++++++++ src/user/hello/hello.asm | 14 ++++++++ src/user/highway/highway.c | 7 +++- src/user/include/knob/format.h | 2 ++ src/user/init/init.c | 15 +++++---- src/user/knob/entry.asm | 1 - src/user/knob/format.c | 14 ++++++++ src/user/knob/user.c | 14 +++++--- 20 files changed, 307 insertions(+), 59 deletions(-) create mode 100644 src/user/dumphex/dumphex.c create mode 100644 src/user/dumptext/dumptext.c create mode 100644 src/user/hello/hello.asm (limited to 'src') diff --git a/src/kernel/elf.c b/src/kernel/elf.c index 423d51a..07cff91 100644 --- a/src/kernel/elf.c +++ b/src/kernel/elf.c @@ -126,6 +126,20 @@ bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_v tstate.page_directory = pd; tstate.ret_addr = ehead.entry_vma; tstate.edx = (uint32_t)pass_vma; + + const char *path_end_start = path; + for (const char *i = path; *i; ++i) + if (*i == '/') + path_end_start = i + 1; + + uint8_t i; + for (i = 0; i < TASK_NAME_LEN; ++i) { + if (!path_end_start[i]) + break; + tstate.name[i] = path_end_start[i]; + } + tstate.name[i] = '\0'; + new_task(tstate); return true; } \ No newline at end of file diff --git a/src/kernel/fat.c b/src/kernel/fat.c index c297cab..c4461de 100644 --- a/src/kernel/fat.c +++ b/src/kernel/fat.c @@ -119,10 +119,17 @@ static const uint8_t this_dir[] = {'.', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' static const uint8_t parent_dir[] = {'.', '.', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; static inline bool check_fat_names(const uint8_t *a, const uint8_t *b) { - return (((uint32_t *)a)[0] == ((uint32_t *)b)[0]) && - (((uint32_t *)a)[1] == ((uint32_t *)b)[1]) && - (((uint16_t *)a)[4] == ((uint16_t *)b)[4]) && - (((uint8_t *)a)[10] == ((uint8_t *)b)[10]); + for (uint8_t i = 0; i < 11; ++i) { + uint8_t ac = a[i]; + uint8_t bc = b[i]; + if ((ac >= 0x61) && (ac <= 0x7a)) + ac &= ~0x20; + if ((bc >= 0x61) && (bc <= 0x7a)) + bc &= ~0x20; + if (ac != bc) + return false; + } + return true; } //after: cur_dir -> specified entry in root diff --git a/src/kernel/idt.c b/src/kernel/idt.c index 4dc8a36..b789d42 100644 --- a/src/kernel/idt.c +++ b/src/kernel/idt.c @@ -103,8 +103,8 @@ void const *syscall_table[] = { &sc_memory_info }; -//these aren't really void (*)()'s, but gcc complains if we take an address of a void, so we give it a type -typedef void (*isr_t)(); +//these aren't really void ()'s, but gcc complains if we take an address of a void, so we give it a type +typedef void isr_t(); extern isr_t syscall_isr; extern isr_t quit_isr; @@ -112,6 +112,48 @@ extern isr_t yield_isr; extern isr_t kbd_isr; +extern isr_t udf_isr; +extern isr_t dfa_isr; +extern isr_t tsf_isr; +extern isr_t npf_isr; +extern isr_t ssf_isr; +extern isr_t gpf_isr; +extern isr_t pff_isr; + +__attribute__ ((noreturn)) +void exception_halt(const char *id, uint32_t code, uint32_t eip, uint32_t cs) { + char nbuf[11]; + + set_log_mode(LOG_PANIC); + logsz("Exception #"); + logsz(id); + logsz(" at 0x"); + u8_hex(cs, nbuf); + logsz(nbuf); + logsz(":0x"); + u32_hex(eip, nbuf); + logsz(nbuf); + + logsz("\nerror code = 0x"); + u32_hex(code, nbuf); + logsz(nbuf); + + logsz("\ntask name = "); + logsz(active_task->name); + + logsz("\ncr3 = 0x"); + uint32_t cr3; + asm ( + "mov %%cr3, %0" + : "=r" (cr3)); + u32_hex(cr3, nbuf); + logsz(nbuf); + + logsz("\nHalting."); + while (1) + asm ("hlt"); +} + static void register_int(uint8_t n, isr_t *isr, uint8_t dpl) { idt[n].addr_low = (uint32_t)isr & 0xffff; idt[n].addr_high = (uint32_t)isr >> 16; @@ -142,6 +184,14 @@ void init_idt() { register_int(0x21, &kbd_isr, 0); + register_int(0x08, &udf_isr, 0); + register_int(0x08, &dfa_isr, 0); + register_int(0x0a, &tsf_isr, 0); + register_int(0x0b, &npf_isr, 0); + register_int(0x0c, &ssf_isr, 0); + register_int(0x0d, &gpf_isr, 0); + register_int(0x0e, &pff_isr, 0); + outb(PIC_MCMD, PIC_RESET); outb(PIC_SCMD, PIC_RESET); diff --git a/src/kernel/isrs.asm b/src/kernel/isrs.asm index 9a9600c..4f2d4e2 100644 --- a/src/kernel/isrs.asm +++ b/src/kernel/isrs.asm @@ -6,6 +6,14 @@ global yield_isr global _start_user_mode global kbd_isr +global udf_isr +global dfa_isr +global tsf_isr +global npf_isr +global ssf_isr +global gpf_isr +global pff_isr + extern syscall_table extern active_task @@ -13,14 +21,26 @@ extern delete_task extern advance_active_task extern on_kbd_isr extern make_sure_tasks +extern exception_halt n_syscalls equ 0x9 +;section .bss +;_debug_is_start_task resb 1 +;extern switch_to_kernel_cr3 +;extern switch_to_task_cr3 + section .text syscall_isr: cmp eax, n_syscalls jge .bad +; mov byte [_debug_is_start_task], 0 +; cmp eax, 0x4 +; jne .dont_set_debug +; mov byte [_debug_is_start_task], 1 +;.dont_set_debug: + mov eax, dword [syscall_table + eax * 4] push edi @@ -33,6 +53,16 @@ syscall_isr: add esp, 20 +; cmp byte [_debug_is_start_task], 0 +; je .dont_do_debug +; push eax +; call switch_to_kernel_cr3 +; jmp $ +; call switch_to_task_cr3 +; pop eax +;.dont_do_debug: + +._before_return: iret .bad: @@ -86,12 +116,13 @@ yield_isr: mov edi, dword [eax + 24] mov ebp, dword [eax + 28] -_before_start_task: +._before_return: iret _start_user_mode: mov ax, 0x2b mov ds, ax + mov es, ax push dword 0x2b sub esp, 4 @@ -113,4 +144,42 @@ kbd_isr: pop edx pop ecx pop eax - iret \ No newline at end of file + iret + +udf_isr: + push 0 + push udid + call exception_halt + +dfa_isr: + push dfid + call exception_halt + +tsf_isr: + push tsid + call exception_halt + +npf_isr: + push npid + call exception_halt + +ssf_isr: + push ssid + call exception_halt + +gpf_isr: + push gpid + call exception_halt + +pff_isr: + push pfid + call exception_halt + +section .rodata +udid db "UD", 0 +dfid db "DF", 0 +tsid db "TS", 0 +npid db "NP", 0 +ssid db "SS", 0 +gpid db "GP", 0 +pfid db "PF", 0 \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index e2a23e8..06b83d1 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -136,7 +136,7 @@ void main() { logsz(nbuf); logsz("k\n\n"); - if (!try_elf_run(drives, "BIN/INIT.ELF", "")) + if (!try_elf_run(drives, "bin/init", "")) PANIC("Failed to load init program."); init_kbd(); diff --git a/src/kernel/paging.c b/src/kernel/paging.c index a0f7c3d..fbc33de 100644 --- a/src/kernel/paging.c +++ b/src/kernel/paging.c @@ -20,28 +20,16 @@ enum { PE_PRESENT = 0x001 }; -//TODO: -// try_elf_run needs to call these new functions. - -void *new_pd() { - uint32_t *pd = allocate_kernel_pages(1); - for (uint16_t i = 0; i < 1024; ++i) - pd[i] = 0; - return pd; -} - -void free_pd(void *pd) { - uint32_t *pd_32 = pd; - for (uint16_t i = 0; i < 1024; ++i) - if (pd_32[i] & PE_PRESENT) - free_pages((void *)(pd_32[i] & PE_ADDR_MASK), 1); - free_pages(pd, 1); -} +#define KERNEL_END (0x08000000) -void pd_map(void *pd, uint32_t physical_addr, uint32_t virtual_addr, bool writable) { +static void pd_map(void *pd, uint32_t physical_addr, uint32_t virtual_addr, bool writable) { uint32_t *ptp = (uint32_t *)pd + (virtual_addr >> 22); - if (!(*ptp & PE_PRESENT)) - *ptp = (uint32_t)allocate_kernel_pages(1) | PE_USER | PE_WRITABLE | PE_PRESENT; + if (!(*ptp & PE_PRESENT)) { + uint32_t *new_pt = allocate_kernel_pages(1); + for (uint16_t i = 0; i < 1024; ++i) + new_pt[i] = 0; + *ptp = (uint32_t)new_pt | PE_USER | PE_WRITABLE | PE_PRESENT; + } ((uint32_t *)(*ptp & PE_ADDR_MASK))[(virtual_addr >> 12) % 1024] = physical_addr | PE_USER | PE_PRESENT | (PE_WRITABLE * writable); } @@ -51,26 +39,28 @@ static bool pd_is_mapped(void *pd, uint32_t vma) { return (pde & PE_PRESENT) && (((uint32_t *)(pde & PE_ADDR_MASK))[(vma >> 12) % 1024] & PE_PRESENT); } -#define KERNEL_END (0x08000000) - void free_task_pd(void *pd) { uint32_t *pd_32 = pd; - for (uint16_t i = 0; i < 1024; ++i) + for (uint16_t i = KERNEL_END / 4096 / 1024; i < 1024; ++i) if (pd_32[i] & PE_PRESENT) { uint32_t *pt_32 = (uint32_t *)(pd_32[i] & PE_ADDR_MASK); - if (i >= KERNEL_END >> 22) - for (uint16_t j = 0; j < 1024; ++j) - if (pt_32[j] & PE_PRESENT) - free_pages((void *)(pt_32[j] & PE_ADDR_MASK), 1); + for (uint16_t j = 0; j < 1024; ++j) + if (pt_32[j] & PE_PRESENT) + free_pages((void *)(pt_32[j] & PE_ADDR_MASK), 1); free_pages(pt_32, 1); } free_pages(pd, 1); } +__attribute__ ((aligned (4096))) +static uint32_t kmap[KERNEL_END / 4096]; + void *new_task_pd() { - uint32_t *pd = new_pd(); - for (uint32_t addr = 0; addr < KERNEL_END; addr += 4096) - pd_map(pd, addr, addr, false); + uint32_t *pd = allocate_kernel_pages(1); + for (uint8_t i = 0; i < KERNEL_END / 4096 / 1024; ++i) + pd[i] = (uint32_t)(kmap + i * 1024) | PE_USER | PE_PRESENT; + for (uint16_t i = KERNEL_END / 4096 / 1024; i < 1024; ++i) + pd[i] = 0; return pd; } @@ -129,6 +119,9 @@ void init_paging() { for (uint16_t i = 0; i < 1024; ++i) KPAGE_DIR[i] = (uint32_t)(KPAGE_TABLE_0 + i * 1024) | PE_WRITABLE | PE_PRESENT; + for (uint16_t i = 0; i < KERNEL_END / 4096; ++i) + kmap[i] = (i * 4096) | PE_USER | PE_PRESENT; + asm volatile ( "mov $0x00005000, %%eax\n" "mov %%eax, %%cr3\n" diff --git a/src/kernel/paging.h b/src/kernel/paging.h index 07bf386..6c1a6f5 100644 --- a/src/kernel/paging.h +++ b/src/kernel/paging.h @@ -3,10 +3,6 @@ void init_paging(); -void *new_pd(); -void free_pd(void *pd); -void pd_map(void *pd, uint32_t physical_addr, uint32_t virtual_addr, bool writable); - void free_task_pd(void *pd); void *new_task_pd(); void *pd_user_allocate(void *pd, uint32_t vma, uint32_t pages, bool writable); diff --git a/src/kernel/pmap.c b/src/kernel/pmap.c index 8634303..37c7261 100644 --- a/src/kernel/pmap.c +++ b/src/kernel/pmap.c @@ -77,8 +77,14 @@ void init_pagemap() { //a smarter algorithm might pick the smallest one available, //and go by bytes (or dwords) instead of bits where possible. void *allocate_kernel_pages(uint32_t n) { +//logsz("trace: allocate_kernel_pages("); +//char nbuf[11]; +//u32_dec(n, nbuf); +//logsz(nbuf); +//logsz(") = 0x"); + uint32_t run = 0; - + for (uint32_t page = KBSS_START >> 12; page < USER_START >> 12; ++page) { if (PAGE_USED(page)) run = 0; @@ -87,6 +93,9 @@ void *allocate_kernel_pages(uint32_t n) { for (uint32_t i = start; i <= page; ++i) SET_PAGE(i); kernel_pages_left -= n; + //u32_hex(start << 12, nbuf); + //logsz(nbuf); + //logch('\n'); return (void *)(start << 12); } } @@ -98,8 +107,14 @@ void *allocate_kernel_pages(uint32_t n) { //a smarter algorithm might pick the smallest one available, //and go by bytes (or dwords) instead of bits where possible. void *allocate_user_pages(uint32_t n) { +//logsz("trace: allocate_user_pages("); +//char nbuf[11]; +//u32_dec(n, nbuf); +//logsz(nbuf); +//logsz(") = 0x"); + uint32_t run = 0; - + for (uint32_t page = USER_START >> 12; page < 1048576; ++page) { if (PAGE_USED(page)) run = 0; @@ -108,6 +123,9 @@ void *allocate_user_pages(uint32_t n) { for (uint32_t i = start; i <= page; ++i) SET_PAGE(i); user_pages_left -= n; + //u32_hex(start << 12, nbuf); + //logsz(nbuf); + //logch('\n'); return (void *)(start << 12); } } @@ -117,6 +135,15 @@ void *allocate_user_pages(uint32_t n) { //in the future, change this to go by bytes or dwords instead of bits. void free_pages(const void *ptr, uint32_t n) { +//logsz("trace: free_pages(0x"); +//char nbuf[11]; +//u32_hex(ptr, nbuf); +//logsz(nbuf); +//logsz(", "); +//u32_dec(n, nbuf); +//logsz(nbuf); +//logsz(")\n"); + uint32_t page = (uint32_t)ptr >> 12; for (uint32_t i = page; i < page + n; ++i) CLEAR_PAGE(i); diff --git a/src/kernel/task.c b/src/kernel/task.c index e2c19ca..6c53510 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -91,6 +91,8 @@ void make_sure_tasks() { } void delete_task(struct task_state *state) { + switch_to_kernel_cr3(); free_task_pd(state->page_directory); + switch_to_task_cr3(); state->page_directory = 0; } \ No newline at end of file diff --git a/src/kernel/task.h b/src/kernel/task.h index 838f27b..0fa9688 100644 --- a/src/kernel/task.h +++ b/src/kernel/task.h @@ -4,10 +4,11 @@ #include #include +#define TASK_NAME_LEN 15 + struct task_state { uint32_t ret_addr; void *page_directory; - //maybe put scheduling or priviledge information here? uint32_t ebx; uint32_t ecx; @@ -16,6 +17,8 @@ struct task_state { uint32_t edi; uint32_t ebp; uint32_t esp; + + char name[TASK_NAME_LEN + 1]; } __attribute__ ((packed)); extern struct task_state *active_task; diff --git a/src/kernel/vga.c b/src/kernel/vga.c index c03e5f0..daa92fe 100644 --- a/src/kernel/vga.c +++ b/src/kernel/vga.c @@ -31,6 +31,8 @@ void vga_blank() { void vga_printch(char ch) { if (ch == '\n') cursor = ((cursor - VGA_START) / VGA_COLUMNS + 1) * VGA_COLUMNS + VGA_START; + else if (ch == '\b') + *--cursor = mask | ' '; else *cursor++ = mask | (uint8_t)ch; if (cursor == VGA_END) diff --git a/src/user/dumphex/dumphex.c b/src/user/dumphex/dumphex.c new file mode 100644 index 0000000..4c63a06 --- /dev/null +++ b/src/user/dumphex/dumphex.c @@ -0,0 +1,29 @@ +#include +#include +#include + +void main(const char *path) { + struct file *f = open_file(path); + if (!f) { + tell_user_sz("Couldn't open file.\n"); + return; + } + char buf[] = { ' ', '\0', '\0', '\0' }; + uint8_t v; + uint32_t a = 0; + while (read_from_file(f, 1, &v)) { + if (!(a & 0xf)) { + char buf2[] = {'0', 'x', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0' }; + itosz_h32(a, buf2 + 2); + tell_user_sz(buf2); + tell_user_sz(" |"); + } + itosz_h8(v, buf + 1); + tell_user_sz(buf); + if (!(++a & 0xf)) + tell_user_sz("\n"); + } + tell_user_sz("\n"); + close_file(f); +} \ No newline at end of file diff --git a/src/user/dumptext/dumptext.c b/src/user/dumptext/dumptext.c new file mode 100644 index 0000000..b10375c --- /dev/null +++ b/src/user/dumptext/dumptext.c @@ -0,0 +1,15 @@ +#include +#include + +void main(const char *path) { + struct file *f = open_file(path); + if (!f) { + tell_user_sz("Couldn't open file.\n"); + return; + } + char buf[] = { '\0', '\0' }; + while (read_from_file(f, 1, buf)) + tell_user_sz(buf); + tell_user_sz("\n"); + close_file(f); +} \ No newline at end of file diff --git a/src/user/hello/hello.asm b/src/user/hello/hello.asm new file mode 100644 index 0000000..65d32be --- /dev/null +++ b/src/user/hello/hello.asm @@ -0,0 +1,14 @@ +bits 32 + +global _entry + +section .text +_entry: + mov eax, 0x5 + mov ebx, hello + int 0x30 + + int 0x38 + +section .data +hello db "Hello, world!", 0x0a, 0 \ No newline at end of file diff --git a/src/user/highway/highway.c b/src/user/highway/highway.c index effc131..8dc0080 100644 --- a/src/user/highway/highway.c +++ b/src/user/highway/highway.c @@ -6,8 +6,13 @@ //TODO: have an active disk and/or directory void main() { - char path_buf[1024 + 4] = "BIN/"; + char path_buf[1024 + 4] = "bin/"; char *const line_buf = path_buf + 4; + + tell_user_sz("Highway, Portland Command Shell, started.\n" + "Type \"exit\" to quit.\n"); + yield_task(); + while (1) { tell_user_sz("> "); ask_user_line_sz(line_buf, 1023); diff --git a/src/user/include/knob/format.h b/src/user/include/knob/format.h index 6c4aa5d..89402c0 100644 --- a/src/user/include/knob/format.h +++ b/src/user/include/knob/format.h @@ -6,5 +6,7 @@ bool try_sntoi(const char *s, uint32_t n, uint32_t *out); void itosz(uint32_t i, char *out); +void itosz_h8(uint8_t i, char *out); +void itosz_h32(uint32_t i, char *out); #endif \ No newline at end of file diff --git a/src/user/init/init.c b/src/user/init/init.c index 64c534e..390b731 100644 --- a/src/user/init/init.c +++ b/src/user/init/init.c @@ -3,25 +3,28 @@ #include void start(const char *cmd) { + tell_user_sz("[init] Starting "); tell_user_sz(cmd); tell_user_sz(": "); tell_user_sz( try_run_command(cmd) - ? "success\n" - : "failed\n" + ? "Succeded.\n" + : "Failed.\n" ); + tell_user_sz("[init] Yielding.\n"); + yield_task(); } -#define STARTUP_FILE_PATH "SYS/STARTUP.RC" +#define STARTUP_FILE_PATH "sys/startup.rc" void main() { struct file *f = open_file(STARTUP_FILE_PATH); if (!f) { - tell_user_sz("Could not open " STARTUP_FILE_PATH "\n"); + tell_user_sz("Could not open " STARTUP_FILE_PATH ".\n"); return; } - tell_user_sz("[init] Reading from " STARTUP_FILE_PATH ":\n"); + tell_user_sz("[init] Reading from " STARTUP_FILE_PATH ".\n"); char buf[1024]; char *bufp = buf; @@ -43,5 +46,5 @@ void main() { close_file(f); - tell_user_sz("[init] Done.\n"); + tell_user_sz("[init] Done starting programs.\n"); } diff --git a/src/user/knob/entry.asm b/src/user/knob/entry.asm index 18faf7f..acf6f5f 100644 --- a/src/user/knob/entry.asm +++ b/src/user/knob/entry.asm @@ -12,7 +12,6 @@ _entry: mov esp, stack push edx - ;TODO: heap stuff? ;TODO: determine current_disk ;any further needed initialization diff --git a/src/user/knob/format.c b/src/user/knob/format.c index 087f6fd..645fb73 100644 --- a/src/user/knob/format.c +++ b/src/user/knob/format.c @@ -28,4 +28,18 @@ void itosz(uint32_t i, char *out) { } } *out = '\0'; +} + +const char *const hex_digits = "0123456789abcdef"; + +void itosz_h8(uint8_t i, char *out) { + out[0] = hex_digits[i >> 4]; + out[1] = hex_digits[i & 0xf]; + out[2] = '\0'; +} + +void itosz_h32(uint32_t i, char *out) { + for (uint8_t digit = 0; digit < 8; ++digit) + out[digit] = hex_digits[(i >> (28 - digit * 4)) & 0xf]; + out[8] = '\0'; } \ No newline at end of file diff --git a/src/user/knob/user.c b/src/user/knob/user.c index 4ef3321..c84977c 100644 --- a/src/user/knob/user.c +++ b/src/user/knob/user.c @@ -165,16 +165,20 @@ uint32_t ask_user_line_sz(char *sz, uint32_t max_length) { goto replace; if (key & 0x80) goto replace;//TODO + if (key == '\b') { + if (i) { + --i; + _log_string("\b"); + } + goto replace; + } log_buf[0] = key; _log_string(log_buf); - if (key == '\b') - i -= i ? 2 : 1; - else if (key == '\n') + if (key == '\n') break; - else - sz[i] = key; + sz[i] = key; } sz[i] = '\0'; -- cgit v1.2.3