summaryrefslogtreecommitdiff
path: root/Kernel/i386.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-05 13:48:07 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-05 13:48:07 +0100
commit2d045d2a647ad5fab57fbb1ec8339a44b9770cc3 (patch)
treef00f3e64819657f25f3d36c56c3e0076d63d82a6 /Kernel/i386.cpp
parente85c22fe58a39aa930251ad5e14c7dd6979a163f (diff)
downloadserenity-2d045d2a647ad5fab57fbb1ec8339a44b9770cc3.zip
Implement COW pages! :^)
sys$fork() now clones all writable regions with per-page COW bits. The pages are then mapped read-only and we handle a PF by COWing the pages. This is quite delightful. Obviously there's lots of work to do still, and it needs better data structures, but the general concept works.
Diffstat (limited to 'Kernel/i386.cpp')
-rw-r--r--Kernel/i386.cpp58
1 files changed, 24 insertions, 34 deletions
diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp
index 0eefee4676..dfc903a48c 100644
--- a/Kernel/i386.cpp
+++ b/Kernel/i386.cpp
@@ -56,24 +56,12 @@ asm(
" iret\n"
);
-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 ## _handler(RegisterDumpWithExceptionCode&); \
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" \
@@ -88,7 +76,7 @@ asm( \
" popw %es\n" \
" popw %fs\n" \
" popw %gs\n" \
- " mov %esp, exception_state_dump\n" \
+ " mov %esp, %eax\n" \
" call exception_" # ec "_handler\n" \
" popw %gs\n" \
" popw %gs\n" \
@@ -96,11 +84,12 @@ asm( \
" popw %es\n" \
" popw %ds\n" \
" popa\n" \
+ " add $0x4, %esp\n" \
" iret\n" \
);
#define EH_ENTRY_NO_CODE(ec) \
-extern "C" void exception_ ## ec ## _handler(); \
+extern "C" void exception_ ## ec ## _handler(RegisterDump&); \
extern "C" void exception_ ## ec ## _entry(); \
asm( \
".globl exception_" # ec "_entry\n" \
@@ -119,7 +108,7 @@ asm( \
" popw %es\n" \
" popw %fs\n" \
" popw %gs\n" \
- " mov %esp, exception_state_dump\n" \
+ " mov %esp, %eax\n" \
" call exception_" # ec "_handler\n" \
" popw %gs\n" \
" popw %gs\n" \
@@ -132,9 +121,8 @@ asm( \
// 6: Invalid Opcode
EH_ENTRY_NO_CODE(6);
-void exception_6_handler()
+void exception_6_handler(RegisterDump& regs)
{
- auto& regs = *reinterpret_cast<RegisterDump*>(exception_state_dump);
kprintf("%s invalid opcode: %u(%s)\n", current->isRing0() ? "Kernel" : "Process", current->pid(), current->name().characters());
word ss;
@@ -147,7 +135,6 @@ void exception_6_handler()
esp = regs.esp_if_crossRing;
}
- 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, esp, regs.esi, regs.edi);
@@ -163,10 +150,9 @@ void exception_6_handler()
// 13: General Protection Fault
EH_ENTRY(13);
-void exception_13_handler()
+void exception_13_handler(RegisterDumpWithExceptionCode& regs)
{
- auto& regs = *reinterpret_cast<RegisterDump*>(exception_state_dump);
- kprintf("%s crash: %u(%s)\n", current->isRing0() ? "Kernel" : "Process", current->pid(), current->name().characters());
+ kprintf("%s GPF: %u(%s)\n", current->isRing0() ? "Kernel" : "User", current->pid(), current->name().characters());
word ss;
dword esp;
@@ -178,7 +164,7 @@ void exception_13_handler()
esp = regs.esp_if_crossRing;
}
- kprintf("exception code: %w\n", exception_code);
+ kprintf("exception code: %w\n", regs.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, esp, regs.esi, regs.edi);
@@ -193,19 +179,18 @@ void exception_13_handler()
// 14: Page Fault
EH_ENTRY(14);
-void exception_14_handler()
+void exception_14_handler(RegisterDumpWithExceptionCode& regs)
{
ASSERT(current);
dword faultAddress;
asm ("movl %%cr2, %%eax":"=a"(faultAddress));
- auto& regs = *reinterpret_cast<RegisterDump*>(exception_state_dump);
- kprintf("Ring%u page fault in %s(%u), %s laddr=%p\n",
+ dbgprintf("Ring%u page fault in %s(%u), %s laddr=%p\n",
regs.cs & 3,
current->name().characters(),
current->pid(),
- exception_code & 2 ? "write" : "read",
+ regs.exception_code & 2 ? "write" : "read",
faultAddress);
word ss;
@@ -218,13 +203,15 @@ void exception_14_handler()
esp = regs.esp_if_crossRing;
}
- 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, esp, regs.esi, regs.edi);
+#ifdef PAGE_FAULT_DEBUG
+ dbgprintf("exception code: %w\n", regs.exception_code);
+ dbgprintf("pc=%w:%x ds=%w es=%w fs=%w gs=%w\n", regs.cs, regs.eip, regs.ds, regs.es, regs.fs, regs.gs);
+ dbgprintf("stk=%w:%x\n", ss, esp);
+ dbgprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx);
+ dbgprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, esp, regs.esi, regs.edi);
byte* codeptr = (byte*)regs.eip;
- kprintf("code: %b %b %b %b %b %b %b %b\n",
+ dbgprintf("code: %b %b %b %b %b %b %b %b\n",
codeptr[0],
codeptr[1],
codeptr[2],
@@ -234,17 +221,20 @@ void exception_14_handler()
codeptr[6],
codeptr[7]
);
+#endif
if (current->isRing0())
HANG;
- auto response = MM.handle_page_fault(PageFault(exception_code, LinearAddress(faultAddress)));
+ auto response = MM.handle_page_fault(PageFault(regs.exception_code, LinearAddress(faultAddress)));
if (response == PageFaultResponse::ShouldCrash) {
kprintf("Crashing after unresolved page fault\n");
Process::processDidCrash(current);
} else if (response == PageFaultResponse::Continue) {
- kprintf("Continuing after resolved page fault\n");
+#ifdef PAGE_FAULT_DEBUG
+ dbgprintf("Continuing after resolved page fault\n");
+#endif
} else {
ASSERT_NOT_REACHED();
}