Hi,
gaf wrote:Brednan wrote:To start other CPUs you first need to detect what other CPUs are present (their local APIC IDs), and detect where the local APIC is mapped in memory (usually at 0xFEE00000, but necessarily always). You can get this information from the Multiprocessor Specification or from ACPI. It's mostly the same in either case - finding and reading data from tables created by the BIOS.
Have you any experiences with the Intel multiprocessor tables on multicore systems ?
Yes.
So far I've written code to detect other CPUs using both tables about 4 times (and have tested it on at least 2 real SMP machines). The way I do it is to look for the ACPI tables and then look for Intel's MP tables if ACPI isn't present, however I write the MP table stuff first so I can test it.
I've also done things from the other side for my Bochs BIOS - writing code to manually detect CPUs and then building the ACPI and MP specification tables for the OS.
gaf wrote:As far as I know the Intel standard is rather outdated today as ACPI has taken its position. This also mean that the specifications are no longer updated or extended as new technologies are introduced. Especially since support for hyperthreading has never been included in the standard I've some doubts whether multicore systems are detected correctly.
Yes - anything made after (roughly) the year 2000 should have ACPI. My OS is "Pentium or later if you want SMP support", which goes back to machines made after the year 1993, and means there's about 7 years where SMP machines will have MP tables but won't have ACPI.
For multi-core and hyper-threading, the ACPI table reports all logical CPUs (if hyper-threading isn't disabled in the BIOS) while Intel's MP tables only report physical CPUs (i.e. multi-core and multi-chip, but not hyper-threading, AFAIK).
I'd recommend doing the same as I do - check for ACPI first, then use the MP tables if ACPI isn't present (although this depends on your OS's minimum requirements - for a "64-bit only" OS I wouldn't bother with Intel's MP tables).
gaf wrote:It should also be noted that there's an alternative way of detecting the number of cores and logical threads on a given cpu. The basic approach is to get the number of logical processors from a series of CPUID call and use this information to reconstruct the APIC IDs of all other cores and HT processors from the ID of any processor (f.ex bootstrap) on that physical package. Chapter 7.10 of the Intel Manual 3a describes the process in greater detail and provides some sample code.
Correct, but if you're going to support "multi-core" then you may as well support SMP - there's very little practical difference (except detection) - the code to start extra CPUs is the same, the OS needs the same re-entrancy locking, etc. The only real differences are optional optimizations (for e.g. detecting which caches are shared within a chip, and adjusting the scheduling, etc to keep caches hot while still allowing tasks to run on different CPUs).
Also note that Intel's documentation describes Intel's CPUs only. IIRC Intel uses CPUID with EAX = 0x00000004, while AMD use CPUID with EAX = 0x80000008, and AMD don't support Intel's method, and Intel don't support AMDs method.
For completeness, there is another way to detect the other CPUs. It's possible to do the multi-CPU startup sequence using broadcast IPIs (send to all except self), so that all extra CPUs start running. Once an extra CPU is running it'd incrememt a "total CPUs found" counter and store it's APIC ID somewhere.
There's 3 problems with this "manual detection" method. First you have to assume the local APIC is at 0xFEE00000 when it might not be. Second, it ignores the "disable hyper-threading" BIOS setting (in some situations disabling hyperthreading can improve performance). Lastly, when a faulty CPU is present the BIOS can start it, find out it's faulty then disable it, but you'd end up trying to use the faulty CPU.
The last 2 reasons are also reasons why an OS should never use "send to all" IPIs for some of the interrupt types - you shouldn't assume your OS knows about all CPUs. The "send to all" broadcast IPI does work fine for normal IPIs as they are ignored by disabled CPUs, but SMI, NMI, STARTUP and INIT aren't ignored by disabled CPUs and can cause unexpected problems.
Cheers,
Brendan