Make the map->header sentinel a part of the initial vm_map binary search tree. Change the order of search tree comparisons so that the end field is tested before the start field, so that the map->header sentinel will always be the leftmost member of the search tree. Change the method of handling search failure in splay so that the new tree root after failure always becomes the largest map entry less than the address sought; such an entry must exist because the sentinel is less than any address sought. Have splay handle tree insertions and deletions. Have splay work on maps, rather than map entries. Change the splay code to eliminate duplicated comparisons. Rename vm_map_entry_splay to vm_map_splay.
Details
Diff Detail
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
uhub4: 2 ports with 2 removable, self powered
uhub5: 2 ports with 2 removable, self powered
WARNING: / was not properly dismounted
Fatal trap 12: page fault while in kernel mode
cpuid = 3; apic id = 03
fault virtual address = 0xc
fault code = supervisor read, page not present
instruction pointer = 0x20:0xc0fbef60
stack pointer = 0x28:0xd49009a0
frame pointer = 0x28:0xd4900a00
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, def32 1, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = 1 (init)
[ thread pid 1 tid 100002 ]
Stopped at vm_map_splay+0x300: movl 0xc(%eax),%eax
db> bt
Tracing pid 1 tid 100002 td 0xd60f9a80
vm_map_splay(bfbfe000,d6102804,d4900a20,44f,d6102804,...) at vm_map_splay+0x300/frame 0xd4900a00
vm_map_entry_unlink(d6102804,d84931dc,c1942b00,c1942b10,c16a2f0f,...) at vm_map_entry_unlink+0x90/frame 0xd4900a30
vm_map_entry_delete(d6102804,d84931dc,bfbff000,c8f,0,...) at vm_map_entry_delete+0x2f/frame 0xd4900acc
vm_map_delete(d6102804,0,bfc00000,d4900b88,bfc00000,...) at vm_map_delete+0x291/frame 0xd4900b2c
vm_map_remove(d6102804,0,bfc00000,ffffffff,d6102804,...) at vm_map_remove+0xbf/frame 0xd4900b6c
vmspace_dofree(d6102804,1,c16a131b,ffffffff,0,0,5,d6102804) at vmspace_dofree+0x36/frame 0xd4900b88
vmspace_free(d6102804,0,0,3,fffffffe,...) at vmspace_free+0x90/frame 0xd4900bb4
post_execve(d60f9a80,fffffffe,d6102804,bfbfefe4,0,...) at post_execve+0xbb/frame 0xd4900bd8
sys_execve(d60f9a80,d4900c90,0,0,d4900c80,...) at sys_execve+0x80/frame 0xd4900c40
start_init(0,d4900ce8,c1644afc,407,0,...) at start_init+0x2ae/frame 0xd4900cac
fork_exit(c0c0a390,0,d4900ce8) at fork_exit+0x7e/frame 0xd4900cd4
fork_trampoline() at fork_trampoline+0x8/frame 0xd4900cd4
--- trap 0, eip = 0, esp = 0xd4900d20, ebp = 0 ---
db> dump
Cannot dump: no dump device specified.
db> show registers
cs 0x20
ds 0x28
es 0x28
fs 0x8
gs 0x3b
ss 0x28
eax 0
ecx 0xd4900a20
edx 0xd6102801
ebx 0xd6102804
esp 0xd49009a0
ebp 0xd4900a00
esi 0x44f
edi 0xd6102804
eip 0xc0fbef60 vm_map_splay+0x300
efl 0x10282
vm_map_splay+0x300: movl 0xc(%eax),%eax
db>
(kgdb) l *vm_map_splay+0x300
0xc0fbef60 is in vm_map_splay (../../../vm/vm_map.c:1008).
1003 root->left = NULL;
1004 *io = root;
1005 root = ltree;
1006 for (;;) {
1007 /* root is never NULL in here. */
1008 y = root->right;
1009 if (y == NULL)
1010 break;
1011 x = root;
1012 root = y->right;
(kgdb)Without this change, it is possible that vm_map_lookup_entry will return with *entry == &map->header, when the root is null or when a binary search is made for an address smaller than any in the tree. So there's no assertion to fail on that condition, and it would be incorrect to add one.
That will still be possible after this change, so that there's no cause to add an assertion.
Ok. I looked at the consumers, and either they explicitly check for the lookup address falling into the map range, or do found_entry->next if result is false.
I mean that with your previous and this changes, the header map entry looks more and more as the normal entry, which might make some futher code change erroneously fail to skip it. I want to have some protection and diagnostic for that error.
The previous change made the header map entry look less like a normal entry, since normal entries have start < end, and the header map entry did too, before the change, which is why extra checks were needed in handling it. By making it less normal, with end < start for that node only, it is now harder to mistake for a normal entry.
This change modifies tree-related fields, left and right, and adj_free/max_free, which are modified in tree manipulation. Outside tree-manipulation code here, left and right are not examined. Outside of this file, adj_free and max_free are not examined. So I don't see the big impact globally from this change. The only functions that can return &map->header after this change are the one's that could return it already.
I'm not sure how to apply the protection and diagnostic changes you seek, other than by putting back in all the &map->header tests I took out of loop bound checks in the previous change, because they were no longer necessary. I'd welcome an example of the sort of change you're looking for.
The patch hasn't changed since February, but some of the context around it has, so updating to deal with conflicts.
Thanks to Peter Holm for point out necessary changes to this patch on account of changes elsewhere. min_offset and max_offset fields have been renamed.
I have tested this patch with all of the stress2 tests. I also ran a buildworld / installworld. No problems seen.
Drop unneeded argument to vm_map_entry_link. Drop unnecessary calls to vm_map_entry_resize_free from vm_map_simplify_entry, by setting start/end fields before removing neighbor. Reduce number of uses of 'prev' member when iterating through consecutive map entries.
Can you extract the helpers functions into separate review ?
| sys/vm/vm_map.c | ||
|---|---|---|
| 1669 | Change the return type to bool ? | |
| 1675 | Almost all () there and below are excessive, and no need in space before the excessive '(' at this line. | |
| 1678 | No need in additional space for indent. | |
| 1692 | Blank line is needed before start of multi-line comment. | |
| 1706 | != NULL | |
startup_alloc from "UMA Zones", 12 boot pages left
startup_alloc from "UMA Zones", 8 boot pages left
startup_alloc from "UMA Zones", 4 boot pages left
kernel trap 12 with interrupts disabled
Kernel page fault with the following non-sleepable locks held:
exclusive sleep mutex vm map (system) (vm map (system)) r = 0 (0xfffff80100001098) locked @ vm/vm_kern.c:730
stack backtrace:
#0 0xffffffff80bf9563 at ??+0
#1 0xffffffff80bfa4af at ??+0
#2 0xffffffff81069063 at ??+0
#3 0xffffffff8106869a at ??+0
#4 0xffffffff81043185 at ??+0
#5 0xffffffff80ed2843 at ??+0
#6 0xffffffff80ed0aa2 at ??+0
#7 0xffffffff80ecf717 at ??+0
#8 0xffffffff80b27ba8 at ??+0
#9 0xffffffff8034502c at ??+0
Fatal trap 12: page fault while in kernel mode
cpuid = 0; apic id = 00
fault virtual address = 0x0
fault code = supervisor write data, page not present
instruction pointer = 0x20:0xffffffff80ed21c8
stack pointer = 0x28:0xffffffff8270e2d0
frame pointer = 0x28:0xffffffff8270e2f0
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags = resume, IOPL = 0
current process = 0 ()
[ thread pid 0 tid 0 ]
Stopped at vm_map_splay+0x1c8: movq %r11,(%r9)
db> bt
Tracing pid 0 tid 0 td 0xffffffff8208e100
vm_map_splay() at vm_map_splay+0x1c8/frame 0xffffffff8270e2f0
vm_map_insert() at vm_map_insert+0x453/frame 0xffffffff8270e390
kmem_init() at kmem_init+0x72/frame 0xffffffff8270e3c0
vm_mem_init() at vm_mem_init+0x47/frame 0xffffffff8270e3d0
mi_startup() at mi_startup+0x118/frame 0xffffffff8270e3f0
btext() at btext+0x2c
db> x/s version
version: FreeBSD 13.0-CURRENT #0 r339523M: Sun Oct 21 08:17:58 CEST 2018\012 pho@flix1a.netstart_init: trying /sbin/init
Expensive timeout(9) function: 0xffffffff80a01180(0xffffffff81af3bd0) 0.010507480 s
Fatal trap 9: general protection fault while in kernel mode
cpuid = 32; apic id = 26
instruction pointer = 0x20:0xffffffff80ed205d
stack pointer = 0x28:0xfffffe00edb16fc0
frame pointer = 0x28:0xfffffe00edb16fe0
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = 132 (ifconfig)
[ thread pid 132 tid 100753 ]
Stopped at vm_map_splay+0x5d: cmpq %r8,ll+0x7(%rcx)
db> bt
Tracing pid 132 tid 100753 td 0xfffff8010f80d580
vm_map_splay() at vm_map_splay+0x5d/frame 0xfffffe00edb16fe0
vm_map_simplify_entry() at vm_map_simplify_entry+0x1c1/frame 0xfffffe00edb17010
vm_map_unwire() at vm_map_unwire+0x4b3/frame 0xfffffe00edb170a0
userland_sysctl() at userland_sysctl+0x20b/frame 0xfffffe00edb17150
sys___sysctl() at sys___sysctl+0x5f/frame 0xfffffe00edb17200
amd64_syscall() at amd64_syscall+0x293/frame 0xfffffe00edb17330
fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe00edb17330
--- syscall (202, FreeBSD ELF64, sys___sysctl), rip = 0x80047bfda, rsp = 0x7fffffffe418, rbp = 0x7fffffffe450 ---
db> x/s version
version: FreeBSD 13.0-CURRENT #2 r339523M: Sun Oct 21 09:50:31 CEST 2018\012 pho@flix1a.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO\012
db>I ran 1/2 of the stress2 tests, for one day, with D13999.id50452.diff without seeing any problems.
Restore vm_map_entry_splay with its original arguments. Break its split and merge phases into separate functions, and use those functions, instead of vm_map_entry_splay, to implement link and unlink.
Well, ...
real memory = 103079215104 (98304 MB) panic: kmem_suballoc: bad status return of 3 cpuid = 0 time = 1 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xffffffff82712240 vpanic() at vpanic+0x1a3/frame 0xffffffff827122a0 panic() at panic+0x43/frame 0xffffffff82712300 kmem_suballoc() at kmem_suballoc+0xb5/frame 0xffffffff82712330 vm_ksubmap_init() at vm_ksubmap_init+0x21d/frame 0xffffffff82712370 cpu_startup() at cpu_startup+0x21c/frame 0xffffffff827123a0 mi_startup() at mi_startup+0x25f/frame 0xffffffff827123f0 btext() at btext+0x2c KDB: enter: panic [ thread pid 0 tid 0 ] Stopped at kdb_enter+0x3b: movq $0,kdb_why db> x/ verson kdb_enter+0x3b: 2504c748 (\360\367\20111000000000 db>
Fix a broken adj_free calculation in _link. Eliminate two gratuitous differences from the original.
If I do not see any other problems during tests, this one seems unrelated IMHO:
https://people.freebsd.org/~pho/stress/log/dougm016.txt
In vm_map_lookup_entry, add a KASSERT to usurp an exit case, so that I can either delete the exit case, or find the caller passing the bad argument that creates the need for the exit case and fix the caller.
[root@flix1a /usr/src/sys/amd64/compile/PHO]# cc -c -O0 -pipe -fno-strict-aliasing -g -nostdinc -I. -I../../.. -I../../../contrib/ck/include -I../../../contrib/libfdt -D_KERNEL -DHAVE_KERNEL_OPTION_HEADERS -include opt_global.h -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -MD -MF.depend.vm_map.o -MTvm_map.o -mcmodel=kernel -mno-red-zone -mno-mmx -mno-sse -msoft-float -fno-asynchronous-unwind-tables -ffreestanding -fwrapv -fstack-protector -gdwarf-2 -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wcast-qual -Wundef -Wno-pointer-sign -D__printf__=__freebsd_kprintf__ -Wmissing-include-dirs -fdiagnostics-show-option -Wno-unknown-pragmas -Wno-error-tautological-compare -Wno-error-empty-body -Wno-error-parentheses-equality -Wno-error-unused-function -Wno-error-pointer-sign -Wno-error-shift-negative-value -Wno-address-of-packed-member -mno-aes -mno-avx -std=iso9899:1999 -Werror ../../../vm/vm_map.c
../../../vm/vm_map.c:1154:26: error: ordered comparison between pointer and integer ('vm_offset_t' (aka 'unsigned long') and 'void *') [-Werror]
KASSERT(vm_map_min(map) <= && address < vm_map_max(map),
~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~
../../../sys/systm.h:102:24: note: expanded from macro 'KASSERT'
if (__predict_false(!(exp))) \
^~~
../../../sys/cdefs.h:455:51: note: expanded from macro '__predict_false'
#define __predict_false(exp) __builtin_expect((exp), 0)
^~~
../../../vm/vm_map.c:1155:65: error: invalid conversion specifier ')' [-Werror,-Wformat-invalid-specifier]
("vm_map_lookup_entry: query address %p out of range [%p, %)",
~^
../../../sys/systm.h:103:17: note: expanded from macro 'KASSERT'
kassert_panic msg; \
^
../../../vm/vm_map.c:1156:48: error: data argument not used by format string [-Werror,-Wformat-extra-args]
(void *)address, (void*)vm_map_min(map), (void*)vm_map_max(map)));
^
../../../sys/systm.h:103:17: note: expanded from macro 'KASSERT'
kassert_panic msg; \
^~~
../../../vm/vm_map.c:1154:32: error: use of undeclared label 'address'
KASSERT(vm_map_min(map) <= && address < vm_map_max(map),
^
4 errors generated.
[root@flix1a /usr/src/sys/amd64/compile/PHO]#
$I booted with it anyway and got this one:
20181130 15:06:49 all (18/590): pmc3.sh hwpmc: SOFT/16/64/0x67<INT,USR,SYS,REA,WRI> TSC/1/64/0x20<REA> IAP/4/48/0x3ff<INT,USR,SYS,EDG,THR,REA,WRI,INV,QUA,PRC> IAF/3/48/0x67<INT,USR,SYS,REA,WRI> panic: vm_map_lookup_entry: query address 0 out of range [0x1000, 0x800000000000] cpuid = 47 time = 1543586811 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0131340b10 vpanic() at vpanic+0x1a3/frame 0xfffffe0131340b70 panic() at panic+0x43/frame 0xfffffe0131340bd0 vm_map_lookup_entry() at vm_map_lookup_entry+0xa5/frame 0xfffffe0131340c40 vm_map_lookup() at vm_map_lookup+0x6b/frame 0xfffffe0131340cf0 vm_fault_hold() at vm_fault_hold+0x7d/frame 0xfffffe0131340e40 vm_fault() at vm_fault+0x60/frame 0xfffffe0131340e80 trap_pfault() at trap_pfault+0x188/frame 0xfffffe0131340ed0 trap() at trap+0x2ba/frame 0xfffffe0131340fe0 calltrap() at calltrap+0x8/frame 0xfffffe0131340fe0 --- trap 0xc, rip = 0xffffffff8107b155, rsp = 0xfffffe01313410b0, rbp = 0xfffffe01313410b0 --- copyin_smap_erms() at copyin_smap_erms+0xa5/frame 0xfffffe01313410b0 pmc_syscall_handler() at pmc_syscall_handler+0xdd1/frame 0xfffffe01313411f0 amd64_syscall() at amd64_syscall+0x293/frame 0xfffffe0131341330 fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe0131341330 --- syscall (0, FreeBSD ELF64, nosys), rip = 0x800440eba, rsp = 0x7fffdf3f7f48, rbp = 0x7fffdf3f7fb0 ---
panic: vm_map_lookup_entry: query address 0 out of range [0x1000, 0x800000000000), vmcore.83 https://people.freebsd.org/~pho/stress/log/dougm017.txt
../../../vm/vm_fault.c:575:39: error: use of undeclared identifier 'addr'; did you mean 'vaddr'?
result = (vaddr < vm_map_min(map) || addr >= vm_map_max(map)) ?
^~~~
vaddr
../../../vm/vm_fault.c:546:41: note: 'vaddr' declared herepanic: vm_map_lookup_entry: query address 0x800000000000 out of range [0x1000, 0x800000000000) https://people.freebsd.org/~pho/stress/log/dougm018.txt
with a mmap() syscall fuzz test.
In vm_map_wire, use VM_MAP_RANGE_CHECK before testing start and end for equality, since it might make them equal and let the function exit before a possible lookup for address vm_map_max, which is outside the valid range.
panic: vm_map_lookup_entry: query address 0x800000000000 out of range [0x1000, 0x800000000000) https://people.freebsd.org/~pho/stress/log/dougm019.txt
Abandon attempts to make callers of vm_map_lookup_entry adhere to range limits on their address inquires, and just go back to having vm_map_lookup_entry check for out-of-bounds address.
Change the tree code to use the header sentinel value as two entries in the tree, both as a least and greatest tree element, by examining the start value of a node before the end value if and only if the node is a right child of its parent.
With D13999.id51793.diff I see:
panic: page fault cpuid = 6 time = 1544449196 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00bbff8ff0 vpanic() at vpanic+0x1a3/frame 0xfffffe00bbff9050 panic() at panic+0x43/frame 0xfffffe00bbff90b0 trap_fatal() at trap_fatal+0x35f/frame 0xfffffe00bbff9100 trap_pfault() at trap_pfault+0x62/frame 0xfffffe00bbff9150 trap() at trap+0x2ba/frame 0xfffffe00bbff9260 calltrap() at calltrap+0x8/frame 0xfffffe00bbff9260 --- trap 0xc, rip = 0xffffffff80eec33b, rsp = 0xfffffe00bbff9338, rbp = 0xfffffe00bbff9340 --- vm_map_entry_splay_split() at vm_map_entry_splay_split+0xb/frame 0xfffffe00bbff9340 vm_map_entry_unlink() at vm_map_entry_unlink+0xa9/frame 0xfffffe00bbff9390 vm_map_entry_delete() at vm_map_entry_delete+0x1c/frame 0xfffffe00bbff93e0 vm_map_delete() at vm_map_delete+0x32c/frame 0xfffffe00bbff9450 vm_map_remove() at vm_map_remove+0x81/frame 0xfffffe00bbff9480 exec_new_vmspace() at exec_new_vmspace+0x183/frame 0xfffffe00bbff94e0 exec_elf64_imgact() at exec_elf64_imgact+0x6bb/frame 0xfffffe00bbff95b0 kern_execve() at kern_execve+0x67a/frame 0xfffffe00bbff98f0 sys_execve() at sys_execve+0x4c/frame 0xfffffe00bbff9970 amd64_syscall() at amd64_syscall+0x293/frame 0xfffffe00bbff9ab0 fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe00bbff9ab0 --- syscall (59, FreeBSD ELF64, sys_execve), rip = 0x2ad00a, rsp = 0x7fffffffe6e8, rbp = 0x7fffffffe6f0 --- KDB: enter: panic [ thread pid 46 tid 100221 ] Stopped at kdb_enter+0x3b: movq $0,kdb_why db> x/s version version: FreeBSD 13.0-CURRENT #0 r341786M: Mon Dec 10 14:37:19 CET 2018\012 pho@t2.osted.lan:/usr/src/sys/amd64/compile/PHO\012 db>
Fatal trap 12: page fault while in kernel mode
cpuid = 1; apic id = 01
fault virtual address = 0x0
fault code = supervisor write data, page not present
instruction pointer = 0x20:0xffffffff80ee85d3
stack pointer = 0x28:0xfffffe00bbff92d0
frame pointer = 0x28:0xfffffe00bbff9340
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = 46 (init)
trap number = 12
panic: page fault
cpuid = 1
time = 1544461569
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00bbff8f90
vpanic() at vpanic+0x1a3/frame 0xfffffe00bbff8ff0
panic() at panic+0x43/frame 0xfffffe00bbff9050
trap_fatal() at trap_fatal+0x35f/frame 0xfffffe00bbff90a0
trap_pfault() at trap_pfault+0x62/frame 0xfffffe00bbff90f0
trap() at trap+0x2ba/frame 0xfffffe00bbff9200
calltrap() at calltrap+0x8/frame 0xfffffe00bbff9200
--- trap 0xc, rip = 0xffffffff80ee85d3, rsp = 0xfffffe00bbff92d0, rbp = 0xfffffe00bbff9340 ---
vm_map_entry_unlink() at vm_map_entry_unlink+0x143/frame 0xfffffe00bbff9340
vm_map_entry_delete() at vm_map_entry_delete+0x1d/frame 0xfffffe00bbff93b0
vm_map_delete() at vm_map_delete+0x28a/frame 0xfffffe00bbff9440
vm_map_remove() at vm_map_remove+0xa6/frame 0xfffffe00bbff9480
exec_new_vmspace() at exec_new_vmspace+0x183/frame 0xfffffe00bbff94e0
exec_elf64_imgact() at exec_elf64_imgact+0x6bb/frame 0xfffffe00bbff95b0
kern_execve() at kern_execve+0x67a/frame 0xfffffe00bbff98f0
sys_execve() at sys_execve+0x4c/frame 0xfffffe00bbff9970
amd64_syscall() at amd64_syscall+0x293/frame 0xfffffe00bbff9ab0
fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe00bbff9ab0
--- syscall (59, FreeBSD ELF64, sys_execve), rip = 0x2ad00a, rsp = 0x7fffffffe6e8, rbp = 0x7fffffffe6f0 ---
KDB: enter: panic
[ thread pid 46 tid 100221 ]
Stopped at kdb_enter+0x3b: movq $0,kdb_why
db> x/s version
version: FreeBSD 13.0-CURRENT #2 r341786M: Mon Dec 10 18:03:16 CET 2018\012 pho@t2.osted.lan:/usr/src/sys/amd64/compile/PHO\012
db>
(kgdb) l *0xffffffff80ee85d3
0xffffffff80ee85d3 is in vm_map_entry_unlink (../../../vm/vm_map.c:1073).
1068 &llist, &rlist);
1069 if (root->right != NULL)
1070 vm_map_entry_splay_split(entry->start, root->right,
1071 &llist, &rlist);
1072 llist->next = rlist;
1073 rlist->prev = llist;
1074 llist->adj_free = rlist->start - llist->end;
1075 /* Make the predecessor of the entry the new root */
1076 root = vm_map_entry_splay_merge(llist, llist->right, rlist, NULL, NULL);
1077 map->root = root;
(kgdb)Fatal trap 12: page fault while in kernel mode
cpuid = 11; apic id = 0b
fault virtual address = 0x18
fault code = supervisor read data, page not present
instruction pointer = 0x20:0xffffffff80ee5fb3
stack pointer = 0x28:0xfffffe00bbff97e0
frame pointer = 0x28:0xfffffe00bbff9810
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = 46 (sh)
trap number = 12
panic: page fault
cpuid = 11
time = 1544513729
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00bbff94a0
vpanic() at vpanic+0x1a3/frame 0xfffffe00bbff9500
panic() at panic+0x43/frame 0xfffffe00bbff9560
trap_fatal() at trap_fatal+0x35f/frame 0xfffffe00bbff95b0
trap_pfault() at trap_pfault+0x62/frame 0xfffffe00bbff9600
trap() at trap+0x2ba/frame 0xfffffe00bbff9710
calltrap() at calltrap+0x8/frame 0xfffffe00bbff9710
--- trap 0xc, rip = 0xffffffff80ee5fb3, rsp = 0xfffffe00bbff97e0, rbp = 0xfffffe00bbff9810 ---
vm_map_entry_splay() at vm_map_entry_splay+0x63/frame 0xfffffe00bbff9810
vm_map_lookup_entry() at vm_map_lookup_entry+0x112/frame 0xfffffe00bbff9870
vm_map_delete() at vm_map_delete+0x5f/frame 0xfffffe00bbff9900
kern_munmap() at kern_munmap+0x8a/frame 0xfffffe00bbff9970
amd64_syscall() at amd64_syscall+0x293/frame 0xfffffe00bbff9ab0
fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe00bbff9ab0
--- syscall (73, FreeBSD ELF64, sys_munmap), rip = 0x80024174a, rsp = 0x7fffffffd268, rbp = 0x7fffffffd3c0 ---
KDB: enter: panic
[ thread pid 46 tid 100221 ]
Stopped at kdb_enter+0x3b: movq $0,kdb_why
db> x/s version
version: FreeBSD 13.0-CURRENT #4 r341786M: Tue Dec 11 08:32:27 CET 2018\012 pho@t2.osted.lan:/usr/src/sys/amd64/compile/PHO\012
db> dump
Cannot dump: no dump device specified.
db> show reg
cs 0x20
ds 0x3b ll+0x1a
es 0x3b ll+0x1a
fs 0x13
gs 0x1b
ss 0x28 ll+0x7
rax 0x12
rcx 0x80 ll+0x5f
rdx 0xfffffe00bbff9390
rbx 0xffffffff813150b9
rsp 0xfffffe00bbff9490
rbp 0xfffffe00bbff94a0
rsi 0x80 ll+0x5f
rdi 0xffffffff81e95358 cnputs_mtx
r8 0
r9 0
r10 0xffffffff81342cd5
r11 0x1
r12 0x1
r13 0xfffffe00bbff9720
r14 0xfffffe00bbff9540
r15 0xfffff80089b63580
rip 0xffffffff80bf252b kdb_enter+0x3b
rflags 0x82 ll+0x61
kdb_enter+0x3b: movq $0,kdb_why
db>
(kgdb) l *0xffffffff80ee5fb3
0xffffffff80ee5fb3 is in vm_map_entry_splay (../../../vm/vm_map.c:1018).
1013 * subtree and make it the root. There is such a
1014 * node, since map->header is in the tree and left of
1015 * all addresses.
1016 */
1017 root = llist;
1018 llist = root->right;
1019 root->right = NULL;
1020 }
1021 return (vm_map_entry_splay_merge(root, llist, rlist,
1022 root->left, root->right));
(kgdb)Just change unlink from the last working version by walking the left and right spines of the found node, without relying on splay_split to do it, and find the new root after that.
Fatal trap 12: page fault while in kernel mode
cpuid = 5; apic id = 05
fault virtual address = 0x18
fault code = supervisor read data, page not present
instruction pointer = 0x20:0xffffffff80ee5fa3
stack pointer = 0x28:0xfffffe00bbff97e0
frame pointer = 0x28:0xfffffe00bbff9810
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = 46 (sh)
trap number = 12
panic: page fault
cpuid = 5
time = 1544527104
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00bbff94a0
vpanic() at vpanic+0x1a3/frame 0xfffffe00bbff9500
panic() at panic+0x43/frame 0xfffffe00bbff9560
trap_fatal() at trap_fatal+0x35f/frame 0xfffffe00bbff95b0
trap_pfault() at trap_pfault+0x62/frame 0xfffffe00bbff9600
trap() at trap+0x2ba/frame 0xfffffe00bbff9710
calltrap() at calltrap+0x8/frame 0xfffffe00bbff9710
--- trap 0xc, rip = 0xffffffff80ee5fa3, rsp = 0xfffffe00bbff97e0, rbp = 0xfffffe00bbff9810 ---
vm_map_entry_splay() at vm_map_entry_splay+0x53/frame 0xfffffe00bbff9810
vm_map_lookup_entry() at vm_map_lookup_entry+0x112/frame 0xfffffe00bbff9870
vm_map_delete() at vm_map_delete+0x5f/frame 0xfffffe00bbff9900
kern_munmap() at kern_munmap+0x8a/frame 0xfffffe00bbff9970
amd64_syscall() at amd64_syscall+0x293/frame 0xfffffe00bbff9ab0
fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe00bbff9ab0
--- syscall (73, FreeBSD ELF64, sys_munmap), rip = 0x80024174a, rsp = 0x7fffffffd268, rbp = 0x7fffffffd3c0 ---
KDB: enter: panic
[ thread pid 46 tid 100221 ]
Stopped at kdb_enter+0x3b: movq $0,kdb_why
db> x/s version
version: FreeBSD 13.0-CURRENT #6 r341786M: Tue Dec 11 12:15:24 CET 2018\012 pho@t2.osted.lan:/usr/src/sys/amd64/compile/PHO\012
db>
(kgdb) l *0xffffffff80ee5fa3
0xffffffff80ee5fa3 is in vm_map_entry_splay (../../../vm/vm_map.c:1017).
1012 * subtree and make it the root. There is such a
1013 * node, since map->header is in the tree and left of
1014 * all addresses.
1015 */
1016 root = llist;
1017 llist = root->right;
1018 root->right = NULL;
1019 }
1020 return (vm_map_entry_splay_merge(root, llist, rlist,
1021 root->left, root->right));
(kgdb)Just change the processing of the left spine a wee bit from what worked before, and see if that breaks.
Dare to change unlink again to walk the right spine also, and try to put the pieces together again afterward.
The essential parts of this have been checked in with D17794, so I'm discarding this.