More advanced Fault handling (recovers to text mode), Keyboard handler converted to C and improved (shifting, simple get_key added)

This commit is contained in:
Lucia Ceionia 2023-02-01 20:42:05 -06:00
parent 0faa2eb553
commit 679eb8cf57
9 changed files with 293 additions and 175 deletions

View File

@ -1,4 +1,4 @@
objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o usermode.o paging.o objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o usermode.o paging.o fault.o
CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding -march=pentium-m -fno-stack-protector -Wno-int-conversion -nostdlib -c CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding -march=pentium-m -fno-stack-protector -Wno-int-conversion -nostdlib -c
%.o: %.nasm %.o: %.nasm

View File

@ -47,7 +47,7 @@ out 0x92, al
after: after:
mov esi, 0x8000 mov esi, 0x8000
mov edi, 0x100000 mov edi, 0x100000
mov ecx, 17000 mov ecx, 0x10000
rep movsb rep movsb
jmp 08h:0x100000 jmp 08h:0x100000
gdt_desc: gdt_desc:

146
fault.nasm Normal file
View File

@ -0,0 +1,146 @@
extern error_screen ; 80x50 words
; Switches to text mode and shit
extern error_environment
_fault_coda:
xchg bx,bx
mov ax, 0x10
mov es, ax
; move to TOP OF kernel stack
mov ebp, 0x400000
mov esp, ebp
call error_environment
.hlt:
hlt
jmp .hlt
global unhandled_handler
unhandled_handler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | 'E' | 'R' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'R' | 'O' << 16
mov dword [error_screen+0x08], 0x0f000f00 | 'R' | '!' << 16
jmp _fault_coda
global pageFaultHandler
pageFaultHandler:
mov ax, 0x10
mov ds, ax
pop eax ; error code
mov ebx, 0x0f000f00 | '0' | '!' << 16
and eax, 0x7 ; U/S,R/W,P
add ebx, eax
mov dword [error_screen+0x00], 0x0f000f00 | 'P' | 'G' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'F' | 'L' << 16
mov dword [error_screen+0x08], 0x0f000f00 | 'T' | ':' << 16
mov dword [error_screen+0x0C], ebx
jmp _fault_coda
extern gpf_handler_v86
global gpfHandler
gpfHandler:
push eax
mov ax, 0x10
mov ds, ax
mov eax, dword [esp+16] ; EFLAGS
and eax, 1 << 17 ; VM flag
test eax, eax
pop eax
jnz gpf_handler_v86
jmp gpf_handler_32
gpf_unhandled:
mov dword [error_screen+0x00], 0x0f000f00 | 'G' | 'P' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'F' | '!' << 16
jmp _fault_coda
gpf_handler_32:
push eax
mov eax, dword [esp+8] ; EIP
movzx eax, word [eax]
cmp eax, 0x30CD ; int 0x30
jne gpf_unhandled
pop eax ; return value
jmp return_prev_task
extern return_prev_task
global divisionErrorHandler
divisionErrorHandler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'D' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'E' | '!' << 16
jmp _fault_coda
global boundRangeHandler
boundRangeHandler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'B' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'R' | '!' << 16
jmp _fault_coda
global invalidOpcodeHandler
invalidOpcodeHandler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'U' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'D' | '!' << 16
jmp _fault_coda
global deviceNotAvailableHandler
deviceNotAvailableHandler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'N' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'D' | '!' << 16
jmp _fault_coda
global doubleFaultHandler
doubleFaultHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000+0x00], 0x0f000f00 | '#' | 'D' << 16
mov dword [0xb8000+0x04], 0x0f000f00 | 'F' | '!' << 16
; double faults simply abort right then
.hlt: hlt
jmp .hlt
global invalidTSSHandler
invalidTSSHandler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'T' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'S' | '!' << 16
jmp _fault_coda
global segmentNotPresentHandler
segmentNotPresentHandler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'N' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'P' | '!' << 16
jmp _fault_coda
global stackSegmentHandler
stackSegmentHandler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'S' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'S' | '!' << 16
jmp _fault_coda
global x87FloatingHandler
x87FloatingHandler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'M' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'F' | '!' << 16
jmp _fault_coda
global alignmentCheckHandler
alignmentCheckHandler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'A' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'C' | '!' << 16
jmp _fault_coda
global controlProtectionHandler
controlProtectionHandler:
mov ax, 0x10
mov ds, ax
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'C' << 16
mov dword [error_screen+0x04], 0x0f000f00 | 'P' | '!' << 16
jmp _fault_coda

