SMP boot on qemu
Posted: Fri May 29, 2009 7:37 am
Hello,
I'm doing a graduation work about SMP scheduling, but first I need to boot the cpus.
I'm having problems with init startup startup sequence.
The first cpu seems to reboot on startup, and the second cpu doesnt boot.
I based my implementation on the Intel manual, and linux and BSD implementation.
Here's my code:
If anyone has a working example on qemu, I would really appreciate.
Thank you
I'm doing a graduation work about SMP scheduling, but first I need to boot the cpus.
I'm having problems with init startup startup sequence.
The first cpu seems to reboot on startup, and the second cpu doesnt boot.
I based my implementation on the Intel manual, and linux and BSD implementation.
Here's my code:
Code: Select all
void inline setup_sys_smp2(){
//while(1);
int i;
int max_cpu = 2, next_apic;
int vector;
//IA32::int_enable();
/*Road Map*/
kout << "Setup trampoline ... \n";
unsigned int trampoline_base = 0x00002000;
//memcpy((char *)trampoline_base, (char *) 0x7c00, 512);
//memcpy((void *)trampoline_base, trampoline_data, trampoline_end - trampoline_data);
memcpy((char *)trampoline_base, bin_data, bin_data_size);
vector = (trampoline_base >> 12);
kout << "Executing Waking up AP CPUS "; /*now we work with 2 cpus*/
apic_ids[0] = Apic::get_apic_id();
next_apic = apic_ids[0] + 1;
// build the apic_id table
for(i = 1; i < max_cpu; i++){
apic_ids[i] = next_apic++;
}
// start the ap protocol
for(i = 1; i < max_cpu; i++){
//int apic_id = apic_ids[i];
//int apic_id = Apic::get_apic_id();
//apic_id = apic_id;
int apic_id = 0x01;
Apic::apic_write(Apic::APIC_ICR_HIGH, apic_id << Apic::APIC_ID_SHIFT);
Apic::apic_write(Apic::APIC_ICR_LOW, Apic::APIC_TRIGMOD_LEVEL |
Apic::APIC_DELMODE_INIT | Apic::APIC_LEVEL_ASSERT );
Apic::apic_ipi_wait(-1);
Apic::pit_delay(10000);
Apic::pit_delay(10000);
//Apic::pit_delay(10000);
kout << " .. step 1\n";
//while(1);
Apic::apic_write(Apic::APIC_ICR_HIGH, apic_id << Apic::APIC_ID_SHIFT);
Apic::apic_write(Apic::APIC_ICR_LOW, Apic::APIC_TRIGMOD_LEVEL |
Apic::APIC_DELMODE_INIT);
//Apic::apic_write(Apic::APIC_ICR_LOW, 0x000C4500);
unsigned char *video = (unsigned char *)0xB8000;
*(video + (2 + 2 * 80) * 2) = 'T' & 0xFF;
Apic::apic_ipi_wait(-1);
//Apic::pit_delay(200);
Apic::pit_delay(10000);
Apic::pit_delay(10000);
//Apic::pit_delay(10000);
//while(1);
kout << " .. step 2\n";
// while(1);
Apic::apic_write(Apic::APIC_ICR_HIGH, apic_id << Apic::APIC_ID_SHIFT);
Apic::apic_write(Apic::APIC_ICR_LOW,Apic::APIC_TRIGMOD_EDGE | Apic::APIC_DELMODE_STARTUP | vector);
//Apic::apic_write(Apic::APIC_ICR_LOW, 0x000C4602 | vector);
//while(1);
Apic::apic_ipi_wait(-1);
*(video + (2 + 2 * 80) * 2) = 'U' & 0xFF;
//while(1);
//while(1);
Apic::pit_delay(200);
Apic::pit_delay(200);
Apic::pit_delay(200);
//while(1);
//{
*(video + (2 + 2 * 80) * 2) = 'U' & 0xFF;
//}
kout << " .. step 3\n";
//while(1);
Apic::apic_write(Apic::APIC_ICR_HIGH, apic_id << Apic::APIC_ID_SHIFT);
Apic::apic_write(Apic::APIC_ICR_LOW,Apic::APIC_TRIGMOD_EDGE | Apic::APIC_DELMODE_STARTUP | vector);
//Apic::apic_write(Apic::APIC_ICR_LOW, 0x000C4602 | vector);
Apic::apic_ipi_wait(-1);
*(video + (2 + 2 * 80) * 2) = 'K' & 0xFF;
Apic::pit_delay(200);
Apic::pit_delay(200);
//Apic::pit_delay(200);
kout << " .. step 4\n";
*(video + (2 + 2 * 80) * 2) = 'G' & 0xFF;
//while(1);
}
}
Thank you