Only one AP can start at a time

This commit is contained in:
Jeremy Soller 2016-09-01 17:08:43 -06:00
parent c74abfc8a7
commit f14569e313
4 changed files with 23 additions and 12 deletions

View file

@ -2,11 +2,12 @@
//! Code to parse the ACPI tables //! Code to parse the ACPI tables
use core::intrinsics::{atomic_load, atomic_store}; use core::intrinsics::{atomic_load, atomic_store};
use core::sync::atomic::Ordering;
use interrupt; use interrupt;
use memory::{allocate_frame, Frame}; use memory::{allocate_frame, Frame};
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress}; use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
use start::kstart_ap; use start::{kstart_ap, AP_READY};
use self::local_apic::{LocalApic, LocalApicIcr}; use self::local_apic::{LocalApic, LocalApicIcr};
use self::madt::{Madt, MadtEntry}; use self::madt::{Madt, MadtEntry};
@ -40,10 +41,10 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
for madt_entry in madt.iter() { for madt_entry in madt.iter() {
println!(" {:?}", madt_entry); println!(" {:?}", madt_entry);
match madt_entry { match madt_entry {
MadtEntry::LocalApic(asp_local_apic) => if asp_local_apic.id == me { MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me {
println!(" This is my local APIC"); println!(" This is my local APIC");
} else { } else {
if asp_local_apic.flags & 1 == 1 { if ap_local_apic.flags & 1 == 1 {
// Map trampoline // Map trampoline
{ {
if active_table.translate_page(Page::containing_address(VirtualAddress::new(TRAMPOLINE))).is_none() { if active_table.translate_page(Page::containing_address(VirtualAddress::new(TRAMPOLINE))).is_none() {
@ -69,28 +70,33 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
unsafe { atomic_store(ap_stack_start, stack_start as u64) }; unsafe { atomic_store(ap_stack_start, stack_start as u64) };
unsafe { atomic_store(ap_stack_end, stack_end as u64) }; unsafe { atomic_store(ap_stack_end, stack_end as u64) };
unsafe { atomic_store(ap_code, kstart_ap as u64) }; unsafe { atomic_store(ap_code, kstart_ap as u64) };
AP_READY.store(false, Ordering::SeqCst);
// Send INIT IPI // Send INIT IPI
{ {
let icr = 0x00004500 | (asp_local_apic.id as u64) << 32; let icr = 0x00004500 | (ap_local_apic.id as u64) << 32;
println!(" Sending IPI to {}: {:>016X} {:?}", asp_local_apic.id, icr, LocalApicIcr::from_bits(icr)); println!(" Sending IPI to {}: {:>016X} {:?}", ap_local_apic.id, icr, LocalApicIcr::from_bits(icr));
local_apic.set_icr(icr); local_apic.set_icr(icr);
} }
// Send START IPI // Send START IPI
{ {
let ap_segment = (AP_STARTUP >> 12) & 0xFF; let ap_segment = (AP_STARTUP >> 12) & 0xFF;
let icr = 0x00004600 | ((asp_local_apic.id as u64) << 32) | ap_segment as u64; //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there let icr = 0x00004600 | ((ap_local_apic.id as u64) << 32) | ap_segment as u64; //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there
println!(" Sending SIPI to {}: {:>016X} {:?}", asp_local_apic.id, icr, LocalApicIcr::from_bits(icr)); println!(" Sending SIPI to {}: {:>016X} {:?}", ap_local_apic.id, icr, LocalApicIcr::from_bits(icr));
local_apic.set_icr(icr); local_apic.set_icr(icr);
} }
// Wait for trampoline ready // Wait for trampoline ready
println!(" Waiting for AP {}", asp_local_apic.id); println!(" Waiting for AP {}", ap_local_apic.id);
while unsafe { atomic_load(ap_ready) } == 0 { while unsafe { atomic_load(ap_ready) } == 0 {
interrupt::pause(); interrupt::pause();
} }
println!(" AP {} is ready!", asp_local_apic.id); println!(" AP {} is trampolined!", ap_local_apic.id);
while ! AP_READY.load(Ordering::SeqCst) {
interrupt::pause();
}
println!(" AP {} is ready!", ap_local_apic.id);
} else { } else {
println!(" CPU Disabled"); println!(" CPU Disabled");
} }

View file

@ -24,7 +24,8 @@ extern crate x86;
macro_rules! print { macro_rules! print {
($($arg:tt)*) => ({ ($($arg:tt)*) => ({
use core::fmt::Write; use core::fmt::Write;
let _ = write!($crate::console::CONSOLE.lock(), $($arg)*); let mut console = $crate::console::CONSOLE.lock();
let _ = write!(console, $($arg)*);
}); });
} }

View file

@ -92,7 +92,7 @@ pub unsafe fn init(stack_start: usize, stack_end: usize) -> ActivePageTable {
let uncacheable = 0; let uncacheable = 0;
let write_combining = 1; let write_combining = 1;
let write_through = 4; let write_through = 4;
let write_protected = 5; //let write_protected = 5;
let write_back = 6; let write_back = 6;
let uncached = 7; let uncached = 7;

View file

@ -27,6 +27,7 @@ static mut TBSS_TEST_ZERO: usize = 0;
static mut TDATA_TEST_NONZERO: usize = 0xFFFFFFFFFFFFFFFF; static mut TDATA_TEST_NONZERO: usize = 0xFFFFFFFFFFFFFFFF;
static AP_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; static AP_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
pub static AP_READY: AtomicBool = ATOMIC_BOOL_INIT;
static BSP_READY: AtomicBool = ATOMIC_BOOL_INIT; static BSP_READY: AtomicBool = ATOMIC_BOOL_INIT;
static HEAP_FRAME: AtomicUsize = ATOMIC_USIZE_INIT; static HEAP_FRAME: AtomicUsize = ATOMIC_USIZE_INIT;
@ -94,6 +95,7 @@ pub unsafe extern fn kstart() -> ! {
// Reset AP variables // Reset AP variables
AP_COUNT.store(0, Ordering::SeqCst); AP_COUNT.store(0, Ordering::SeqCst);
AP_READY.store(false, Ordering::SeqCst);
BSP_READY.store(false, Ordering::SeqCst); BSP_READY.store(false, Ordering::SeqCst);
HEAP_FRAME.store(0, Ordering::SeqCst); HEAP_FRAME.store(0, Ordering::SeqCst);
@ -127,7 +129,7 @@ pub unsafe extern fn kstart() -> ! {
device::init(&mut active_table); device::init(&mut active_table);
// Read ACPI tables, starts APs // Read ACPI tables, starts APs
// acpi::init(&mut active_table); acpi::init(&mut active_table);
BSP_READY.store(true, Ordering::SeqCst); BSP_READY.store(true, Ordering::SeqCst);
} }
@ -187,6 +189,8 @@ pub unsafe extern fn kstart_ap(stack_start: usize, stack_end: usize) -> ! {
// Init devices for AP // Init devices for AP
device::init_ap(&mut active_table); device::init_ap(&mut active_table);
AP_READY.store(true, Ordering::SeqCst);
} }
let ap_number = AP_COUNT.fetch_add(1, Ordering::SeqCst); let ap_number = AP_COUNT.fetch_add(1, Ordering::SeqCst);