Improved fault handling

This commit is contained in:
Lucia Ceionia 2023-02-07 23:53:13 -06:00
parent 7f0a94352d
commit de2edf1404
7 changed files with 77 additions and 27 deletions

View File

@ -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

View File

@ -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:

View File

@ -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);
}

View File

@ -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), &regs);
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;);
}
}

View File

@ -39,13 +39,13 @@ void TestDiskRead() {
vga_text += printStr("Setting Text Mode... ", vga_text);
regs.w.ax = 3; // text mode
V8086Int(0x10, &regs);
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), &regs);
enter_v86(0x0000, 0x8000, FP_SEG(v86_entry), FP_OFF(v86_entry), &regs);
vga_text = (uint16_t *)0xb8000;
for (int i = 0; i < (80*25)/2; i++) {
printByte(diskReadBuf[i], &vga_text[i*2]);

View File

@ -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

View File

@ -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: