fix(mmu): heap demand paging never triggered in page fault handler - #103
Conversation
HEAP_END (0x30000000) was lower than HEAP_START (0xD0000000), so the condition fault_addr >= HEAP_START and fault_addr < HEAP_END could never be true: the demand-paging path was dead code and every heap page fault ended in a kernel panic. 0x30000000 is the intended heap *size* (0xD0000000 + 0x30000000 = top of the 32-bit address space), so the check becomes fault_addr >= HEAP_START. Also stop reusing the faulting access flags (write, user) as mapping flags: a first *read* on a heap page mapped it read-only, and the next write panicked with a protection violation. Heap pages are now always mapped writable and kernel-only. The now-unused user constant is removed to keep Zig compiling.
|
HEAP_START = 0xD0000000 but HEAP_END = 0x30000000, so the guard if (fault_addr >= HEAP_START and fault_addr < HEAP_END)is x >= 0xD0000000 and x < 0x30000000, impossible for any x. The lazy-mapping branch is dead code, so any not-present fault in the heap window falls straight through to the panic path: // once the heap can grow past the initially mapped pages
char *p = malloc(0x30000);
p[0] = 1; // first touch of a demand pageInstead of allocating a frame and mapping it, the handler prints [PANIC] PAGE FAULT DETECTED! ... Page not present (OOM) and halts the machine. Second bug on the same path: the page is mapped with the faulting access flags (write, user). A first read of a fresh heap page maps it read-only, and the following write faults again as a protection violation, another panic. The fix maps heap pages writable and kernel-only unconditionally and uses fault_addr >= HEAP_START (the heap runs up to the top of the 32-bit space). |
|
LGTM, Todo next : centralize HEAP_START |
HEAP_END (0x30000000) was lower than HEAP_START (0xD0000000), so the condition fault_addr >= HEAP_START and fault_addr < HEAP_END could never be true. The demand-paging path was dead code and every heap page fault ended in a kernel panic. 0x30000000 is the intended heap size (0xD0000000 + 0x30000000 = top of the 32-bit address space), so the check becomes fault_addr >= HEAP_START.
Also stop reusing the faulting access flags (write, user) as mapping flags. A first read on a heap page mapped it read-only, and the next write panicked with a protection violation. Heap pages are now always mapped writable and kernel-only. The now-unused user constant is removed to keep Zig compiling.