multi-core /parallel programming

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Laksen
Member
Member
Posts: 140
Joined: Fri Nov 09, 2007 3:30 am
Location: Aalborg, Denmark

Post by Laksen »

Couldn't you just clear present on the interrupt descriptor for the cpu which doesn't need to handle a specific interrupt
User avatar
Jef
Member
Member
Posts: 112
Joined: Tue Jan 08, 2008 7:25 am
Location: Greece
Contact:

Post by Jef »

Laksen wrote:As your computer boots the BSP(boot service processor) has control. Your kernel should get loaded like it's a UP(uniprocessor system). Then you search the SMP or ACPI table for processor entries. If you find more than one then your PC should have multiple cores. Then you choose to boot the AP's. You do this by sending interrupts to the designated AP's local APIC. In this interrupt you tell the AP where it should start. Then you would have two kernel's running so to say. They can essentially be running the same code, and you can access the same memory and by that way talk between the processors.
I find the MP Floating Pointer Structure in memory, i follow the MP Configuration Table pointer.
The first entries that are the processors (entries with Entry Type=0) are the follow (20 bytes per entry):

Code: Select all

00 00 00 11 03 F8 06 00 00 FF FB EB 0F 00 00 00 00 00 00 00
00 00 01 11 01 F8 06 00 00 FF FB EB 0F 00 00 00 00 00 00 00
00 01 00 50 43 49 20 20 20 01 01 50 43 49 20 20 20 01 02 49
I have a dual core cpu so the first two entries are correct.
Why exists a third entry with entry type zero ?
Keep coding...
...the sky is the limit

AsteriOS project: http://www.mindfields.gr/main/index.php ... &Itemid=27
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post by Brendan »

Hi,
Jef wrote:

Code: Select all

00 00 00 11 03 F8 06 00 00 FF FB EB 0F 00 00 00 00 00 00 00
00 00 01 11 01 F8 06 00 00 FF FB EB 0F 00 00 00 00 00 00 00
00 01 00 50 43 49 20 20 20 01 01 50 43 49 20 20 20 01 02 49
Decoded:

Code: Select all

First entry:
    00 = Local APIC entry
    00 = Local APIC ID = 0
    00 = Local APIC version = 0 (which is extremely unlikely)
    11 = CPU flags = Usable AP CPU
    03 F8 06 00 = CPU Signature (stepping = 3, model = 0, family = 8)
    00 FF FB EB = CPU features
    0F 00 00 00 00 00 00 00 = reserved

Second entry:
    00 = Local APIC entry
    00 = Local APIC ID = 0 (which is wrong because the ID is already used by first entry)
    01 = Local APIC version = 0 (which is extremely unlikely)
    11 = CPU flags = Usable AP CPU
    01 F8 06 00 = CPU Signature (stepping = 1, model = 0, family = 8)
    00 FF FB EB = CPU features
    0F 00 00 00 00 00 00 00 = reserved

Third entry:
    00 = Local APIC entry
    01 = Local APIC ID = 1
    00 = Local APIC version = 0 (which is extremely unlikely)
    50 = CPU flags = unusable AP CPU
    43 49 20 20 = CPU Signature (stepping = 3, model = 4, family = 9)
    20 01 01 50 = CPU features
    43 49 20 20 20 01 02 49 = reserved
This looks entirely dodgy - there isn't even any BSP.

However, if you skip the first byte and look at it like this:

Code: Select all

00 00 11 03 F8 06 00 00 FF FB EB 0F 00 00 00 00 00 00 00 00
00 01 11 01 F8 06 00 00 FF FB EB 0F 00 00 00 00 00 00 00 00
01 00 50 43 49 20 20 20 01 01 50 43 49 20 20 20 01 02 49 ??
Then it becomes:

Code: Select all

First entry:
    00 = Local APIC entry
    00 = Local APIC ID = 0
    00 = Local APIC version = 0x11
    03 = CPU flags = Usable BSP CPU
    F8 06 00 00 = CPU Signature (stepping = 8, model = F, family = 6)
    FF FB EB 0F = CPU features
    00 00 00 00 00 00 00 00 = reserved