View File

@ -1,61 +1,4 @@
extern unhandled_handler oldscancodesToAscii: db 0, 0 ; 0x00 - 0x01
unhandled_handler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | 'E' | 'R' << 16
mov dword [0xb8004], 0x0f000f00 | 'R' | 'O' << 16
mov dword [0xb8008], 0x0f000f00 | 'R' | '!' << 16
.hlt:
hlt
jmp .hlt
global pageFaultHandler
pageFaultHandler:
mov ax, 0x10
mov ds, ax
pop eax ; error code
mov ebx, 0x0f000f00 | '0' | '!' << 16
and eax, 0x7 ; U/S,R/W,P
add ebx, eax
mov dword [0xb8000], 0x0f000f00 | 'P' | 'G' << 16
mov dword [0xb8004], 0x0f000f00 | 'F' | 'L' << 16
mov dword [0xb8008], 0x0f000f00 | 'T' | ':' << 16
mov dword [0xb800C], ebx
.hlt:
hlt
jmp .hlt
extern gpf_handler_v86
global gpfHandler
gpfHandler:
push eax
mov ax, 0x10
mov ds, ax
mov eax, dword [esp+16] ; EFLAGS
and eax, 1 << 17 ; VM flag
test eax, eax
pop eax
jnz gpf_handler_v86
jmp gpf_handler_32
gpf_unhandled:
mov dword [0xb8000], 0x0f000f00 | 'G' | 'P' << 16
mov dword [0xb8004], 0x0f000f00 | 'F' | '!' << 16
.hlt:
hlt
jmp .hlt
gpf_handler_32:
push eax
mov eax, dword [esp+8] ; EIP
movzx eax, word [eax]
cmp eax, 0x30CD ; int 0x30
jne gpf_unhandled
pop eax ; return value
jmp return_prev_task
extern return_prev_task
scancodesToAscii: db 0, 0 ; 0x00 - 0x01
db "1234567890" ; 0x02 - 0x0B db "1234567890" ; 0x02 - 0x0B
db "-=" ; 0x0C - 0x0D db "-=" ; 0x0C - 0x0D
db 0, 0 ; 0x0E - 0x0F db 0, 0 ; 0x0E - 0x0F
@ -71,8 +14,8 @@ db ' ' ; 0x39
db 'C' db 'C'
scancodesToAsciiEnd: scancodesToAsciiEnd:
cursorCurrent: dd 0xb8000 + (80*6*2) cursorCurrent: dd 0xb8000 + (80*6*2)
global keyboardHandler global oldkeyboardHandler
keyboardHandler: oldkeyboardHandler:
push eax push eax
push ebx push ebx
push ds push ds
@ -82,7 +25,7 @@ xor eax, eax
in al, 0x60 in al, 0x60
cmp eax, 0x3A cmp eax, 0x3A
jg .done jg .done
mov al, [scancodesToAscii+eax] mov al, [oldscancodesToAscii+eax]
test al, al test al, al
jz .done jz .done
mov ebx, [cursorCurrent] mov ebx, [cursorCurrent]
@ -98,8 +41,7 @@ pop eax
iret iret
KBDWAIT: db 0 KBDWAIT: db 0
global kbd_wait oldkbd_wait:
kbd_wait:
mov byte [KBDWAIT], 0 mov byte [KBDWAIT], 0
.loop: .loop:
hlt hlt
@ -108,13 +50,15 @@ test eax, eax
jz .loop jz .loop
ret ret
TIMERVAL: dd 0
global timerHandler global timerHandler
timerHandler: timerHandler:
push eax push eax
push ds push ds
mov ax, 0x10 mov ax, 0x10
mov ds, ax mov ds, ax
inc byte [(0xb8000 + (80*8*2))] ;inc byte [(0xb8000 + (80*8*2))]
inc dword [TIMERVAL]
mov al, 0x20 mov al, 0x20
out 0x20, al out 0x20, al
pop ds pop ds
@ -159,103 +103,3 @@ jmp $+2
jmp $+2 jmp $+2
out 0xA1, al out 0xA1, al
ret ret
global divisionErrorHandler
divisionErrorHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'D' << 16
mov dword [0xb8004], 0x0f000f00 | 'E' | '!' << 16
.hlt:
hlt
jmp .hlt
global boundRangeHandler
boundRangeHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'B' << 16
mov dword [0xb8004], 0x0f000f00 | 'R' | '!' << 16
.hlt:
hlt
jmp .hlt
global invalidOpcodeHandler
invalidOpcodeHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'U' << 16
mov dword [0xb8004], 0x0f000f00 | 'D' | '!' << 16
.hlt:
hlt
jmp .hlt
global deviceNotAvailableHandler
deviceNotAvailableHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'N' << 16
mov dword [0xb8004], 0x0f000f00 | 'D' | '!' << 16
.hlt:
hlt
jmp .hlt
global doubleFaultHandler
doubleFaultHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'D' << 16
mov dword [0xb8004], 0x0f000f00 | 'F' | '!' << 16
.hlt:
hlt
jmp .hlt
global invalidTSSHandler
invalidTSSHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'T' << 16
mov dword [0xb8004], 0x0f000f00 | 'S' | '!' << 16
.hlt:
hlt
jmp .hlt
global segmentNotPresentHandler
segmentNotPresentHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'N' << 16
mov dword [0xb8004], 0x0f000f00 | 'P' | '!' << 16
.hlt:
hlt
jmp .hlt
global stackSegmentHandler
stackSegmentHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'S' << 16
mov dword [0xb8004], 0x0f000f00 | 'S' | '!' << 16
.hlt:
hlt
jmp .hlt
global x87FloatingHandler
x87FloatingHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'M' << 16
mov dword [0xb8004], 0x0f000f00 | 'F' | '!' << 16
.hlt:
hlt
jmp .hlt
global alignmentCheckHandler
alignmentCheckHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'A' << 16
mov dword [0xb8004], 0x0f000f00 | 'C' | '!' << 16
.hlt:
hlt
jmp .hlt
global controlProtectionHandler
controlProtectionHandler:
mov ax, 0x10
mov ds, ax
mov dword [0xb8000], 0x0f000f00 | '#' | 'C' << 16
mov dword [0xb8004], 0x0f000f00 | 'P' | '!' << 16
.hlt:
hlt
jmp .hlt

