From 6f6f8f739168329310db3c155977d47eb9c3a5a6 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 29 Apr 2017 12:52:12 +0200 Subject: [PATCH] Check multicore code even if disabled --- Cargo.toml | 1 + src/acpi/mod.rs | 178 ++++++++++++++++++++++++------------------------ src/lib.rs | 34 +++++---- 3 files changed, 110 insertions(+), 103 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a6b285a..a364666 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,3 +27,4 @@ default-features = false [features] default = [] live = [] +multi_core = [] \ No newline at end of file diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 751044a..4fe234a 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -76,7 +76,7 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { } else if let Some(madt) = Madt::new(sdt) { println!(": {:>08X}: {}", madt.local_address, madt.flags); - let mut local_apic = unsafe { &mut LOCAL_APIC }; + let local_apic = unsafe { &mut LOCAL_APIC }; let me = local_apic.id() as u8; @@ -86,98 +86,98 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { println!(" XAPIC {}: {:>08X}", me, local_apic.address); } - /* - let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); - let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); + if cfg!(feature = "multi_core"){ + let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); + let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); - // Map trampoline - let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); - result.flush(active_table); + // Map trampoline + let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); + result.flush(active_table); - for madt_entry in madt.iter() { - println!(" {:?}", madt_entry); - match madt_entry { - MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me { - println!(" This is my local APIC"); - } else { - if ap_local_apic.flags & 1 == 1 { - // Increase CPU ID - CPU_COUNT.fetch_add(1, Ordering::SeqCst); - - // Allocate a stack - let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET; - let stack_end = stack_start + 64 * 4096; - - let ap_ready = TRAMPOLINE as *mut u64; - let ap_cpu_id = unsafe { ap_ready.offset(1) }; - let ap_page_table = unsafe { ap_ready.offset(2) }; - let ap_stack_start = unsafe { ap_ready.offset(3) }; - let ap_stack_end = unsafe { ap_ready.offset(4) }; - let ap_code = unsafe { ap_ready.offset(5) }; - - // Set the ap_ready to 0, volatile - unsafe { atomic_store(ap_ready, 0) }; - unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) }; - unsafe { atomic_store(ap_page_table, active_table.address() 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_code, kstart_ap as u64) }; - AP_READY.store(false, Ordering::SeqCst); - - print!(" AP {}:", ap_local_apic.id); - - // Send INIT IPI - { - let mut icr = 0x4500; - if local_apic.x2 { - icr |= (ap_local_apic.id as u64) << 32; - } else { - icr |= (ap_local_apic.id as u64) << 56; - } - print!(" IPI..."); - local_apic.set_icr(icr); - } - - // Send START IPI - { - //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there - let ap_segment = (AP_STARTUP >> 12) & 0xFF; - let mut icr = 0x4600 | ap_segment as u64; - - if local_apic.x2 { - icr |= (ap_local_apic.id as u64) << 32; - } else { - icr |= (ap_local_apic.id as u64) << 56; - } - - print!(" SIPI..."); - local_apic.set_icr(icr); - } - - // Wait for trampoline ready - print!(" Wait..."); - while unsafe { atomic_load(ap_ready) } == 0 { - interrupt::pause(); - } - print!(" Trampoline..."); - while ! AP_READY.load(Ordering::SeqCst) { - interrupt::pause(); - } - println!(" Ready"); - - active_table.flush_all(); + for madt_entry in madt.iter() { + println!(" {:?}", madt_entry); + match madt_entry { + MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me { + println!(" This is my local APIC"); } else { - println!(" CPU Disabled"); - } - }, - _ => () - } - } + if ap_local_apic.flags & 1 == 1 { + // Increase CPU ID + CPU_COUNT.fetch_add(1, Ordering::SeqCst); - // Unmap trampoline - let (result, _frame) = active_table.unmap_return(trampoline_page, false); - result.flush(active_table); - */ + // Allocate a stack + let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET; + let stack_end = stack_start + 64 * 4096; + + let ap_ready = TRAMPOLINE as *mut u64; + let ap_cpu_id = unsafe { ap_ready.offset(1) }; + let ap_page_table = unsafe { ap_ready.offset(2) }; + let ap_stack_start = unsafe { ap_ready.offset(3) }; + let ap_stack_end = unsafe { ap_ready.offset(4) }; + let ap_code = unsafe { ap_ready.offset(5) }; + + // Set the ap_ready to 0, volatile + unsafe { atomic_store(ap_ready, 0) }; + unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) }; + unsafe { atomic_store(ap_page_table, active_table.address() 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_code, kstart_ap as u64) }; + AP_READY.store(false, Ordering::SeqCst); + + print!(" AP {}:", ap_local_apic.id); + + // Send INIT IPI + { + let mut icr = 0x4500; + if local_apic.x2 { + icr |= (ap_local_apic.id as u64) << 32; + } else { + icr |= (ap_local_apic.id as u64) << 56; + } + print!(" IPI..."); + local_apic.set_icr(icr); + } + + // Send START IPI + { + //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there + let ap_segment = (AP_STARTUP >> 12) & 0xFF; + let mut icr = 0x4600 | ap_segment as u64; + + if local_apic.x2 { + icr |= (ap_local_apic.id as u64) << 32; + } else { + icr |= (ap_local_apic.id as u64) << 56; + } + + print!(" SIPI..."); + local_apic.set_icr(icr); + } + + // Wait for trampoline ready + print!(" Wait..."); + while unsafe { atomic_load(ap_ready) } == 0 { + interrupt::pause(); + } + print!(" Trampoline..."); + while ! AP_READY.load(Ordering::SeqCst) { + interrupt::pause(); + } + println!(" Ready"); + + active_table.flush_all(); + } else { + println!(" CPU Disabled"); + } + }, + _ => () + } + } + + // Unmap trampoline + let (result, _frame) = active_table.unmap_return(trampoline_page, false); + result.flush(active_table); + } } else if let Some(dmar) = Dmar::new(sdt) { println!(": {}: {}", dmar.addr_width, dmar.flags); diff --git a/src/lib.rs b/src/lib.rs index f200492..678d8be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -102,6 +102,9 @@ pub mod time; #[cfg(test)] pub mod tests; +#[cfg(feature = "multi_core")] +static MULTI_CORE_IS_NOT_SUPPORTED_AT_THE_MOMENT: u8 = (); + /// A unique number that identifies the current CPU - used for scheduling #[thread_local] static CPU_ID: AtomicUsize = ATOMIC_USIZE_INIT; @@ -171,6 +174,7 @@ pub extern fn kmain(cpus: usize) { /// This is the main kernel entry point for secondary CPUs #[no_mangle] +#[allow(unreachable_code, unused_variables)] pub extern fn kmain_ap(id: usize) { loop { unsafe { @@ -178,26 +182,28 @@ pub extern fn kmain_ap(id: usize) { interrupt::halt(); } } - /* - CPU_ID.store(id, Ordering::SeqCst); + + if cfg!(feature = "multi_core"){ + CPU_ID.store(id, Ordering::SeqCst); - context::init(); + context::init(); - let pid = syscall::getpid(); - println!("AP {}: {:?}", id, pid); + let pid = syscall::getpid(); + println!("AP {}: {:?}", id, pid); - loop { - unsafe { - interrupt::disable(); - if context::switch() { - interrupt::enable_and_nop(); - } else { - // Enable interrupts, then halt CPU (to save power) until the next interrupt is actually fired. - interrupt::enable_and_halt(); + loop { + unsafe { + interrupt::disable(); + if context::switch() { + interrupt::enable_and_nop(); + } else { + // Enable interrupts, then halt CPU (to save power) until the next interrupt is actually fired. + interrupt::enable_and_halt(); + } } } } - */ + } /// Allow exception handlers to send signal to arch-independant kernel