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
_______________________________________________
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to