From de2edf14045c209f5eef63a8392d00dc495721c3 Mon Sep 17 00:00:00 2001 From: Lucia Ceionia Date: Tue, 7 Feb 2023 23:53:13 -0600 Subject: [PATCH] Improved fault handling --- boot.nasm | 4 ++-- fault.nasm | 9 +++++++++ interrupt.c | 17 ++++++++--------- kernel.c | 43 ++++++++++++++++++++++++++++++++++--------- tests.c | 6 +++--- usermode.nasm | 22 ++++++++++++++++++---- v86.nasm | 3 +++ 7 files changed, 77 insertions(+), 27 deletions(-) diff --git a/boot.nasm b/boot.nasm index cd5738d..897e5a3 100644 --- a/boot.nasm +++ b/boot.nasm @@ -94,8 +94,8 @@ mov gs, ax mov ss, ax ; check A20 .a20: -mov edi, 0x101337 -mov esi, 0x001337 +mov edi, 0x107C00 +mov esi, 0x007C00 mov [esi], esi mov [edi], edi cmpsd diff --git a/fault.nasm b/fault.nasm index 5821935..9affccd 100644 --- a/fault.nasm +++ b/fault.nasm @@ -8,6 +8,14 @@ mov ax, 0x10 mov es, ax ; move to 'safe' location mov ebp, 0x318000 +; copy stack a bit +mov ecx, 0 +.copy: +mov eax, [esp+ecx*4] +mov [ebp+ecx*4], eax +inc ecx +cmp ecx, 6 +jl .copy mov esp, ebp call error_environment .hlt: @@ -47,6 +55,7 @@ mov eax, dword [esp+16] ; EFLAGS and eax, 1 << 17 ; VM flag test eax, eax pop eax +mov dword [_gpf_eax_save], eax jnz gpf_handler_v86 jmp gpf_handler_32 gpf_unhandled: diff --git a/interrupt.c b/interrupt.c index 46e8862..ae55cfa 100644 --- a/interrupt.c +++ b/interrupt.c @@ -99,6 +99,7 @@ __attribute((__no_caller_saved_registers__)) extern void return_prev_task(); __attribute((__no_caller_saved_registers__)) extern void error_environment(); // defined in kernel.c +extern uint32_t _gpf_eax_save; #define VALID_FLAGS 0xDFF __attribute__ ((interrupt)) void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) { @@ -233,8 +234,11 @@ void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) { uint16_t *e = error_screen; for (int i = 0; i < 80; i++) e[i] = 0x0f00; - e += int_printStr("Unknown instruction caused V86 GPF: ", e); - *(uint32_t*)e = 0x1f001f00; + e += int_printStr("Unknown instruction caused V86 GPF(", e); + int_printWord(error_code, e); + e += 4; + e += int_printStr("):", e); + *(uint32_t*)e = 0x7f007f00; int_printDword(*(uint32_t*)ip, e); e += 9; *(uint8_t*)e = '@'; @@ -293,19 +297,14 @@ void set_trap_gate(uint8_t gate, void (*handler)()) { IDT[gate].type_attributes = 0x8F; } void setup_interrupts() { + asm volatile("cli"); IDTR.size = 256*8 - 1; IDTR.offset = (uint32_t)(size_t)IDT; for (int i = 0; i < 256; i++) { *(uint64_t*)&IDT[i] = 0; } - for (int i = 0; i < 9; i++) { - set_trap_gate(i, unhandled_handler); - } - for (int i = 10; i < 15; i++) { - set_trap_gate(i, unhandled_handler); - } - for (int i = 16; i < 22; i++) { + for (int i = 0; i < 256; i++) { set_trap_gate(i, unhandled_handler); } diff --git a/kernel.c b/kernel.c index e2415b2..e9fc16d 100644 --- a/kernel.c +++ b/kernel.c @@ -109,18 +109,31 @@ void ensure_v86env() { __attribute((__no_caller_saved_registers__)) extern void return_prev_task(); __attribute((__no_caller_saved_registers__)) -void error_environment() { +void error_environment(uint32_t stack0, uint32_t stack1, uint32_t stack2, uint32_t stack3, uint32_t stack4, uint32_t stack5) { ensure_v86env(); + setup_interrupts(); // just in case for (int i = 0; i < 80*50; i++) if (!(error_screen[i] & 0xFF00)) error_screen[i] = 0x0f00 | (error_screen[i] & 0x00FF); union V86Regs_t regs; FARPTR v86_entry = i386LinearToFp(v86TextMode); enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); - char str0[] = "Oh noes!!! System error! ;c "; + char str0[] = "Oh noes!!! System error! ;c STKDMP:"; printStr(str0, &error_screen[80]); - printStr("Press E for a fun recovery :3", &error_screen[80+sizeof(str0)]); - printStr("Press R to return to previous task", &error_screen[160+sizeof(str0)]); + uint16_t *tmp = &error_screen[80+sizeof(str0)-1]; + tmp += printDword(stack0, tmp); + tmp++; + tmp += printDword(stack1, tmp); + tmp++; + tmp += printDword(stack2, tmp); + tmp = &error_screen[80*2+sizeof(str0)-1]; + tmp += printDword(stack3, tmp); + tmp++; + tmp += printDword(stack4, tmp); + tmp++; + tmp += printDword(stack5, tmp); + printStr("Press E for a fun recovery :3", &error_screen[80*2]); + printStr("Press R to return to previous task", &error_screen[80*3]); uint16_t *vga_text = ((uint16_t*)0xB8000); for (int i = 0; i < 80*50; i++) vga_text[i] = error_screen[i]; @@ -225,6 +238,7 @@ void FileSelect() { int32_t fileHovered = 0, lastFileHovered = 0; for (char reload = 1;;) { // Info line (4) + DrawScreen(); printStr("T to run tests - X to view in hex - V to view as text - P to load as program", &vga_text[80*4+2]); VOLINFO vi; DIRINFO di; if (reload) { @@ -253,7 +267,6 @@ void FileSelect() { case 0x14: // t create_child(0x380000, (uintptr_t)RunTests, 0); SetCursorDisabled(); - DrawScreen(); reload = 1; break; case KEY_P: @@ -261,7 +274,6 @@ void FileSelect() { create_child(0x380000, (uintptr_t)ProgramLoadTest, 2, path, &vi); SetVideo25Lines(); SetCursorDisabled(); - DrawScreen(); reload = 1; break; case KEY_X: @@ -270,7 +282,6 @@ void FileSelect() { create_child(0x380000, (uintptr_t)HexViewTest, 2, path, &vi); SetVideo25Lines(); SetCursorDisabled(); - DrawScreen(); break; case KEY_V: File83ToPath((char*)entries[fileHovered].name, (char*)path); @@ -278,7 +289,6 @@ void FileSelect() { create_child(0x380000, (uintptr_t)TextViewTest, 2, path, &vi); SetVideo25Lines(); SetCursorDisabled(); - DrawScreen(); reload = 1; break; default: @@ -346,6 +356,21 @@ void start() { SetVideo25Lines(); SetCursorDisabled(); DrawScreen(); - FileSelect(); + uint32_t stack; + asm volatile("mov %%esp,%%eax":"=a"(stack)); + stack = ((stack - 0x4000) / 0x1000) * 0x1000; + for (;;) { + create_child(stack, (uintptr_t)FileSelect, 0); + // should never return, so if it does, + // we have an error + SetVideo25Lines(); + SetCursorDisabled(); + DrawScreen(); + vga_text = &((word*)0xb8000)[80*4 + 2]; + vga_text += printStr("Error loading file select. Ensure the disk has a valid MBR and FAT partition.", vga_text); + vga_text = &((word*)0xb8000)[80*5 + 2]; + vga_text += printStr("Press R to retry.", vga_text); + for (;(get_scancode() & 0xff) != KEY_R;); + } } diff --git a/tests.c b/tests.c index b4f1a8e..a556435 100644 --- a/tests.c +++ b/tests.c @@ -39,13 +39,13 @@ void TestDiskRead() { vga_text += printStr("Setting Text Mode... ", vga_text); regs.w.ax = 3; // text mode V8086Int(0x10, ®s); - vga_text += printStr("Done. Starting Disk Read... ", vga_text); - char *diskReadBuf = (char *)0x8000; + //vga_text += printStr("Done. Starting Disk Read... ", vga_text); + char *diskReadBuf = (char *)0x20000; v86disk_addr_packet.transfer_buffer = (uintptr_t)diskReadBuf & 0x000F | (((uintptr_t)diskReadBuf & 0xFFFF0) << 12); FARPTR v86_entry = i386LinearToFp(v86DiskRead); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); + enter_v86(0x0000, 0x8000, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); vga_text = (uint16_t *)0xb8000; for (int i = 0; i < (80*25)/2; i++) { printByte(diskReadBuf[i], &vga_text[i*2]); diff --git a/usermode.nasm b/usermode.nasm index 6cc1a0b..2e5c355 100644 --- a/usermode.nasm +++ b/usermode.nasm @@ -5,7 +5,7 @@ mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16 mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16 mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16 mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 16 -mov word [0xb8010], 0x0f00 | '!' +mov dword [0xb8010], 0x0f000f00 | '!' mov dword [0xb8000+160], 0x0f000f00 | 'F' | 'a' << 16 mov dword [0xb8004+160], 0x0f000f00 | 'u' | 'l' << 16 mov dword [0xb8008+160], 0x0f000f00 | 't' | 's' << 16 @@ -18,12 +18,24 @@ mov dword [0xb8000+480], 0x0f000f00 | 'p' | ':' << 16 mov dword [0xb8004+480], 0x0f000f00 | ' ' | 'P' << 16 mov dword [0xb8008+480], 0x0f000f00 | 'G' | 'F' << 16 mov dword [0xb800C+480], 0x0f000f00 | 'L' | 'T' << 16 +mov dword [0xb8000+640], 0x0f000f00 | 'u' | ':' << 16 +mov dword [0xb8004+640], 0x0f000f00 | ' ' | '#' << 16 +mov dword [0xb8008+640], 0x0f000f00 | 'U' | 'D' << 16 +mov dword [0xb800C+640], 0x0f000f00 | '2' | ' ' << 16 +mov dword [0xb8000+800], 0x0f000f00 | 'g' | ':' << 16 +mov dword [0xb8004+800], 0x0f000f00 | ' ' | '#' << 16 +mov dword [0xb8008+800], 0x0f000f00 | 'G' | 'P' << 16 +mov dword [0xb800C+800], 0x0f000f00 | 'F' | ' ' << 16 mov eax, 0 ; command = 00h, get key int 0x21 ; OS call cmp al, 'd' je .div_err cmp al, 'p' je .page_err +cmp al, 'u' +je .undefined_err +cmp al, 'g' +je .gpf_err push 0x00000013 ; eax AH=0,AL=3 set video mode 3 push 0x00000000 ; ecx push 0x00000000 ; edx @@ -43,9 +55,6 @@ inc al cmp eax, 200 jl .loop mov eax, 0xA0000 -;mov ecx, 1000000000 -;.dbg: -;loop .dbg int 0x30 ; Exit .page_err: mov edx, 0x105000 ; somewhere in kernel mem @@ -53,3 +62,8 @@ mov edx, [edx] ; should page fault .div_err: xor ebx, ebx div bl ; Unhandled DIV0 exception +.undefined_err: +ud2 ; undefined instruction +.gpf_err: +mov ax, 0x10 +mov ds, ax ; load ds with bad value diff --git a/v86.nasm b/v86.nasm index a761599..4ec03c3 100644 --- a/v86.nasm +++ b/v86.nasm @@ -97,7 +97,10 @@ mov ah, 0x42 mov dl, 0x80 ; TODO get this from BIOS or something mov si, v86disk_addr_packet ; ds:si int 0x13 +jc .err int 0x30 +.err: +ud2 jmp $ global v86disk_addr_packet v86disk_addr_packet: