Date: Thu, 29 Dec 2016 01:59:12 +0200 From: Konstantin Belousov <kostikbel@gmail.com> To: Steve Kargl <sgk@troutmask.apl.washington.edu> Cc: freebsd-current@freebsd.org Subject: Re: unkillable firefox Message-ID: <20161228235912.GE1923@kib.kiev.ua> In-Reply-To: <20161228232439.GA1031@troutmask.apl.washington.edu> References: <20161220212920.GA69662@troutmask.apl.washington.edu> <20161228205453.GA96328@troutmask.apl.washington.edu> <20161228222836.GD1923@kib.kiev.ua> <20161228232439.GA1031@troutmask.apl.washington.edu>
next in thread | previous in thread | raw e-mail | index | archive | help
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
@@ -304,13 +304,48 @@ 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);
@@ -357,28 +392,25 @@ 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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20161228235912.GE1923>