View File

@ -84,8 +84,6 @@ void IRQ_clear_mask(char IRQline) {
char v86_if = 0; char v86_if = 0;
extern uint16_t *ivt; extern uint16_t *ivt;
extern void real_test(); extern void real_test();
__attribute((__no_caller_saved_registers__))
extern void kbd_wait();
extern void jmp_usermode_test(); extern void jmp_usermode_test();
__attribute((__no_caller_saved_registers__)) __attribute((__no_caller_saved_registers__))
extern void return_prev_task(); extern void return_prev_task();
@ -236,8 +234,81 @@ void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) {
vga[0] = 'G'; vga[2] = 'S'; int_printWord(frame->gs, (uint16_t*)&vga[4]); vga += 14; vga[0] = 'G'; vga[2] = 'S'; int_printWord(frame->gs, (uint16_t*)&vga[4]); vga += 14;
} }
uint8_t scancodesToAscii[0x3B] =
"\0\0" // 0x00 - 0x01
"1234567890" // 0x02 - 0x0B
"-=" // 0x0C - 0x0D
"\0\0" // 0x0E - 0x0F
"qwertyuiop[]" // 0x10 - 0x1B
"\0\0" // 0x1C - 0x1D
"asdfghjkl;'`" // 0x1E - 0x29
"\0" // 0x2A
"\\zxcvbnm,./" // 0x2B - 0x35
"\0" // 0x36
"*" // 0x37
"\0" // 0x38
" " // 0x39
"\0"; // 0x3A
uint8_t scancodesToAsciiShift[0x3B] =
"\0\0" // 0x00 - 0x01
"!@#$%^&*()" // 0x02 - 0x0B
"_+" // 0x0C - 0x0D
"\0\0" // 0x0E - 0x0F
"QWERTYUIOP{}" // 0x10 - 0x1B
"\0\0" // 0x1C - 0x1D
"ASDFGHJKL:\"~" // 0x1E - 0x29
"\0" // 0x2A
"|ZXCVBNM<>?" // 0x2B - 0x35
"\0" // 0x36
"*" // 0x37
"\0" // 0x38
" " // 0x39
"\0"; // 0x3A
uint8_t _KBDWAIT;
uint8_t _KEYCAPS = 0, _KEYSHIFT = 0;
uint8_t _LSTKEY = 0;
__attribute__ ((interrupt))
void keyboardHandler(struct interrupt_frame *frame) {
uint8_t key;
asm volatile("inb $0x60, %%al":"=a"(key));
if (key == 0x3A) { // caps lock press
_KEYCAPS = !_KEYCAPS;
} else if (key == 0x2A || key == 0x36) { // left and right shift press
_KEYSHIFT = 1;
} else if (key == 0xAA || key == 0xB6) { // left and right shift release
_KEYSHIFT = 0;
} else if (key < 0x3B) {
uint8_t ascii = _KEYCAPS != _KEYSHIFT ?
scancodesToAsciiShift[key] :
scancodesToAscii[key];
if (ascii) {
_LSTKEY = ascii;
_KBDWAIT = 1;
}
}
asm volatile("outb %%al, $0x20"::"a"(0x20));
}
__attribute((__no_caller_saved_registers__))
void kbd_wait() {
_KBDWAIT = 0;
while(!_KBDWAIT) {
asm volatile("hlt");
}
}
__attribute((__no_caller_saved_registers__))
uint8_t get_key() {
while(!_LSTKEY) {
asm volatile("hlt");
}
uint8_t k = _LSTKEY;
_LSTKEY = 0;
return k;
}
extern void timerHandler(); extern void timerHandler();
extern void keyboardHandler(); //extern void keyboardHandler();
extern void gpfHandler(); extern void gpfHandler();
extern void pageFaultHandler(); extern void pageFaultHandler();
extern void unhandled_handler(); extern void unhandled_handler();

