Date: Mon, 28 Jan 2008 16:25:37 -0500 From: John Baldwin <jhb@freebsd.org> To: Pete French <petefrench@ticketswitch.com> Cc: freebsd-stable@freebsd.org Subject: Re: panic: vm_fault: fault on nofualt entry, addr: 81423000 Message-ID: <200801281625.37804.jhb@freebsd.org> In-Reply-To: <E1JJYKf-0000Uy-DA@dilbert.ticketswitch.com> References: <E1JJYKf-0000Uy-DA@dilbert.ticketswitch.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Monday 28 January 2008 01:03:45 pm Pete French wrote: > o.k., done some investigative work, and I think i have actually tracke > dodnw what is going wrong, though i do not know how to fix it. mapping > the header calls madt_map_table, which in turn calls madt_map > to do the actual mapping: > > madt_map called with pa 0x7fec7f40, offset 1, length 60 > 'off' becomes 3904, and the rounded length 4096 > pmap_kenter_temporary called with pa 0x7fec7000, offset 1 > gives va of 0x8142300 > returns 0x81423f40 > > thus the header is ending up in page 0x8142300 if I read that correctly. this > is importnat for later on. meanwhile, back at the table scanning code... > > rsdt mapped at 0x81423f40 > table offset at 0x81423f64 > count is 6 > table offset address and their contents > 0 0x81423f64 0x7fec7fe8 > 1 0x81423f68 0x7fec805c > 2 0x81423f6c 0x7fec80c4 > 3 0x81423f70 0x7fec8127 > 4 0x81423f74 0x7fec8163 > 5 0x81423f78 0x7fec8195 > > so, it probes the first table, held at 0x7fec7fe8 as indicated by > the address in 0x81423f64. this calls madt_map to map the table > > madt_map called with pa 0x7fec7fe8, offset 0, length 36 > 'off' becomes 4072, and the rounded length 8192 > pmap_kenter_temporary called with pa 0x7fec7000, offset 0 > pmap_kenter called with va 0x8142300, pa 0x7fec8000 > gives va of 0x8142200 > returns 0x81422fe8 > > code is looking for a signature of 'APIC', but this table has 'FACP', so > a call is made to madt_unmap before returning > > madt_unmap called with data 0x81422fe8, length 36 > 'off' becomes 4072, and the rounded length 8192 > pmap_kremove called with 0x81422000 > pmap_kremove called with 0x81423000 > > the function then returns 0, and the loop goes round again to look > at table entry 1. the address of the table is stored at 0x81423f68 > as you can see from the list above, and it is when it tries to access > that address that it panics. > > now preseumably the panic is correct - 0x81423f68 is in page 0x81423000, > and didn't we just unmap that ? now I dont really understand this fully, > but why is page 0x81423000 being touched at all ? shouldnt the mapped > pages be 0x81421000 and 0x81422000 instead so they don't clash with > the already mapped 0x81423000 ? The unmap function is quite correctly doing > the reverse of the map function, but maybe theres something simply going > wrong in the algorithm working out which pages to map ? I think the problem is that the header for the FACP table crossed a page boundary so we had to map 2 pages to map the header, but the code assumes only 1 page is needed so when the second page was mapped, it overlapped with the page holding the XSDT. Here's a fix: Index: madt.c =================================================================== RCS file: /usr/cvs/src/sys/i386/acpica/madt.c,v retrieving revision 1.28 diff -u -r1.28 madt.c --- madt.c 11 Sep 2007 22:54:09 -0000 1.28 +++ madt.c 28 Jan 2008 21:25:03 -0000 @@ -109,9 +109,11 @@ /* * Code to abuse the crashdump map to map in the tables for the early * probe. We cheat and make the following assumptions about how we - * use this KVA: page 0 is used to map in the first page of each table - * found via the RSDT or XSDT and pages 1 to n are used to map in the - * RSDT or XSDT. The offset is in pages; the length is in bytes. + * use this KVA: pages 0 and 1 are used to map in the header of each + * table found via the RSDT or XSDT and pages 2 to n are used to map + * in the RSDT or XSDT. We have to use 2 pages for the table headers + * in case a header spans a page boundary. The offset is in pages; + * the length is in bytes. */ static void * madt_map(vm_paddr_t pa, int offset, vm_offset_t length) @@ -232,7 +234,7 @@ printf("MADT: RSDP failed extended checksum\n"); return (ENXIO); } - xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, + xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT); if (xsdt == NULL) { if (bootverbose) @@ -246,7 +248,7 @@ break; madt_unmap_table(xsdt); } else { - rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, + rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 2, ACPI_SIG_RSDT); if (rsdt == NULL) { if (bootverbose) -- John Baldwin
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801281625.37804.jhb>