|
From: Daniel R. <cos...@gm...> - 2006-04-30 20:02:38
|
Hello, I've now added the APIC reactivation hack that I've mentioned a while ago to the code. It would be great if everybody could run the kernel on a few real computers, so that we get a better idea of how broadly the APIC is really supported. Based on this knowledge we can then decide if it's really necessary to write some backwards compatiblity code for PCs that don't support the APIC timer. What I need to know is how many processors your computer has and if they where all detected, if the APIC test was passed and whether an I/O APIC was detected. The local apic test sets-up a timer and then waits until it runs out. The timer length is 0x1000000 cycles, so that the test should be finished after a few seconds. If there is an local apic the I/O APIC test will follow, otherwise the computer just hangs. For the I/O APIC test the kernel simply assumes that the default location is used, and prints some of the registers that should be located there. If the APIC really exists the values should all be different: version should be between 0x10 and 0x20 and the number of redirection entries should be 0x17. In case that there's no I/O APIC the values printed will all be the same (in most cases either 0x00 or 0xff). I've uploaded an example screenshot to my webspace (mitglied.lycos.de/coszmo86/example.png) in order to give you an idea of how it should look if everything works as planned.. (Note that I just had some problems compiling the code with cygwin. In case that you too encounter some errors in cpu_info.hpp you should be able to fix them by simply declaring the whole class as public.) regards, cosmo86 |
|
From: Daniel R. <cos...@gm...> - 2006-04-30 20:06:51
|
Sorry guys, the url is actually: mitglied.lycos.de/cozmo86/example.png |
|
From: Stephen M. W. <ste...@br...> - 2006-05-01 14:48:32
|
On 30/04/06 16:02, Daniel Raffler wrote: > > What I need to know is how many processors your computer has and if they > where all detected, if the APIC test was passed and whether an I/O APIC > was detected. Here's the result of tests on 5 different machines. Description M/U # LAPIC ID Ver Red AMD Sempron 2800+ M 1 000f0d00 2 03 17 AMD Athlon 2200+ U 1 1 11 17 AMD dual-core Opteron 165 M 2 000f0d00 0 11 17 Intel Celeron M 1 000f0000 0 11 0f Intel P4 M 1 000f12a0 1 20 17 Notes: M/U indicates if the kernel detected a multiprocessor configuration or not (uniprocessor). # indicates the number of processors sucessfully booted. LAPIC is the detected address of the local APIC. -- Stephen M. Webb ste...@br... |
|
From: Daniel R. <cos...@gm...> - 2006-05-03 17:00:41
|
> Description M/U # LAPIC ID Ver Red > > AMD Sempron 2800+ M 1 000f0d00 2 03 17 > AMD Athlon 2200+ U 1 1 11 17 > AMD dual-core Opteron 165 M 2 000f0d00 0 11 17 > Intel Celeron M 1 000f0000 0 11 0f > Intel P4 M 1 000f12a0 1 20 17 Hi Stephen, thanks for having taken the time for a test-run ! It's good to see that the new local apic reactivation code doesn't only work on my computer but also on you uniprocessor Athlon. From the results it also looks as if the I/O APIC was much more common on modern computers than I've expected. The only thing that causes me some headach is the version number returned by your Sempron 2800+, which should actually be something in between 0x10 and 0x20 for an internal APIC. The two other values (ID and Red) seem to be perfectly sensible though.. Luckily the machine's BIOS however does support the multiprocessor table and will thus report if there's an I/O APIC. For uniprocessor systems that don't provide any multiprocessor tables we could fall back to a probing mechanism. I would propose that we simply try to read-out the I/O APIC's version number to make some sanity checks on it. If the number is between 0x10 and 0x20 we assume that it really is an I/O APIC, otherwise we'll have to retreat to the ISA PIC. It guess it should be unlikely enough that the bus-noise returned if there's no I/O APIC happens to be a valid version number ? Description M/U # ID Ver Red AMD Athlon 2600+ M 1 2 11 17 Intel Pentium 3 700 U 1 f ff ff Intel P4 2800 M 1 2 20 17 regards, cosmo86 |
|
From: Stephen M. W. <ste...@xa...> - 2006-05-03 18:41:15
|
On 03/05/06 13:00, Daniel Raffler wrote:
> > Description M/U # LAPIC ID Ver Red
> >
> > AMD Sempron 2800+ M 1 000f0d00 2 03 17
> The
> only thing that causes me some headach is the version number returned by
> your Sempron 2800+, which should actually be something in between 0x10
> and 0x20 for an internal APIC. The two other values (ID and Red) seem to
> be perfectly sensible though..
It's a real IOAPIC all right. The mobo is a GA-K8VM800M (VIA chipset for
socket 754). I suspect Gigabyte misinterpreted the IOAPIC specs, since they
say the correct value is 11h which they may have though was in binary.
The first few lines of the Linux bootup (just for interests sake) is as
follows. Note that the LAPIC address here is different that the one you
detected.
Linux version 2.6.15-dcc-smp (root@amd64-coreos) (gcc version 3.3.5 (Debian
1:3.3.5-13)) #1 SMP PREEMPT Fri Mar 10 15:50:30 EST 2006
BIOS-provided physical RAM map:
BIOS-e820: 0000000000000000 - 000000000009f800 (usable)
BIOS-e820: 000000000009f800 - 00000000000a0000 (reserved)
BIOS-e820: 00000000000f0000 - 0000000000100000 (reserved)
BIOS-e820: 0000000000100000 - 000000003bff0000 (usable)
BIOS-e820: 000000003bff0000 - 000000003bff3000 (ACPI NVS)
BIOS-e820: 000000003bff3000 - 000000003c000000 (ACPI data)
BIOS-e820: 00000000fec00000 - 00000000fec01000 (reserved)
BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved)
BIOS-e820: 00000000ffff0000 - 0000000100000000 (reserved)
ACPI: RSDP (v000 VIAK8 ) @ 0x00000000000f6b20
ACPI: RSDT (v001 VIAK8 AWRDACPI 0x42302e31 AWRD 0x01010101) @
0x000000003bff3000
ACPI: FADT (v001 VIAK8 AWRDACPI 0x42302e31 AWRD 0x01010101) @
0x000000003bff3040
ACPI: MADT (v001 VIAK8 AWRDACPI 0x42302e31 AWRD 0x01010101) @
0x000000003bff7740
ACPI: DSDT (v001 VIAK8 AWRDACPI 0x00001000 MSFT 0x0100000c) @
0x0000000000000000
On node 0 totalpages: 241262
DMA zone: 2917 pages, LIFO batch:0
DMA32 zone: 238345 pages, LIFO batch:31
Normal zone: 0 pages, LIFO batch:0
HighMem zone: 0 pages, LIFO batch:0
ACPI: PM-Timer IO Port: 0x4008
ACPI: Local APIC address 0xfee00000
ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled)
Processor #0 15:12 APIC version 16
ACPI: LAPIC_NMI (acpi_id[0x00] dfl dfl lint[0x1])
ACPI: IOAPIC (id[0x02] address[0xfec00000] gsi_base[0])
IOAPIC[0]: apic_id 2, version 3, address 0xfec00000, GSI 0-23
ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
ACPI: IRQ0 used by override.
ACPI: IRQ2 used by override.
ACPI: IRQ9 used by override.
Setting APIC routing to physical flat
Using ACPI (MADT) for SMP configuration information
Allocating PCI resources starting at 40000000 (gap: 3c000000:c2c00000)
Checking aperture...
CPU 0: aperture @ e0000000 size 64 MB
SMP: Allowing 3 CPUs, 2 hotplug CPUs
Built 1 zonelists
Kernel command line: auto BOOT_IMAGE=Xandros_Server_1 ro root=306 quiet rw
acpi=on resume2=swap:/dev/hda5
Initializing CPU#0
PID hash table entries: 4096 (order: 12, 131072 bytes)
time.c: Using 3.579545 MHz PM timer.
time.c: Detected 1607.471 MHz processor.
Console: colour dummy device 80x25
Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes)
Inode-cache hash table entries: 65536 (order: 7, 524288 bytes)
Memory: 962932k/982976k available (2274k kernel code, 19344k reserved, 877k
data, 176k init)
Calibrating delay using timer specific routine.. 3222.83 BogoMIPS
(lpj=6445671)
Security Framework v1.0.0 initialized
SELinux: Initializing.
SELinux: Starting in permissive mode
selinux_register_security: Registering secondary module capability
Capability LSM initialized as secondary
Mount-cache hash table entries: 256
CPU: L1 I Cache: 64K (64 bytes/line), D cache 64K (64 bytes/line)
CPU: L2 Cache: 256K (64 bytes/line)
mtrr: v2.0 (20020519)
Using local APIC timer interrupts.
Detected 12.558 MHz APIC timer.
Brought up 1 CPUs
time.c: Using PIT/TSC based timekeeping.
testing NMI watchdog ... OK.
checking if image is initramfs...it isn't (no cpio magic); looks like an
initrd
NET: Registered protocol family 16
ACPI: bus type pci registered
PCI: Using configuration type 1
ACPI: Subsystem revision 20050902
ACPI: Interpreter enabled
ACPI: Using IOAPIC for interrupt routing
ACPI: PCI Root Bridge [PCI0] (0000:00)
PCI: Probing PCI hardware (bus 00)
ACPI-0412: *** Error: Handler for [SystemMemory] returned AE_AML_ALIGNMENT
ACPI-0508: *** Error: Method execution failed [\_SB_.PCI0._CRS] (Node
ffff810001ee4900), AE_AML_ALIGNMENT
ACPI-0156: *** Error: Method execution failed [\_SB_.PCI0._CRS] (Node
ffff810001ee4900), AE_AML_ALIGNMENT
Boot video device is 0000:01:00.0
ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
ACPI: PCI Interrupt Link [LNKA] (IRQs 3 4 6 7 10 *11 12)
ACPI: PCI Interrupt Link [LNKB] (IRQs 3 4 6 7 10 11 12) *5
ACPI: PCI Interrupt Link [LNKC] (IRQs 3 4 6 7 *10 11 12)
ACPI: PCI Interrupt Link [LNKD] (IRQs 3 4 6 7 10 11 12) *0, disabled.
ACPI: PCI Interrupt Link [LNKE] (IRQs 3 4 6 7 10 11 12) *0, disabled.
ACPI: PCI Interrupt Link [LNKF] (IRQs 3 4 6 7 10 11 12) *0, disabled.
ACPI: PCI Interrupt Link [LNK0] (IRQs 3 4 6 7 10 11 12) *0, disabled.
ACPI: PCI Interrupt Link [LNK1] (IRQs 3 4 6 7 10 11 12) *0, disabled.
ACPI: PCI Interrupt Link [ALKA] (IRQs 20) *0, disabled.
ACPI: PCI Interrupt Link [ALKB] (IRQs 21) *0, disabled.
ACPI: PCI Interrupt Link [ALKC] (IRQs 22) *0, disabled.
ACPI: PCI Interrupt Link [ALKD] (IRQs 23) *0, disabled.
|
|
From: Daniel R. <cos...@gm...> - 2006-05-04 17:15:21
|
> It's a real IOAPIC all right. The mobo is a GA-K8VM800M (VIA chipset for > socket 754). I suspect Gigabyte misinterpreted the IOAPIC specs, since > they say the correct value is 11h which they may have though was in > binary. As the I/O APIC is part of the chipset's south-bridge it's actually VIA rather than Gigabyte that is to be blamed for the bug. In any case your assumption does make some sense in my opinion, although I frankly wouldn't have expected a global player like VIA to make such blunders. > Note that the LAPIC address here is different that the one you > detected. Actually the trion kernel doesn't even print the local APIC address, what you posted is the location of the multiprocessor configuration table.. regards, Daniel |
|
From: Stephen M. W. <ste...@br...> - 2006-05-04 18:41:11
|
On 04/05/06 13:15, Daniel Raffler wrote: > > It's a real IOAPIC all right. The mobo is a GA-K8VM800M (VIA chipset for > > socket 754). I suspect Gigabyte misinterpreted the IOAPIC specs, since > > they say the correct value is 11h which they may have though was in > > binary. > > As the I/O APIC is part of the chipset's south-bridge it's actually VIA > rather than Gigabyte that is to be blamed for the bug. In any case your > assumption does make some sense in my opinion, although I frankly wouldn't > have expected a global player like VIA to make such blunders. True. I have a VIA chipset in another computer (not at hand at the moment) that does not report anything unusual. Since noone seems to do much with the IO-APIC version number I don't suppose it really makes any difference. > > Note that the LAPIC address here is different that the one you > > detected. > > Actually the trion kernel doesn't even print the local APIC address, what > you posted is the location of the multiprocessor configuration table.. My mistake. I was so excitied about creating a bootable Trion CD I didn't bother checking the code tee see what I was actually writing down. Some of my test systems do not have floppies. -- Stephen M. Webb ste...@br... |
|
From: Manuel H. <mho...@ph...> - 2006-05-09 01:13:28
|
Hi Trionists,
I have also tested the kernel at several computers at home and at
university, here's the result:
M/U # Addr ID Ver Red
Dual Pentium 2, 333 MHz M 2 000F1400 2 11 17
Pentium 2, 350 MHz U 1 F FF FF
AMD Athlon, 500 MHz U 1 F FF FF
Pentium 4, 2400 MHz M 1 000F0000 4 20 17
AMD Athlon XP 3000+ M 1 000F6570 2 03 17
AMD Athlon 64 3200+ M 1 000F1400 2 11 17
As you can see, it also works on SMP hardware that is slightly older.
Regards,
Manuel
|
|
From: Stephen M. W. <ste...@br...> - 2006-05-09 12:22:16
|
On 07/05/06 08:14, Manuel Hohmann wrote: > AMD Athlon XP 3000+ M 1 000F6570 2 03 17 There it is again (the version 03). I guess it's legitimate. -- Stephen M. Webb ste...@br... |
|
From: Daniel R. <cos...@gm...> - 2006-05-09 16:13:38
|
Hello Manuel
thanks for the test-run.. Good to see that it also works on the more dated
hardware.
> There it is again (the version 03). I guess it's legitimate.
Either that or you two just happen to use mainboards with the same chipset
;). From what I can tell versions numbers 0x01 through 0x10 are reserved
for I/O APICs of the 486 era that didn't yet use the new APIC architecture
(XAPIC). Here's a snipped of the linux code that checks the version number
at boot-time:
if((reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
(reg_01.bits.version != 0x10) && /* oldest IO-APICs */
(reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
(reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
(reg_01.bits.version != 0x20)) /* Intel P64H (82806 AA) */
{
UNEXPECTED_IO_APIC();
}
I propably should add that UNEXPECTED_IO_APIC() is just some empty stub
procedure, so that the kernel still boots if the version is other than the
expected values.
regards,
cosmo86
http://lxr.linux.no/source/arch/i386/kernel/io_apic.c#L1302
|
|
From: Daniel R. <cos...@gm...> - 2006-05-22 16:18:31
|
Hello Trionists, I finally found some time to fix a number of minor bugs and extended the kernel by some new functionality: - Added (very basic) handling for local APIC errors and spurious interrupts - APIC classes now use logical IDs only - Fixed a small bug that migth have lead to faulty APIC reactivations - Cleaned up the exception class, registers on the stack can now be accessed directly - IRQ class can detect an I/O APIC by probing, support for system that use ISA PIC only - Included support for hyperthreading enabled processors Unfortunately there are still some problems with the logical ID APIC code. As cluster-mode doesn't seem to be supported by modern CPU anymore, I was forced to use the more restrictive flat-mode, that only allows a maximum of 8 processors. Each CPU is assigned a unique 8 bit logical ID that can be calculated by (1 << physical_id). The ID is thus basically a bitmask with each bit representing a processor. If the APIC receives a message it compares (AND operation) its logical ID with the destination ID defined in the message. In case that the result is true the message is accepted and gets handled. All messages sent by the I/O APIC have a destination of 0xff, which basically means that any processors may handle it. As the IRQs are sent with delivery-mode 'lowest' the processors with the lowest privilege-level should take the message. The privilege-level is either determined by the current task-priority, that can be set by software (I however didn't touch it yet..), or by the priority of a pending interrupt that is currently handled. I then ran a test in which the first CPU receives an interrupt and blocks, thus remaining on a high priority-level. One would now expect that the next interrupt is handled by one of the remaining processors, which still run on the lowest privilege-level. Unfortunately this is not what's happening. Any subsequent interrupt is again dispatched to the first processor, which of course can't handle it as it hasn't yet acknowledged its earlier messages. The logical destination code itself however seems to work flawlessly: If I change the IRQ's destination ID to 0xFE the second processor handles it, and if I set it to 0xFB it's the third CPU that gets the message. As I've already spent quite some time location my mistake (without any notable success so far), I was wondering whether it wasn't possible that Bochs just doesn't simulate the details of APIC message delivery mechanism properly. Bochs' APIC support is still somewhat limited, and I've seen similiar things with error-handling, that doesn't seem to get emulated either (the error-handling code however does work on real hardware). Maybe someone could try the code on some multiprocessor or dual-core hardware ? All you would have to do is to hang the code at the _beginning_ of InterruptDestructor() in irq.cpp - if my code works each processor should print its own number, otherwise there's only one number printed after the "You may now type something" statement. Has anybody here already implemented logical APIC IDs before ? regards, cosmo86 I should probably warn you that the CVS address hostname has changed from "cvs.sourceforge.net" to "trion.cvs.sourceforge.net", it took me two days to find it out myself ;) |
|
From: Daniel R. <cos...@gm...> - 2006-06-02 21:57:45
|
Hello, I'll be on holiday in Italy during the next week and though that I might aswell commit the code I've been working on to the CVS. Unfortunately I ran out of time a bit and thus couldn't fully debug the code: It does work on bochs though, on real hardware there seem to be some minor problems. - support for sysenter/sysexit mechanism (ring3) - merged apic_error with the exception class - some general improvements to the old code In case that somebody wants to code a bit in the meantime there's (..for example..) still the GRUB memory map parsing class that we'll need sooner or later. In my opinion it shouldn't be too hard a task, especially if you take mp_detect.hpp - which too scans through some tables - as a base.. cheers, cosmo86 |