View File

@ -28,6 +28,11 @@ typedef uint32_t FARPTR;
FARPTR i386LinearToFp(void *ptr); FARPTR i386LinearToFp(void *ptr);
__attribute((__no_caller_saved_registers__))
void kbd_wait();
__attribute((__no_caller_saved_registers__))
uint8_t get_key();
__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);

View File

@ -69,16 +69,14 @@ extern void v86GfxMode();
extern void v86TextMode(); extern void v86TextMode();
extern void v86DiskRead(); extern void v86DiskRead();
extern char *jmp_usermode_test(); extern char *jmp_usermode_test();
__attribute((__no_caller_saved_registers__))
extern void kbd_wait();
extern char _edata, _v86code, _ev86code, _bstart, _bend, _loadusercode, _usercode, _eusercode; extern char _edata, _v86code, _ev86code, _bstart, _bend, _loadusercode, _usercode, _eusercode;
void setup_binary() { void setup_binary() {
// Put V86 code in proper place based on linker // Put V86 code in proper place based on linker
char *s = &_edata; char *s = &_edata;
char *d = &_v86code; char *d = &_v86code;
//while (d < &_ev86code) while (d < &_ev86code)
// *d++ = *s++; *d++ = *s++;
// Put Usermode code in proper place based on linker // Put Usermode code in proper place based on linker
s = &_loadusercode; s = &_loadusercode;
@ -91,6 +89,42 @@ void setup_binary() {
*d = 0; *d = 0;
} }
uint16_t error_screen[80*50]; // 50-line VGA screen of error content
extern uint16_t *ivt;
uint16_t ivt_bkup[0x200];
uint8_t bios_bkup[0x40000];
void backup_ivtbios() {
for (int i = 0; i < 0x200; i++)
ivt_bkup[i] = ivt[i];
for (int i = 0; i < 0x40000; i++)
bios_bkup[i] = ((uint8_t*)0xC0000)[i];
}
// This should only be used during fault handling, as it is expensive
void ensure_v86env() {
for (int i = 0; i < 0x200; i++)
ivt[i] = ivt_bkup[i];
for (int i = 0; i < 0x40000; i++)
((uint8_t*)0xC0000)[i] = bios_bkup[i];
char *s = &_edata;
char *d = &_v86code;
while (d < &_ev86code)
*d++ = *s++;
for (int i = 0; i < 80*50; i++)
if (!error_screen[i]) error_screen[i] = 0x0f00;
}
void error_environment() {
ensure_v86env();
FARPTR v86_entry = i386LinearToFp(v86TextMode);
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry));
printStr("Oh noes!!! System error! ;c", &error_screen[80]);
uint16_t *vga_text = ((uint16_t*)0xB8000);
for (int i = 0; i < 80*50; i++)
vga_text[i] = error_screen[i];
}
/* /*
Real Mode Accessible (First MB) Real Mode Accessible (First MB)
00000 - 00400 IVT (1kB) 00000 - 00400 IVT (1kB)
@ -260,14 +294,30 @@ void start() {
//print_cr4(); //print_cr4();
vga_text += printStr("V86 Test... ", vga_text); vga_text += printStr("V86 Test... ", vga_text);
//asm ("xchgw %bx, %bx");
TestV86(); // has int 3 wait in v86 TestV86(); // has int 3 wait in v86
vga_text = (word *)0xb8000 + (80*3); vga_text = (word *)0xb8000 + (80*3);
printStr("Done. Press any key for next test.", vga_text); backup_ivtbios();
vga_text += printStr("Done. Press 'N' for next test.", vga_text);
uint8_t key;
while ((key = get_key()) != 'N') {
*vga_text = (*vga_text & 0xFF00) | key;
vga_text++;
}
TestGfx(); TestGfx();
kbd_wait(); kbd_wait();
TestDiskRead(); TestDiskRead();
kbd_wait(); kbd_wait();
TestFAT(); TestFAT();
kbd_wait(); kbd_wait();
vga_text = &((uint16_t*)0xB8000)[80*16];
vga_text += printStr("Press ` for a flagrant system error... ", vga_text);
while ((key = get_key()) != '`') {
*vga_text = (*vga_text & 0xFF00) | key;
vga_text++;
}
// flagrant system error
*((uint8_t*)0x1000000) = 0;
} }

View File

@ -15,7 +15,7 @@ SECTIONS {
_edata = .; _edata = .;
} }
.realmode (0x8000 + ADDR(.data) + SIZEOF(.data) - 0x100000) : .realmode 0x8000 :
AT ( ADDR(.data) + SIZEOF(.data) ) AT ( ADDR(.data) + SIZEOF(.data) )
{ _v86code = .; *(.v86); _ev86code = .; } { _v86code = .; *(.v86); _ev86code = .; }

View File

@ -16,5 +16,7 @@ cmp eax, 200
jl .loop jl .loop
mov eax, 0xA0000 mov eax, 0xA0000
int 0x30 ; Exit int 0x30 ; Exit
mov edx, 0x105000 ; somewhere in kernel mem
mov edx, [edx] ; should page fault
xor ebx, ebx xor ebx, ebx
div bl ; Unhandled DIV0 exception div bl ; Unhandled DIV0 exception