summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-10-17 23:49:32 +0200
committerAndreas Kling <awesomekling@gmail.com>2018-10-17 23:49:32 +0200
commit56c1f9db8e5e1f289858632acd3e84f419d6b267 (patch)
tree7bef6b37089b863234d0b1854140e88b33becc61 /Kernel
parent77299cf54d02066e37340cb7533ee6a070dd4166 (diff)
downloadserenity-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.cpp19
-rw-r--r--Kernel/Task.cpp8
-rw-r--r--Kernel/Task.h2
-rw-r--r--Kernel/VGA.cpp4
-rw-r--r--Kernel/i386.cpp64
-rw-r--r--Kernel/i386.h20
-rw-r--r--Kernel/i8253.cpp19
-rw-r--r--Kernel/init.cpp2
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"(&current->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);