Re: unkillable firefox

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Thu, 29 Dec 2016 01:59:12 +0200
On Wed, Dec 28, 2016 at 03:24:39PM -0800, Steve Kargl wrote:
> Patch results in a panic when I start X server.
> 
> Fatal trap 12: page fault while in kernel mode
> cpuid = 7; apic id = 17
> fault virtual address   = 0x30
> fault code              = supervisor read data, page not present
> instruction pointer     = 0x20:0xffffffff807d3999
> stack pointer           = 0x0:0xfffffe0238c22720
> frame pointer           = 0x0:0xfffffe0238c22750
> 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         = 790 (fvwm)
> trap number             = 12
> panic: page fault
> cpuid = 7
> KDB: stack backtrace:
> db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0238c223b0
> vpanic() at vpanic+0x186/frame 0xfffffe0238c22430
> panic() at panic+0x43/frame 0xfffffe0238c22490
> trap_fatal() at trap_fatal+0x322/frame 0xfffffe0238c224e0
> trap_pfault() at trap_pfault+0x1bc/frame 0xfffffe0238c22540
> trap() at trap+0x253/frame 0xfffffe0238c22650
> calltrap() at calltrap+0x8/frame 0xfffffe0238c22650
> --- trap 0xc, rip = 0xffffffff807d3999, rsp = 0xfffffe0238c22720, rbp = 0xfffffe0238c22750 ---
> vm_fault_populate_cleanup() at vm_fault_populate_cleanup+0x39/frame 0xfffffe0238c22750
> vm_fault_hold() at vm_fault_hold+0x1a65/frame 0xfffffe0238c22880
> vm_fault() at vm_fault+0x78/frame 0xfffffe0238c228c0
> trap_pfault() at trap_pfault+0xf6/frame 0xfffffe0238c22920
> trap() at trap+0x2ed/frame 0xfffffe0238c22a30
> calltrap() at calltrap+0x8/frame 0xfffffe0238c22a30
> 
> (kgdb) bt
> #0  doadump (textdump=1) at pcpu.h:222
> #1  0xffffffff80590002 in kern_reboot (howto=<value optimized out>)
>     at /usr/src/sys/kern/kern_shutdown.c:386
> #2  0xffffffff805904c0 in vpanic (fmt=<value optimized out>, 
>     ap=<value optimized out>) at /usr/src/sys/kern/kern_shutdown.c:779
> #3  0xffffffff805902f3 in panic (fmt=<value optimized out>)
>     at /usr/src/sys/kern/kern_shutdown.c:710
> #4  0xffffffff808151d2 in trap_fatal (frame=0xfffffe0238c22660, eva=48)
>     at /usr/src/sys/amd64/amd64/trap.c:801
> #5  0xffffffff8081539c in trap_pfault (frame=0xfffffe0238c22660, usermode=0)
>     at /usr/src/sys/amd64/amd64/trap.c:658
> #6  0xffffffff80814ab3 in trap (frame=0xfffffe0238c22660)
>     at /usr/src/sys/amd64/amd64/trap.c:421
> #7  0xffffffff807fb023 in calltrap ()
>     at /usr/src/sys/amd64/amd64/exception.S:236
> #8  0xffffffff807d3999 in vm_fault_populate_cleanup (
>     object=<value optimized out>, first=<value optimized out>, 
>     last=<value optimized out>) at pcpu.h:222
> #9  0xffffffff807d2105 in vm_fault_hold (map=0xfffff8000999f000, 
>     vaddr=8597401600, fault_type=<value optimized out>, fault_flags=0, 
>     m_hold=0x0) at /usr/src/sys/vm/vm_fault.c:402
> #10 0xffffffff807d0658 in vm_fault (map=0xfffff8000999f000, 
>     vaddr=<value optimized out>, fault_type=1 '\001', 
>     fault_flags=<value optimized out>) at /usr/src/sys/vm/vm_fault.c:464
> #11 0xffffffff808152d6 in trap_pfault (frame=0xfffffe0238c22a40, usermode=1)
>     at /usr/src/sys/amd64/amd64/trap.c:708
> #12 0xffffffff80814b4d in trap (frame=0xfffffe0238c22a40)
>     at /usr/src/sys/amd64/amd64/trap.c:326
> #13 0xffffffff807fb023 in calltrap ()
>     at /usr/src/sys/amd64/amd64/exception.S:236
> #14 0x0000000200b25c33 in ?? ()
> 

You do not have INVARIANTS in the kernel config ?

