Improved fault handling
This commit is contained in:
parent
7f0a94352d
commit
de2edf1404
@ -94,8 +94,8 @@ mov gs, ax
|
|||||||
mov ss, ax
|
mov ss, ax
|
||||||
; check A20
|
; check A20
|
||||||
.a20:
|
.a20:
|
||||||
mov edi, 0x101337
|
mov edi, 0x107C00
|
||||||
mov esi, 0x001337
|
mov esi, 0x007C00
|
||||||
mov [esi], esi
|
mov [esi], esi
|
||||||
mov [edi], edi
|
mov [edi], edi
|
||||||
cmpsd
|
cmpsd
|
||||||
|
@ -8,6 +8,14 @@ mov ax, 0x10
|
|||||||
mov es, ax
|
mov es, ax
|
||||||
; move to 'safe' location
|
; move to 'safe' location
|
||||||
mov ebp, 0x318000
|
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
|
mov esp, ebp
|
||||||
call error_environment
|
call error_environment
|
||||||
.hlt:
|
.hlt:
|
||||||
@ -47,6 +55,7 @@ mov eax, dword [esp+16] ; EFLAGS
|
|||||||
and eax, 1 << 17 ; VM flag
|
and eax, 1 << 17 ; VM flag
|
||||||
test eax, eax
|
test eax, eax
|
||||||
pop eax
|
pop eax
|
||||||
|
mov dword [_gpf_eax_save], eax
|
||||||
jnz gpf_handler_v86
|
jnz gpf_handler_v86
|
||||||
jmp gpf_handler_32
|
jmp gpf_handler_32
|
||||||
gpf_unhandled:
|
gpf_unhandled:
|
||||||
|
17
interrupt.c
17
interrupt.c
@ -99,6 +99,7 @@ __attribute((__no_caller_saved_registers__))
|
|||||||
extern void return_prev_task();
|
extern void return_prev_task();
|
||||||
__attribute((__no_caller_saved_registers__))
|
__attribute((__no_caller_saved_registers__))
|
||||||
extern void error_environment(); // defined in kernel.c
|
extern void error_environment(); // defined in kernel.c
|
||||||
|
extern uint32_t _gpf_eax_save;
|
||||||
#define VALID_FLAGS 0xDFF
|
#define VALID_FLAGS 0xDFF
|
||||||
__attribute__ ((interrupt))
|
__attribute__ ((interrupt))
|
||||||
void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) {
|
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;
|
uint16_t *e = error_screen;
|
||||||
for (int i = 0; i < 80; i++)
|
for (int i = 0; i < 80; i++)
|
||||||
e[i] = 0x0f00;
|
e[i] = 0x0f00;
|
||||||
e += int_printStr("Unknown instruction caused V86 GPF: ", e);
|
e += int_printStr("Unknown instruction caused V86 GPF(", e);
|
||||||
*(uint32_t*)e = 0x1f001f00;
|
int_printWord(error_code, e);
|
||||||
|
e += 4;
|
||||||
|
e += int_printStr("):", e);
|
||||||
|
*(uint32_t*)e = 0x7f007f00;
|
||||||
int_printDword(*(uint32_t*)ip, e);
|
int_printDword(*(uint32_t*)ip, e);
|
||||||
e += 9;
|
e += 9;
|
||||||
*(uint8_t*)e = '@';
|
*(uint8_t*)e = '@';
|
||||||
@ -293,19 +297,14 @@ void set_trap_gate(uint8_t gate, void (*handler)()) {
|
|||||||
IDT[gate].type_attributes = 0x8F;
|
IDT[gate].type_attributes = 0x8F;
|
||||||
}
|
}
|
||||||
void setup_interrupts() {
|
void setup_interrupts() {
|
||||||
|
asm volatile("cli");
|
||||||
IDTR.size = 256*8 - 1;
|
IDTR.size = 256*8 - 1;
|
||||||
IDTR.offset = (uint32_t)(size_t)IDT;
|
IDTR.offset = (uint32_t)(size_t)IDT;
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
*(uint64_t*)&IDT[i] = 0;
|
*(uint64_t*)&IDT[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 9; i++) {
|
for (int i = 0; i < 256; 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++) {
|
|
||||||
set_trap_gate(i, unhandled_handler);
|
set_trap_gate(i, unhandled_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
kernel.c
43
kernel.c
@ -109,18 +109,31 @@ void ensure_v86env() {
|
|||||||
__attribute((__no_caller_saved_registers__))
|
__attribute((__no_caller_saved_registers__))
|
||||||
extern void return_prev_task();
|
extern void return_prev_task();
|
||||||
__attribute((__no_caller_saved_registers__))
|
__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();
|
ensure_v86env();
|
||||||
|
setup_interrupts(); // just in case
|
||||||
for (int i = 0; i < 80*50; i++)
|
for (int i = 0; i < 80*50; i++)
|
||||||
if (!(error_screen[i] & 0xFF00))
|
if (!(error_screen[i] & 0xFF00))
|
||||||
error_screen[i] = 0x0f00 | (error_screen[i] & 0x00FF);
|
error_screen[i] = 0x0f00 | (error_screen[i] & 0x00FF);
|
||||||
union V86Regs_t regs;
|
union V86Regs_t regs;
|
||||||
FARPTR v86_entry = i386LinearToFp(v86TextMode);
|
FARPTR v86_entry = i386LinearToFp(v86TextMode);
|
||||||
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
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(str0, &error_screen[80]);
|
||||||
printStr("Press E for a fun recovery :3", &error_screen[80+sizeof(str0)]);
|
uint16_t *tmp = &error_screen[80+sizeof(str0)-1];
|
||||||
printStr("Press R to return to previous task", &error_screen[160+sizeof(str0)]);
|
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);
|
uint16_t *vga_text = ((uint16_t*)0xB8000);
|
||||||
for (int i = 0; i < 80*50; i++)
|
for (int i = 0; i < 80*50; i++)
|
||||||
vga_text[i] = error_screen[i];
|
vga_text[i] = error_screen[i];
|
||||||
@ -225,6 +238,7 @@ void FileSelect() {
|
|||||||
int32_t fileHovered = 0, lastFileHovered = 0;
|
int32_t fileHovered = 0, lastFileHovered = 0;
|
||||||
for (char reload = 1;;) {
|
for (char reload = 1;;) {
|
||||||
// Info line (4)
|
// 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]);
|
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;
|
VOLINFO vi; DIRINFO di;
|
||||||
if (reload) {
|
if (reload) {
|
||||||
@ -253,7 +267,6 @@ void FileSelect() {
|
|||||||
case 0x14: // t
|
case 0x14: // t
|
||||||
create_child(0x380000, (uintptr_t)RunTests, 0);
|
create_child(0x380000, (uintptr_t)RunTests, 0);
|
||||||
SetCursorDisabled();
|
SetCursorDisabled();
|
||||||
DrawScreen();
|
|
||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_P:
|
case KEY_P:
|
||||||
@ -261,7 +274,6 @@ void FileSelect() {
|
|||||||
create_child(0x380000, (uintptr_t)ProgramLoadTest, 2, path, &vi);
|
create_child(0x380000, (uintptr_t)ProgramLoadTest, 2, path, &vi);
|
||||||
SetVideo25Lines();
|
SetVideo25Lines();
|
||||||
SetCursorDisabled();
|
SetCursorDisabled();
|
||||||
DrawScreen();
|
|
||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_X:
|
case KEY_X:
|
||||||
@ -270,7 +282,6 @@ void FileSelect() {
|
|||||||
create_child(0x380000, (uintptr_t)HexViewTest, 2, path, &vi);
|
create_child(0x380000, (uintptr_t)HexViewTest, 2, path, &vi);
|
||||||
SetVideo25Lines();
|
SetVideo25Lines();
|
||||||
SetCursorDisabled();
|
SetCursorDisabled();
|
||||||
DrawScreen();
|
|
||||||
break;
|
break;
|
||||||
case KEY_V:
|
case KEY_V:
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)path);
|
File83ToPath((char*)entries[fileHovered].name, (char*)path);
|
||||||
@ -278,7 +289,6 @@ void FileSelect() {
|
|||||||
create_child(0x380000, (uintptr_t)TextViewTest, 2, path, &vi);
|
create_child(0x380000, (uintptr_t)TextViewTest, 2, path, &vi);
|
||||||
SetVideo25Lines();
|
SetVideo25Lines();
|
||||||
SetCursorDisabled();
|
SetCursorDisabled();
|
||||||
DrawScreen();
|
|
||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -346,6 +356,21 @@ void start() {
|
|||||||
SetVideo25Lines();
|
SetVideo25Lines();
|
||||||
SetCursorDisabled();
|
SetCursorDisabled();
|
||||||
DrawScreen();
|
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;);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
tests.c
6
tests.c
@ -39,13 +39,13 @@ void TestDiskRead() {
|
|||||||
vga_text += printStr("Setting Text Mode... ", vga_text);
|
vga_text += printStr("Setting Text Mode... ", vga_text);
|
||||||
regs.w.ax = 3; // text mode
|
regs.w.ax = 3; // text mode
|
||||||
V8086Int(0x10, ®s);
|
V8086Int(0x10, ®s);
|
||||||
vga_text += printStr("Done. Starting Disk Read... ", vga_text);
|
//vga_text += printStr("Done. Starting Disk Read... ", vga_text);
|
||||||
char *diskReadBuf = (char *)0x8000;
|
char *diskReadBuf = (char *)0x20000;
|
||||||
v86disk_addr_packet.transfer_buffer =
|
v86disk_addr_packet.transfer_buffer =
|
||||||
(uintptr_t)diskReadBuf & 0x000F |
|
(uintptr_t)diskReadBuf & 0x000F |
|
||||||
(((uintptr_t)diskReadBuf & 0xFFFF0) << 12);
|
(((uintptr_t)diskReadBuf & 0xFFFF0) << 12);
|
||||||
FARPTR v86_entry = i386LinearToFp(v86DiskRead);
|
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;
|
vga_text = (uint16_t *)0xb8000;
|
||||||
for (int i = 0; i < (80*25)/2; i++) {
|
for (int i = 0; i < (80*25)/2; i++) {
|
||||||
printByte(diskReadBuf[i], &vga_text[i*2]);
|
printByte(diskReadBuf[i], &vga_text[i*2]);
|
||||||
|
@ -5,7 +5,7 @@ mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16
|
|||||||
mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16
|
mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16
|
||||||
mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16
|
mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16
|
||||||
mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 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 [0xb8000+160], 0x0f000f00 | 'F' | 'a' << 16
|
||||||
mov dword [0xb8004+160], 0x0f000f00 | 'u' | 'l' << 16
|
mov dword [0xb8004+160], 0x0f000f00 | 'u' | 'l' << 16
|
||||||
mov dword [0xb8008+160], 0x0f000f00 | 't' | 's' << 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 [0xb8004+480], 0x0f000f00 | ' ' | 'P' << 16
|
||||||
mov dword [0xb8008+480], 0x0f000f00 | 'G' | 'F' << 16
|
mov dword [0xb8008+480], 0x0f000f00 | 'G' | 'F' << 16
|
||||||
mov dword [0xb800C+480], 0x0f000f00 | 'L' | 'T' << 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
|
mov eax, 0 ; command = 00h, get key
|
||||||
int 0x21 ; OS call
|
int 0x21 ; OS call
|
||||||
cmp al, 'd'
|
cmp al, 'd'
|
||||||
je .div_err
|
je .div_err
|
||||||
cmp al, 'p'
|
cmp al, 'p'
|
||||||
je .page_err
|
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 0x00000013 ; eax AH=0,AL=3 set video mode 3
|
||||||
push 0x00000000 ; ecx
|
push 0x00000000 ; ecx
|
||||||
push 0x00000000 ; edx
|
push 0x00000000 ; edx
|
||||||
@ -43,9 +55,6 @@ inc al
|
|||||||
cmp eax, 200
|
cmp eax, 200
|
||||||
jl .loop
|
jl .loop
|
||||||
mov eax, 0xA0000
|
mov eax, 0xA0000
|
||||||
;mov ecx, 1000000000
|
|
||||||
;.dbg:
|
|
||||||
;loop .dbg
|
|
||||||
int 0x30 ; Exit
|
int 0x30 ; Exit
|
||||||
.page_err:
|
.page_err:
|
||||||
mov edx, 0x105000 ; somewhere in kernel mem
|
mov edx, 0x105000 ; somewhere in kernel mem
|
||||||
@ -53,3 +62,8 @@ mov edx, [edx] ; should page fault
|
|||||||
.div_err:
|
.div_err:
|
||||||
xor ebx, ebx
|
xor ebx, ebx
|
||||||
div bl ; Unhandled DIV0 exception
|
div bl ; Unhandled DIV0 exception
|
||||||
|
.undefined_err:
|
||||||
|
ud2 ; undefined instruction
|
||||||
|
.gpf_err:
|
||||||
|
mov ax, 0x10
|
||||||
|
mov ds, ax ; load ds with bad value
|
||||||
|
3
v86.nasm
3
v86.nasm
@ -97,7 +97,10 @@ mov ah, 0x42
|
|||||||
mov dl, 0x80 ; TODO get this from BIOS or something
|
mov dl, 0x80 ; TODO get this from BIOS or something
|
||||||
mov si, v86disk_addr_packet ; ds:si
|
mov si, v86disk_addr_packet ; ds:si
|
||||||
int 0x13
|
int 0x13
|
||||||
|
jc .err
|
||||||
int 0x30
|
int 0x30
|
||||||
|
.err:
|
||||||
|
ud2
|
||||||
jmp $
|
jmp $
|
||||||
global v86disk_addr_packet
|
global v86disk_addr_packet
|
||||||
v86disk_addr_packet:
|
v86disk_addr_packet:
|
||||||
|
Loading…
Reference in New Issue
Block a user