Hi,
Tyler wrote:Are the intel multiprocessor specs and ACPI multiprocessor tables incompatible?
Intel's Multiprocessor Specification (or MPS for short) is a set of tables that contain information needed to use SMP (and nothing else). ACPI is a set of tables that contain the same information needed to use SMP (and a lot of other stuff we can ignore for the purpose of this discussion).
MPS is older and easier to understand because it doesn't contain other stuff, gives better descriptions of what's going on and also contains more information (like the algorithm used to actually start the CPUs). ACPI is newer and is meant to make MPS obsolete (although I haven't found an SMP system with ACPI that doesn't also have MPS tables for backwards compatability). ACPI also includes things that are useful once you move beyond plain SMP (i.e. more tables that describe NUMA machines).
GLneo wrote:well I could read the table ( mabey ) but I don't understand where these tables are? also how do I send the startup to all CPUs?
For the reasons mentioned above, I'd implement support for MPS first, and worry about ACPI after you've got that working. Most OS's will check for ACPI tables and use them, but will also use MPS if ACPI isn't found.
I'd start by downloading and reading
Intel's Multiprocessor Specification.
To make this easier I'll provide a description of how I do things and links to the source code...
Note: My code to find the MPS and ACPI tables is seperate from the code that uses these tables. This isn't necessary and is a result of my modular OS design (I have a Boot Manager that has an API that allows other modules to ask for the addresses of MPS tables and ACPI tables).
There's several steps that are mostly the same for both MPS and ACPI, so I'll describe them in parallel.
Step 1 - Find The Table/s
For both ACPI and MPS, the tables live somewhere, and you need to search for them. This mainly involves scanning different areas (the EBDA and the BIOS) for an identifier ("_MP_" and "RSD ") and checking a checksum.
Step 2 - Find Relevant Entries In The Table/s
This is slightly different for ACPI and MPS. For MPS each table has a length, and the tables follow each other in memory. Each table has a unique numeric identifier. To find a specific table you'd start from the beginning and skip tables until you find the right one. For ACPI each table has a 4 character ASCII identifier, and there's a "Root Directory" that contains pointers to each table, so you scan this directory until you find the right pointer. My Boot Manger's API also includes functions to determine how many tables there are with a certain identifier (and allows other modules to ask for the Nth table of a certain type).
Step 3 - Parse The Table/s
For MPS there's "default configurations" which a describe a specific configuration (always 2 CPUs where one uses APIC ID 0x00 and the other uses APIC ID 0x01), so first we check if MPS is using a default configuration and use assumed values (instead of parsing tables) if it is. Most machines don't use a default configuration. For most machines there's a table for each "local APIC" (or CPU), so my code asks the Boot Manager how many of these there are, then does a loop that gets each table and parses it. For ACPI there's a single table that describes all APICs (local APICs and IO APICs). My code gets the address of this table and scans through it, ignoring anything that doesn't describe a local APIC.
Step 4 - Start Each CPU
For the previous step, each time the code found a local APIC (or a CPU) in the tables it created a structure containing initial information about that CPU. In this step we go through the list of "CPU data structures" and start each CPU, except for the BSP CPU (which is already running). This involves sending some IPIs (Interprocessor Interrupts) from the BSP CPU to the "sleeping" CPU to wake it up. The sequence of IPIs (and the timing requirements) are described in Intel's Multiprocessor Specification. To be honest I don't follow Intel's algorithm here (I found the delays are too short to accurately measure) and did my own slightly different thing. Also, starting CPUs with older local APICs is slightly different. Intel's algorithm describes how they are started, while my OS refuses to use SMP in this case (I don't support SMP for 80486 or older computers, and they'd boot as single CPU machines).
When a CPU is started it starts in real mode at the address you tell it (which must be below 1 MB with certain aligment restrictions). My code puts a JMP instruction at a suitable address and tells AP CPUs to start there. My boot code also runs in real mode so I don't switch the AP CPUs to protected mode at this stage (but it does set GS to "flat mode").
Conclusions
The way I do things is a little more complicated than necessary (due to the modular nature of my OS). It'd be possible to have a single routine that parses the ACPI or MPS tables and starts CPUs as it finds them.
I have skipped some details in my descriptions above (like full descriptions of tables, etc), and my source code might be a little hard to follow without these details. This is deliberate - you'll learn about these details (and be able to follow my code) after you've read
Intel's Multiprocessor Specification and the relevant part of the ACPI Specification.
Cheers,
Brendan