Opened 5 weeks ago
Closed 5 weeks ago
#19367 closed bug (fixed)
PANIC: remove page X from cache Y: page still has mappings!
Reported by: | waddlesplash | Owned by: | nobody |
---|---|---|---|
Priority: | normal | Milestone: | R1/beta6 |
Component: | System/Kernel | Version: | R1/beta5 |
Keywords: | Cc: | ||
Blocked By: | Blocking: | ||
Platform: | All |
Description
First reported in the replies to #19360, and there's some analysis already there. This is reproducible on current hrevs, using the test scripts found there and ramfs.
Change History (8)
comment:1 by , 5 weeks ago
comment:2 by , 5 weeks ago
Is it possible to know what is the page and where it has mappings (team, area name etc.)?
comment:3 by , 5 weeks ago
That's already printed in the KDL information, see my analysis on the other ticket, I didn't bother copying it here.
comment:4 by , 5 weeks ago
Here's another instance of it: there are 3 running threads at the time of the panic. 118824 is the one that's KDLed, 118827 is in a spin() in delete_area, and 118828 is doing a LookupPage on page fault. But there's a lot of others of course, here's the excerpted list:
thread id state wait for object cpu pri stack team name 0xffffffff903c01c0 118770 waiting mutex 0xfffffff01681d678 - 10 0xffffffff8276b000118770 perl 0xfffffff0167d1dc0 118775 waiting cvar:team 0xffffffff8ff4c938 - 10 0xffffffff82351000118770 pthread func 0xfffffff01696ec40 118777 waiting mutex 0xfffffff0164c2e40 - 10 0xffffffff82775000118770 pthread func 0xfffffff016965500 118781 waiting cvar:team 0xffffffff8ff4c938 - 10 0xffffffff82789000118770 pthread func 0xfffffff0169662c0 118786 waiting cvar:team 0xffffffff8ff4c938 - 10 0xffffffff827a2000118770 pthread func 0xfffffff0167d9980 118793 waiting cvar:team 0xffffffff8ff4c938 - 10 0xffffffff8277f000118770 pthread func 0xfffffff01696a780 118809 waiting cvar:team 0xffffffff8ff45b38 - 10 0xffffffff827bb000118809 sh 0xffffffff903cc240 118812 waiting cvar:team 0xffffffff8ff4c938 - 10 0xffffffff827c5000118770 pthread func 0xfffffff0167dd080 118815 waiting signal - 10 0xffffffff827ca000118815 timeout 0xffffffff90671d80 118816 waiting cvar:team 0xffffffff8ff4bf38 - 10 0xffffffff827a7000118816 sh 0xffffffff903b0f40 118817 waiting cvar:team 0xffffffff8ff40b38 - 10 0xffffffff827cf000118817 sh 0xffffffff9067de00 118819 waiting mutex 0xffffffff81b3d8a0 - 10 0xffffffff827ac000118819 sh 0xffffffff90672b40 118820 ready - - 10 0xffffffff827b1000118820 timeout 0xffffffff90139840 118822 waiting cvar:team 0xffffffff8ff4c938 - 10 0xffffffff827de000118770 pthread func 0xffffffff9067b4c0 118823 waiting mutex 0xffffffff81b3d8a0 - 10 0xffffffff827e3000118823 filtertest 0xffffffff903c9900 118824 running - 1 10 0xffffffff827ed000118824 pthread func 0xfffffff0167d54c0 118825 waiting mutex 0xffffffff81b3d8a0 - 10 0xffffffff827e8000118825 timeout 0xffffffff90679940 118826 waiting cvar:team 0xffffffff8ff4c938 - 10 0xffffffff827f2000118770 pthread func 0xfffffff016961040 118827 running - 3 10 0xffffffff827f7000118827 pthread func 0xfffffff0167dc2c0 118828 running - 0 10 0xffffffff8278e000118828 pthread func
KDL information:
PANIC: remove page 0xffffffff88a0ac30 from cache 0xfffffff01686b428: page still has mappings!
PAGE: 0xffffffff88a0ac30 queue_next,prev: 0xffffffff85501520, 0xffffffff83eaa150 physical_number: 0x120327 cache: 0xfffffff01686b428 cache_offset: 10288 cache_next: 0x0000000000000000 state: active wired_count: 0 usage_count: 0 busy: 0 busy_writing: 0 accessed: 0 modified: 0 accessor: -1 area mappings: 0xffffffff904e79a0 (10242765)
CACHE 0xfffffff01686b428: ref_count: 0 source: 0x0000000000000000 type: RAM virtual_base: 0x0 virtual_end: 0x2430000 temporary: 1 lock: 0xfffffff01686b4b8 lock.holder: 118824 areas: consumers: pages: 1 in cache
AREA: 0xffffffff904e79a0 name: 'heap' owner: 0x1cff2 id: 0x9c4acd base: 0x120079da3000 size: 0x2930000 protection: 0x33 page_protection:0x0000000000000000 wiring: 0x0 memory_type: 0x0 cache: 0xfffffff01681d5e8 cache_type: RAM cache_offset: 0x0 cache_next: 0x0000000000000000 cache_prev: 0x0000000000000000 page mappings: 10454
kdebug> cache_tree ... 0xfffffff016827800 0xfffffff0164dac40 0xfffffff0164c2db0 0xfffffff01686dd90 0xfffffff01681d5e8 <-- kdebug> cache ... CACHE 0xfffffff016827800: ref_count: 3 source: 0x0000000000000000 type: RAM virtual_base: 0x0 virtual_end: 0x27f0000 temporary: 1 lock: 0xfffffff016827890 lock.holder: 118828 areas: consumers: 0xfffffff0164dac40 0xfffffff0164c2db0 pages: 10132 in cache
comment:5 by , 5 weeks ago
OK, I think I see something in this: the page's cache_offset is 10288, aka. 0x2830000. That's actually beyond its cache's virtual_end of 0x2430000, but more to the point it's also beyond the presumptive child cache's virtual end of 0x27f0000, and so when merging the caches, we would have completely ignored this page deliberately. That probably explains how it got "left behind".
If the CoW'ed areas are never shrunk after a first fork occurs, then there's a question of how the cache wound up with a that's beyond its end at all. I have swap disabled on this VM, I am pretty sure, so this isn't swap-related.
comment:6 by , 5 weeks ago
This looks like it (system booted to desktop with this assert, and only KDLed when I started the test):
PANIC: ASSERT FAILED (../src/system/kernel/vm/VMCache.cpp:806): offset <= virtual_end Welcome to Kernel Debugging Land... Thread 250 "perl" running on CPU 3 stack trace for thread 250 "perl" kernel stack: 0xffffffff8276e000 to 0xffffffff82773000 user stack: 0x00007f6ae350f000 to 0x00007f6ae450f000 frame caller <image>:function + offset 0 ffffffff827726f0 (+ 32) ffffffff80156fe0 <kernel_x86_64> arch_debug_call_with_fault_handler + 0x1a 1 ffffffff82772740 (+ 80) ffffffff800b8af8 <kernel_x86_64> debug_call_with_fault_handler + 0x78 2 ffffffff827727a0 (+ 96) ffffffff800ba1e4 <kernel_x86_64> kernel_debugger_loop(char const*, char const*, __va_list_tag*, int) + 0xf4 3 ffffffff827727f0 (+ 80) ffffffff800ba57e <kernel_x86_64> kernel_debugger_internal(char const*, char const*, __va_list_tag*, int) + 0x6e 4 ffffffff827728e0 (+ 240) ffffffff800ba917 <kernel_x86_64> panic + 0xb7 5 ffffffff82772920 (+ 64) ffffffff8014e6e1 <kernel_x86_64> VMCache::InsertPage(vm_page*, long) + 0x391 6 ffffffff82772a80 (+ 352) ffffffff8012f799 <kernel_x86_64> vm_soft_fault(VMAddressSpace*, unsigned long, bool, bool, bool, vm_page**) + 0x519 7 ffffffff82772b70 (+ 240) ffffffff8013d061 <kernel_x86_64> vm_page_fault + 0x161 8 ffffffff82772bb0 (+ 64) ffffffff8016311e <kernel_x86_64> x86_page_fault_exception + 0x15e 9 ffffffff82772f38 (+ 904) ffffffff801589cd <kernel_x86_64> int_bottom_user + 0xd8 user iframe at 0xffffffff82772f38 (end = 0xffffffff82773000) rax 0x106999cc8710 rbx 0x106999c262c0 rcx 0x1678 rdx 0x223b8 rsi 0x106999c47000 rdi 0x106999ce9450 rbp 0x7f6ae450d620 r8 0x1069986b1270 r9 0x35 r10 0x35 r11 0x0 r12 0x106999c262c0 r13 0x106999cc8710 r14 0x10699980a680 r15 0x4000 rip 0x107d1bd2a46 rsp 0x7f6ae450d5f0 rflags 0x10212 vector: 0xe, error code: 0x4 10 00007f6ae450d620 (+ 0) 00000107d1bd2a46 </boot/system/lib/libroot.so> memcpy + 0x26 11 00007f6ae450d650 (+ 48) 00000107d1bdd1d2 </boot/system/lib/libroot.so> realloc + 0xa2 ...
comment:7 by , 5 weeks ago
Seems this is coming from the "Read-only pages come in the deepest cache" logic in fault_get_page. That seems suspect to me. I've checked and that logic has actually been there in one form or another since the very beginning of the main repository history, and more than that goes back to NewOS itself (see here for where it was introduced).
I haven't had a lot of success debugging this so far. It's very intermittent, all my attempts at adding sleeps/spins don't seem to make it much more likely (in fact basically all seem to make it less likely, though it's hard to tell), and it's very optimization-sensitive (I've never gotten it to happen with -O0 yet, with -Og it does after a while, and with -O2 it's more reliable.) But even in the best case it takes multiple minutes or more to reproduce here, on average.
To make matters worse, GDB (and/or VMware's GDB stub) doesn't work correctly on binaries compiled even with -Og. Inspection of "heap" variables works, but any stack variables outside the current frame give bogus values (or worse, misleading ones.) So that does not help either.