page fault panic in device_get_softc/acpi_pcib_route_interrupt

Pawel Worach pawel.worach at telia.com
Thu Jan 6 11:57:03 PST 2005


John Baldwin wrote:
> On Wednesday 05 January 2005 06:02 pm, Nate Lawson wrote:
> 
>>John Baldwin wrote:
>>
>>>On Sunday 02 January 2005 07:35 pm, Nate Lawson wrote:
>>>
>>>>We already associate handles and devices in
>>>>sys/dev/acpica/acpi.c:acpi_probe_child() before probing anything.  See
>>>>the AcpiAttachData() step.  I don't think that's the problem.
>>>
>>>I do because he passes a null device_t pointer in as an argument to a
>>>function.  The calling code is:
>>>
>>>    /*
>>>     * We have to find the source device (PCI interrupt link device).
>>>     */
>>>    if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, prt->Source,
>>>&lnkdev))) { device_printf(pcib, "couldn't find PCI interrupt link device
>>>%s\n", prt->Source);
>>>    interrupt = acpi_pci_link_route_interrupt(acpi_get_device(lnkdev),
>>>	prt->SourceIndex);
>>>
>>>And Pawel's trace shows that the first argument to
>>>acpi_pci_link_route_interrupt() is NULL.
>>
>>What's the value of prt->Source?  If it's not a valid reference to a
>>link device (i.e. \_SB.PCIx.LNKx), then trying to get a device_t from it
>>would yield NULL.  For instance, if it points to \_SB, you'll get a
>>valid handle from AcpiGetHandle but that handle obviously has no
>>associated device_t.
>>
>>Additionally, I see you're using the root handle ACPI_ROOT_OBJECT as the
>>base for lookup.  If the reference is relative (doesn't start with \),
>>this won't work.  You should be using the handle of the parent of _PRT
>>(the PCI bus handle) as the root of the lookup.  Commonly, this will be
>>something like a \_SB.PCI0 string.
>>
>>This would fix this scenario:
>>\_SB.PCI0
>>     _PRT (Source = LNKA)
>>     LNKA
>>     LNKB
> 
> 
> Ok, that might be it.  I'll work up a patch to use the relative roots instead.  
> In fact, the patch is very simple.  It already used relative lookups when 
> force-attaching the link devices during attach.  Pawel, the change is this:
> 
> --- //depot/vendor/freebsd/src/sys/dev/acpica/acpi_pcib.c	2004/12/27 05:40:30
> +++ //depot/user/jhb/acpipci/dev/acpica/acpi_pcib.c	2005/01/06 18:40:54
> @@ -249,7 +249,8 @@
>      /*
>       * We have to find the source device (PCI interrupt link device).
>       */
> -    if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, prt->Source, &lnkdev))) 
> {
> +    if (ACPI_FAILURE(AcpiGetHandle(acpi_get_handle(pcib), prt->Source,
> +	&lnkdev))) {
>  	device_printf(pcib, "couldn't find PCI interrupt link device %s\n",
>  	    prt->Source);
>  	goto out;
> 

CURRENT from 16:00 UTC and the patch above seems to result in the same thing :(

Copyright (c) 1992-2005 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
         The Regents of the University of California. All rights reserved.
FreeBSD 6.0-CURRENT #0: Thu Jan  6 20:31:16 CET 2005
     root at zero:/usr/obj/usr/src/sys/ZERO
...
pcib0: matched entry for 0.15.INTA (src \LPUS:0)


Fatal trap 12: page fault while in kernel mode
cpuid = 0; apic id = 00
fault virtual address   = 0x48
fault code              = supervisor read, page not present
instruction pointer     = 0x8:0xc051f487
stack pointer           = 0x10:0xc0820958
frame pointer           = 0x10:0xc082096c
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         = 0 (swapper)
[thread pid 0 tid 0 ]
Stopped at      device_get_softc+0x7:   movl    0x48(%eax),%eax
db> tr
Tracing pid 0 tid 0 td 0xc06ef960
device_get_softc(c07de4a0,c07d99cd,355,c1e841c0,c1e841c0) at device_get_softc+0x7
acpi_pci_link_route_interrupt(0,0,c0820a24,c0820a2c,41) at 
acpi_pci_link_route_interrupt+0x3a
acpi_pcib_route_interrupt(c1f16d00,c1f8b780,1,c1f7e1f4,1) at 
acpi_pcib_route_interrupt+0x3a1
acpi_pcib_acpi_route_interrupt(c1f16d00,c1f8b780,1,c06c7f10,c1f8b808) at 
acpi_pcib_acpi_route_interrupt+0x2f
pci_assign_interrupt_method(c1f16a00,c1f8b780,f,2,24) at 
pci_assign_interrupt_method+0x71
pci_add_child(c1f16a00,c1f8b800,f,2,80) at pci_add_child+0x207
pci_add_children(c1f16a00,0,80,c0820b54,c052188f) at pci_add_children+0x123
acpi_pci_attach(c1f16a00,c1f4484c,c06c14ec,c06aa680,0) at acpi_pci_attach+0x86
device_attach(c1f16a00,c1ed5d80,c0820bdc,c07c538c,c1f16d00) at device_attach+0x2c9
bus_generic_attach(c1f16d00,c07d92a7,0,c0820bcc,0) at bus_generic_attach+0x18
acpi_pcib_attach(c1f16d00,c1f7e1f4,0,c0820c04,c07bff97) at acpi_pcib_attach+0xec
acpi_pcib_acpi_attach(c1f16d00,c1f4384c,c06c14ec,c06aa680,0) at 
acpi_pcib_acpi_attach+0xf9
device_attach(c1f16d00,2f,c0820cbc,c07c27c4,c1ed5d80) at device_attach+0x2c9
bus_generic_attach(c1ed5d80,2e,2f,c1f7dc28,2e) at bus_generic_attach+0x18
acpi_attach(c1ed5d80,c1f4604c,c06c14ec,c06aa680,0) at acpi_attach+0x7b4
device_attach(c1ed5d80,c1f15000,c0820d18,c0679ffa,c1f15000) at device_attach+0x2c9
bus_generic_attach(c1f15000,c1f1504c,c0820d54,c0520839,c1f15000) at 
bus_generic_attach+0x18
nexus_attach(c1f15000,c1f3c04c,c06c14ec,c06aa680,0) at nexus_attach+0x1a
device_attach(c1f15000,c06dda30,c0820d78,c06670d8,c1f15680) at device_attach+0x2c9
root_bus_configure(c1f15680,c06bb361,0,c0820d98,c04d1126) at root_bus_configure+0x19
configure(0,0,c1e6f774,81ec00,81e000) at configure+0x28
mi_startup() at mi_startup+0xd6
begin() at begin+0x2c
db>

> 
>>Also, I'm not sure if you picked up the size issue with the _PRT struct
>>supplied by ACPI-CA.  Since Source is a variable-length string, if you
>>copy the struct you get from AcpiGetRoutingTable (or whatever), you only
>>get the first 4 bytes, non-null terminated, of the string.
>>
>>typedef struct acpi_pci_routing_table
>>{
>>     UINT32                      Length;
>>     UINT32                      Pin;
>>     ACPI_INTEGER                Address;
>>     UINT32                      SourceIndex;
>>     char                        Source[4];
>>} ACPI_PCI_ROUTING_TABLE;
>>
>>Note that Source above is not 4 bytes, it's variable-length.  That's why
>>I copied it to a different field in the old acpi_pci_link PRT struct.
> 
> 
> I don't ever store the Source anywhere, I just use it to lookup handles, so I 
> don't have to worry about the size change.
> 

-- 
Pawel


More information about the freebsd-current mailing list