diff options
author | Benji Dial <benji6283@gmail.com> | 2020-09-13 17:12:29 -0400 |
---|---|---|
committer | Benji Dial <benji6283@gmail.com> | 2020-09-13 17:12:29 -0400 |
commit | 5481848e27fdd4fc859def9841a0283665531a46 (patch) | |
tree | 990a8df008214d85141a3bd10bd96898e64b0c37 /src/kernel | |
parent | 1e4a254674f668839e5de273916024c16814b045 (diff) | |
download | portland-os-5481848e27fdd4fc859def9841a0283665531a46.tar.gz |
fixed some paging bugs, added fault handlers and new programs
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/elf.c | 14 | ||||
-rw-r--r-- | src/kernel/fat.c | 15 | ||||
-rw-r--r-- | src/kernel/idt.c | 54 | ||||
-rw-r--r-- | src/kernel/isrs.asm | 73 | ||||
-rw-r--r-- | src/kernel/main.c | 2 | ||||
-rw-r--r-- | src/kernel/paging.c | 53 | ||||
-rw-r--r-- | src/kernel/paging.h | 4 | ||||
-rw-r--r-- | src/kernel/pmap.c | 31 | ||||
-rw-r--r-- | src/kernel/task.c | 2 | ||||
-rw-r--r-- | src/kernel/task.h | 5 | ||||
-rw-r--r-- | src/kernel/vga.c | 2 |
11 files changed, 209 insertions, 46 deletions
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 <stdbool.h> #include <stdint.h> +#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) |