Below is my guess about the issue in the patch.  Hopefully it fixes
your panic and still cure the bug I see in your previous report.

diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index e8fb5d00408..4d25e127e8d 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
_at__at_ -304,13 +304,48 _at__at_ vm_fault_restore_map_lock(struct faultstate *fs)
 	fs->lookup_still_valid = true;
 }
 
+static void
+vm_fault_populate_check_page(vm_page_t m, vm_object_t object, vm_pindex_t pidx)
+{
+
+	/*
+	 * Check each page to ensure that the driver is
+	 * obeying the interface: the page must be installed
+	 * in the object, fully valid, and exclusively busied.
+	 */
+	MPASS(m != NULL);
+	MPASS(vm_page_xbusied(m));
+	MPASS(m->valid == VM_PAGE_BITS_ALL);
+	MPASS(m->object == object);
+	MPASS(m->pindex == pidx);
+}
+
+static void
+vm_fault_populate_cleanup(vm_object_t object, vm_pindex_t first,
+    vm_pindex_t last)
+{
+	vm_page_t m;
+	vm_pindex_t pidx;
+
+	VM_OBJECT_ASSERT_WLOCKED(object);
+	if (first > last) /* micro-op: avoid page lookup */
+		return;
+	for (pidx = first, m = vm_page_lookup(object, pidx);
+	    pidx <= last; pidx++, m = vm_page_next(m)) {
+		vm_fault_populate_check_page(m, object, pidx);
+		vm_page_lock(m);
+		vm_page_activate(m);
+		vm_page_unlock(m);
+		vm_page_xunbusy(m);
+	}
+}
 
 static int
 vm_fault_populate(struct faultstate *fs, vm_offset_t vaddr, vm_prot_t prot,
     int fault_type, int fault_flags, boolean_t wired, vm_page_t *m_hold)
 {
 	vm_page_t m;
-	vm_pindex_t f_first, f_last, pidx;
+	vm_pindex_t f_first, f_last, f1_first, f1_last, pidx;
 	int rv;
 
 	MPASS(fs->object == fs->first_object);
_at__at_ -357,28 +392,25 _at__at_ vm_fault_populate(struct faultstate *fs, vm_offset_t vaddr, vm_prot_t prot,
 	MPASS(f_last < fs->first_object->size);
 
 	vm_fault_restore_map_lock(fs);
-	if (fs->map->timestamp != fs->map_generation)
+	if (fs->map->timestamp != fs->map_generation) {
+		vm_fault_populate_cleanup(fs->first_object, f_first, f_last);
 		return (KERN_RESOURCE_SHORTAGE); /* RetryFault */
+	}
 
 	/* Clip pager response to fit into the vm_map_entry. */
-	f_first = MAX(OFF_TO_IDX(fs->entry->offset), f_first);
-	f_last = MIN(OFF_TO_IDX(fs->entry->end - fs->entry->start +
+	f1_first = MAX(OFF_TO_IDX(fs->entry->offset), f_first);
+	if (f1_first > f_first)
+		vm_fault_populate_cleanup(fs->first_object, f_first, f1_first
+		    - 1);
+	f1_last = MIN(OFF_TO_IDX(fs->entry->end - fs->entry->start +
 	    fs->entry->offset), f_last);
+	if (f1_last < f_last)
+		vm_fault_populate_cleanup(fs->first_object, f1_last + 1,
+		    f_last);
 
-	pidx = f_first;
-	for (m = vm_page_lookup(fs->first_object, pidx); pidx <= f_last;
-	    pidx++, m = vm_page_next(m)) {
-		/*
-		 * Check each page to ensure that the driver is
-		 * obeying the interface: the page must be installed
-		 * in the object, fully valid, and exclusively busied.
-		 */
-		MPASS(m != NULL);
-		MPASS(vm_page_xbusied(m));
-		MPASS(m->valid == VM_PAGE_BITS_ALL);
-		MPASS(m->object == fs->first_object);
-		MPASS(m->pindex == pidx);
-
+	for (pidx = f1_first, m = vm_page_lookup(fs->first_object, pidx);
+	    pidx <= f1_last; pidx++, m = vm_page_next(m)) {
+		vm_fault_populate_check_page(m, fs->first_object, pidx);
 		vm_fault_dirty(fs->entry, m, prot, fault_type, fault_flags,
 		    true);
 		VM_OBJECT_WUNLOCK(fs->first_object);
Received on Wed Dec 28 2016 - 22:59:20 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:41:09 UTC