cvs commit: src/sys/i386/i386 machdep.c
John Baldwin
jhb at FreeBSD.org
Fri Dec 5 12:17:36 PST 2003
On 05-Dec-2003 John-Mark Gurney wrote:
> John Baldwin wrote this message on Fri, Dec 05, 2003 at 11:23 -0500:
>> The problem (which you didn't read in my mail I guess) is that the
>> fact that madt.ko is in its own module shouldn't be user visible.
>> The user should just say "load ACPI' and all the right magic should
>> happen.
>
> Well, now that you restate it, it's more clear. I got confused with
> your talking about linking issues, and other stuff, not just that issue.
>
> I was going to say, why don't you just call
> linker_load_module("madt.ko", NULL, NULL, NULL, NULL) from acpi and
> ignore the return code. Then if the module exists, it's loaded, if it
> doesn't, nothing changes...
>
> But this is problematic since SI_SUB_KMEM is significantly earlier than
> SI_SUB_KLD..
>
>> > is thinking of) attachment... Then madt would become a device off the
>> > acpi bus... If acpi can detect the presence of madt (self identifing
>> > bus), it can create the device node for madt to attach too... if acpi
>> > can't, then you use an identify function in the madt code to create
>> > the device node off the acpi bus...
>>
>> new-bus doesn't exist yet when we probe CPUs. Again, you haven't
>> actually looked at how this stuff works.
>
> I realized that shortly after I sent off the email that we might be a
> bit earlier than the vm subsystem and friends have been setup for newbus.
>
> Ok, now I'm completely confused, why is ACPI mentioned sooo much when
> the apic code that madt uses doesn't reference ACPI??
Well, two issuse. First, the APIC "driver" consists of a couple of
different pieces. One is the actual apic hardware driver for both the
local and I/O apics that provides interrupt sources for over devices to
use. The other pieces are apic enumerators. These "modules" perform
functionality similar to an identify routine for a new-bus driver in
that they create local and I/O APIC "devices" that the core apic driver
code then manages.
The second issue is PCI interrupt routing. Roughly, the function of
PCI interrupt routing is so that when a PCI device wants to register
an interrupt handler, it needs to know which interrupt source on the
motherboard it is hooked up to. In FreeBSD we use an IRQ number as a
kind of cookie. Some arch's like alpha do math on the cookie value
to map it to a given PCI device. On i386, the cookie value is an
index into an array of interrupt source objects. A given interrupt
source may be a pin on an 8259A managed by the atpic "driver" or it
may be a pin on an I/O apic managed by the apic "driver". The apic
enumerator plays a role in PCI interrupt routing in that it provides
PCI bridge drivers that give a PCI device an IRQ cookie at the "bottom"
that map to the right interrupt source at the "top".
For example, in the !ACPI case using the MP Table, the MP Table provides
in addition to entries dsecribing each APIC, entries for each ISA, EISA,
and PCI interrupt in the system. The entry lists which I/O APIC and pin
that interrupt is mapped to. For PCI devices, the entry actually contains
the bus, device, and intpin (#A through #D) and what (apic, pin) tuple
it maps to. Thus, when a PCI device routes its interrupt, the MP Table
PCI bridge drivers walk the MP Table to find an entry with a matching
bus, device, and intpin. They then look up that I/O APIC in an internal
array and ask it for the interrupt source associated with the given pin.
They can then ask that interrupt source for its associated vector via
the pic_get_vector() method.
In the ACPI case, each PCI bridge in the ACPI tree has a _PRT object
that describes interrupt routing for a given PCI device. Each entry
in the _PRT matches a certain bus/device/intpin and says that it either
maps to a fixed global interrupt number (common for APIC case) or to a
given index of a routable PCI link device (common for 8259A case and some
APIC cases). ACPI has a top-level _PIC method that OSPM executes to tell
it what kind of interrupt model (PIC vs. APIC) it is using. The _PRT
method then usually checks the saved value of this flag to determine
which table to use. (It has separate tables for the APIC and 8259A
cases.) Thus, while in the !ACPI case we have different sets of PCI
bridge drivers for PIC (PCIBIOS) vs. APIC (MP Table), ACPI has one
PCI bridge driver for both interrupt models.
Now, it is absolutely crucial that when using the APIC we use the
corresponding interrupt routing PCI bridge driver. For the PIC case,
the interrupts are always the ISA IRQs 0-15 with values 0-15 always
mapping to the 8259A master and slave PICs. However, for the MP Table
case, there is no defined mapping for how pins on I/O APICs are ordered.
We use a sensible model similar to ACPI in that we just assign the
vectors consecutively. For example, ioapic0 gets irqs 0-23 for its
intpins 0-23, ioapic1 gets IRQs 24-55 for its 32 intpins, etc.
ACPI generally follows that model but sometimes it leaves gaps. For
example, ioapic0 might be 0-23, and ioapic1 might be 48-79. Thus,
the ACPI and !ACPI interrupt routings can be different. Now, ACPI
provides those base interrupt numbers for I/O APICs in the MADT entries,
thus if we use the MADT to probe APICs, we must use ACPI to route
interrupts. If we don't use the MADT to probe APICs, we must not
use ACPI to route interrupts but must use the MP Table drivers
instead.
Thus, madt.ko and acpi.ko really are conceptually part of a single
ACPI driver in that both parts contribute to the acpi_pcib(4) drivers
and their interrupt routing mechanism. Hopefully this helps clear up
some of the confusion.
--
John Baldwin <jhb at FreeBSD.org> <>< http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve!" - http://www.FreeBSD.org/
More information about the cvs-src
mailing list