Second entry:
    00 = Local APIC entry
    01 = Local APIC ID = 1
    00 = Local APIC version = 0x11
    01 = CPU flags = Usable AP CPU
    F8 06 00 00 = CPU Signature (stepping = 8, model = F, family = 6)
    FF FB EB 0F = CPU features
    00 00 00 00 00 00 00 00 = reserved

Third entry:
    01 = Bus entry
    00 = Bus ID = 0
    50 43 49 20 20 20 = Bus type string = "PCI   "

Fourth entry:
    01 = Bus entry
    01 = Bus ID = 1
    50 43 49 20 20 20 = Bus type string = "PCI   "

Fifth entry (truncated):
    01 = Bus entry
    02 = Bus ID = 2
    49 ?? ?? ?? ?? ?? = Bus type string = "I?????"
This correctly describes a dual CPU system with two "P6" CPUs (from the feature flags and CPU model I'd guess it's a relatively new Intel CPU; and not a Pentium III or older "P6"). The computer has 2 PCI buses and I'd guess the last (truncated) bus entry is for an ISA bus.

Basically, IMHO, you're starting from the wrong byte of data... ;)


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Jef
Member
Member
Posts: 112
Joined: Tue Jan 08, 2008 7:25 am
Location: Greece
Contact:

Post by Jef »

Brendan wrote:Basically, IMHO, you're starting from the wrong byte of data... ;)


Cheers,

Brendan
I made the "decode" you say above, but it was 8:30 am (after 8 hours of programing). I am sure you are right.
Yes, its a Intel Dual Core (E2180 2.0 GHz)
Thanks for the info.
Sometimes the solutions its too obvious (or too simple) that you cannot think it :)
Keep coding...
...the sky is the limit

AsteriOS project: http://www.mindfields.gr/main/index.php ... &Itemid=27
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

I've done this before too - remember that your configuration table ends with a reserved block - if you don't build this in to your struct and then use sizeof(configurationtable) to work out where the first entry is, you'll read garbage data.

Cheers,
Adam
User avatar
Jef
Member
Member
Posts: 112
Joined: Tue Jan 08, 2008 7:25 am
Location: Greece
Contact:

Post by Jef »

AJ wrote:Hi,

I've done this before too - remember that your configuration table ends with a reserved block - if you don't build this in to your struct and then use sizeof(configurationtable) to work out where the first entry is, you'll read garbage data.

Cheers,
Adam
Of course there are structures.
And i have in mind that the structure will be used depends on entry type.
Keep coding...
...the sky is the limit

AsteriOS project: http://www.mindfields.gr/main/index.php ... &Itemid=27
User avatar
Jef
Member
Member
Posts: 112
Joined: Tue Jan 08, 2008 7:25 am
Location: Greece
Contact:

Post by Jef »

As i read at the tutorial ( http://www.osdever.net/tutorials/mp.php ),
the steps to startup the second cpu/core is to
1) enable the APIC module (bit 8 ) at Spurious-Interrupt Vector Register
2) setup the interrupt vector (delivered to the processor in the event of a spurious interrupt)
3) setup the Interrupt Command Register

at the 3rd step, i have two questions.
1) I must do the "Init" and then the "Startup" in delivery mode (?) or init is not needed?

The "startup" mode do the follow: Sends a Startup message to the processors listed in the destination field. The 8-bit vector information is the physical page number of the address for the processors to begin executing from.
So the destination field must have the APIC ID of the cpu that i try to startup

2) What is the physical page number ? It has to do with memory paging (that i am not use) or its too late and my brain does not works?

I suppose that the memory that will point, its the scheduler.

Does it need to be done all this before entering PMode ?
Keep coding...
...the sky is the limit

AsteriOS project: http://www.mindfields.gr/main/index.php ... &Itemid=27
Post Reply