Improved fault handling
This commit is contained in:
parent
7f0a94352d
commit
de2edf1404
@ -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
|
||||
|
@ -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:
|
||||
|
17
interrupt.c
17
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);
|
||||
}
|
||||
|
||||
|
43
kernel.c
43
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;);
|
||||
}
|
||||
}
|
||||
|
||||
|
6
tests.c
6
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]);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user