diff options
author | Andreas Kling <awesomekling@gmail.com> | 2018-10-17 23:49:32 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2018-10-17 23:49:32 +0200 |
commit | 56c1f9db8e5e1f289858632acd3e84f419d6b267 (patch) | |
tree | 7bef6b37089b863234d0b1854140e88b33becc61 /Kernel | |
parent | 77299cf54d02066e37340cb7533ee6a070dd4166 (diff) | |
download | serenity-56c1f9db8e5e1f289858632acd3e84f419d6b267.zip |
A userspace process can now GPF and the OS goes on!
This is really rickety, but it kinda sorta works for my test GPF!
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Syscall.cpp | 19 | ||||
-rw-r--r-- | Kernel/Task.cpp | 8 | ||||
-rw-r--r-- | Kernel/Task.h | 2 | ||||
-rw-r--r-- | Kernel/VGA.cpp | 4 | ||||
-rw-r--r-- | Kernel/i386.cpp | 64 | ||||
-rw-r--r-- | Kernel/i386.h | 20 | ||||
-rw-r--r-- | Kernel/i8253.cpp | 19 | ||||
-rw-r--r-- | Kernel/init.cpp | 2 |
8 files changed, 96 insertions, 42 deletions
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 163b11af74..e6f10cae20 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -3,25 +3,6 @@ #include "Task.h" #include "Syscall.h" -struct RegisterDump { - WORD gs; - WORD fs; - WORD es; - WORD ds; - DWORD edi; - DWORD esi; - DWORD ebp; - DWORD esp; - DWORD ebx; - DWORD edx; - DWORD ecx; - DWORD eax; - DWORD eip; - WORD cs; - WORD __csPadding; - DWORD eflags; -} PACKED; - extern "C" void syscall_entry(); extern "C" void syscall_ISR(); extern volatile RegisterDump* syscallRegDump; diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index a8b14e34b9..d4bc462114 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -185,11 +185,15 @@ void yield() if (!scheduleNewTask()) return; + //kprintf("yield() jumping to new task: %x (%s)\n", current->farPtr().selector, current->name().characters()); + switchNow(); +} + +void switchNow() +{ Descriptor& descriptor = getGDTEntry(current->selector()); descriptor.type = 9; flushGDT(); - - //kprintf("yield() jumping to new task: %x (%s)\n", current->farPtr().selector, current->name().characters()); asm( "ljmp *(%%eax)\n" ::"a"(¤t->farPtr()) diff --git a/Kernel/Task.h b/Kernel/Task.h index 9929da4b7f..21fad1857f 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -29,6 +29,7 @@ public: BlockedSend = 4, BlockedSleep = 5, Terminated = 6, + Crashing = 7, }; enum RingLevel { @@ -121,6 +122,7 @@ private: extern void task_init(); extern void yield(); extern bool scheduleNewTask(); +extern void switchNow(); extern void block(Task::State); extern void sleep(DWORD ticks); diff --git a/Kernel/VGA.cpp b/Kernel/VGA.cpp index 837b0c2a7b..8f23cf9b67 100644 --- a/Kernel/VGA.cpp +++ b/Kernel/VGA.cpp @@ -90,6 +90,10 @@ int kprintfInternal(PutChFunc putch, char* buffer, const char*& fmt, char*& ap) ret += printHex(putch, bufptr, va_arg(ap, DWORD), 8); break; + case 'w': + ret += printHex(putch, bufptr, va_arg(ap, int), 4); + break; + case 'b': ret += printHex(putch, bufptr, va_arg(ap, int), 2); break; diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index a3c0ed3816..47f156772a 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -26,6 +26,68 @@ WORD allocateGDTEntry() return newGDTEntry; } +extern volatile dword exception_state_dump; +extern volatile word exception_code; +asm( + ".globl exception_state_dump\n" + "exception_state_dump:\n" + ".long 0\n" + ".globl exception_code\n" + "exception_code:\n" + ".short 0\n" +); + +#define EH_ENTRY(ec) \ +extern "C" void exception_ ## ec ## _handler(); \ +extern "C" void exception_ ## ec ## _entry(); \ +asm( \ + ".globl exception_" # ec "_entry\n" \ + "exception_" # ec "_entry: \n" \ + " pop exception_code\n" \ + " pusha\n" \ + " pushw %ds\n" \ + " pushw %es\n" \ + " pushw %fs\n" \ + " pushw %gs\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " popw %ds\n" \ + " popw %es\n" \ + " popw %fs\n" \ + " popw %gs\n" \ + " mov %esp, exception_state_dump\n" \ + " call exception_" # ec "_handler\n" \ + " popw %gs\n" \ + " popw %fs\n" \ + " popw %es\n" \ + " popw %ds\n" \ + " popa\n" \ + " iret\n" \ +); + +EH_ENTRY(13) + +void exception_13_handler() +{ + auto& regs = *reinterpret_cast<RegisterDump*>(exception_state_dump); + kprintf("Process crash: %u(%s)\n", current->pid(), current->name().characters()); + + kprintf("exception code: %w\n", exception_code); + kprintf("pc=%w:%x ds=%w es=%w fs=%w gs=%w\n", regs.cs, regs.eip, regs.ds, regs.es, regs.fs, regs.gs); + kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx); + kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, regs.esp, regs.esi, regs.edi); + + current->setState(Task::Crashing); + if (!scheduleNewTask()) { + kprintf("Failed to schedule a new task :(\n"); + HANG; + } + + switchNow(); +} + #define EH(i, msg) \ static void _exception ## i () \ { \ @@ -164,7 +226,7 @@ void idt_init() registerInterruptHandler(0x0a, _exception10); registerInterruptHandler(0x0b, _exception11); registerInterruptHandler(0x0c, _exception12); - registerInterruptHandler(0x0d, _exception13); + registerInterruptHandler(0x0d, exception_13_entry); registerInterruptHandler(0x0e, _exception14); registerInterruptHandler(0x0f, _exception15); registerInterruptHandler(0x10, _exception16); diff --git a/Kernel/i386.h b/Kernel/i386.h index 86c8003fb9..c96001af22 100644 --- a/Kernel/i386.h +++ b/Kernel/i386.h @@ -75,3 +75,23 @@ void writeGDTEntry(WORD selector, Descriptor&); /* Map IRQ0-15 @ ISR 0x50-0x5F */ #define IRQ_VECTOR_BASE 0x50 + +struct RegisterDump { + WORD gs; + WORD fs; + WORD es; + WORD ds; + DWORD edi; + DWORD esi; + DWORD ebp; + DWORD esp; + DWORD ebx; + DWORD edx; + DWORD ecx; + DWORD eax; + DWORD eip; + WORD cs; + WORD __csPadding; + DWORD eflags; +} PACKED; + diff --git a/Kernel/i8253.cpp b/Kernel/i8253.cpp index 42eea444b5..86319bb135 100644 --- a/Kernel/i8253.cpp +++ b/Kernel/i8253.cpp @@ -63,25 +63,6 @@ asm( /* Miscellaneous */ #define BASE_FREQUENCY 1193182 -struct RegisterDump { - WORD gs; - WORD fs; - WORD es; - WORD ds; - DWORD edi; - DWORD esi; - DWORD ebp; - DWORD esp; - DWORD ebx; - DWORD edx; - DWORD ecx; - DWORD eax; - DWORD eip; - WORD cs; - WORD __csPadding; - DWORD eflags; -} PACKED; - void clock_handle() { IRQHandlerScope scope(IRQ_TIMER); diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 7e4b3e964a..2b2b716f0b 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -69,7 +69,7 @@ static void user_main() // Crash ourselves! char* x = reinterpret_cast<char*>(0xbeefbabe); //*x = 1; - //HANG; + HANG; for (;;) { // nothing? Userspace::sleep(1 * TICKS_PER_SECOND); |