|
@@ -1,23 +1,18 @@
|
|
|
-use super::{GDT_OBJECT, TSS_OBJECT};
|
|
|
+use super::{interrupt::setup_idt, GDT_OBJECT, TSS_OBJECT};
|
|
|
use crate::{
|
|
|
kernel::{
|
|
|
- mem::{
|
|
|
- paging::Page,
|
|
|
- phys::{CachedPP, PhysPtr as _},
|
|
|
- },
|
|
|
+ arch::interrupt::APIC_BASE,
|
|
|
+ mem::{paging::Page, phys::PhysPtr as _},
|
|
|
smp,
|
|
|
},
|
|
|
println_debug, println_info,
|
|
|
sync::preempt,
|
|
|
};
|
|
|
use arch::{
|
|
|
- task::{pause, rdmsr},
|
|
|
+ task::pause,
|
|
|
x86_64::{gdt::GDT, task::TSS},
|
|
|
};
|
|
|
-use core::{
|
|
|
- arch::asm,
|
|
|
- sync::atomic::{AtomicU32, AtomicUsize, Ordering},
|
|
|
-};
|
|
|
+use core::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
|
|
|
|
|
|
unsafe fn init_gdt_tss_thiscpu() {
|
|
|
preempt::disable();
|
|
@@ -41,12 +36,31 @@ unsafe fn init_gdt_tss_thiscpu() {
|
|
|
preempt::enable();
|
|
|
}
|
|
|
|
|
|
+/// Initialization routine for all CPUs.
|
|
|
pub unsafe fn init_cpu() {
|
|
|
arch::x86_64::io::enable_sse();
|
|
|
|
|
|
let area = smp::alloc_percpu_area();
|
|
|
smp::set_percpu_area(area);
|
|
|
init_gdt_tss_thiscpu();
|
|
|
+
|
|
|
+ setup_idt();
|
|
|
+
|
|
|
+ APIC_BASE.spurious().write(0x1ff);
|
|
|
+ APIC_BASE.task_priority().write(0);
|
|
|
+ APIC_BASE.timer_divide().write(0x3); // Divide by 16
|
|
|
+ APIC_BASE.timer_register().write(0x20040);
|
|
|
+
|
|
|
+ // TODO: Get the bus frequency from...?
|
|
|
+ let freq = 800;
|
|
|
+ let count = freq * 1_000_000 / 16 / 100;
|
|
|
+ APIC_BASE.timer_initial_count().write(count as u32);
|
|
|
+
|
|
|
+ let cpu = CPU_COUNT.fetch_add(1, Ordering::Relaxed);
|
|
|
+ if cpu != 0 {
|
|
|
+ // Application processor
|
|
|
+ println_debug!("AP{} started", cpu);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
#[no_mangle]
|
|
@@ -54,15 +68,11 @@ pub static BOOT_SEMAPHORE: AtomicU32 = AtomicU32::new(0);
|
|
|
#[no_mangle]
|
|
|
pub static BOOT_STACK: AtomicUsize = AtomicUsize::new(0);
|
|
|
|
|
|
-pub static AP_COUNT: AtomicUsize = AtomicUsize::new(0);
|
|
|
+pub static CPU_COUNT: AtomicUsize = AtomicUsize::new(0);
|
|
|
|
|
|
#[no_mangle]
|
|
|
pub unsafe extern "C" fn ap_entry(_stack_start: u64) {
|
|
|
init_cpu();
|
|
|
- let cpuid = AP_COUNT.fetch_add(1, Ordering::Release);
|
|
|
- println_debug!("AP{} started", cpuid);
|
|
|
-
|
|
|
- // TODO!!!!!: Set up LAPIC and timer.
|
|
|
|
|
|
// TODO!!!!!: Set up idle task.
|
|
|
|
|
@@ -72,32 +82,19 @@ pub unsafe extern "C" fn ap_entry(_stack_start: u64) {
|
|
|
}
|
|
|
|
|
|
pub unsafe fn bootstrap_cpus() {
|
|
|
- let apic_base = rdmsr(0x1b);
|
|
|
- assert_eq!(apic_base & 0x800, 0x800, "LAPIC not enabled");
|
|
|
- assert_eq!(apic_base & 0x100, 0x100, "Is not bootstrap processor");
|
|
|
-
|
|
|
- let apic_base = apic_base & !0xfff;
|
|
|
- println_debug!("IA32_APIC_BASE: {apic_base:#x}");
|
|
|
-
|
|
|
- let apic_base = CachedPP::new(apic_base as usize);
|
|
|
- let spurious = apic_base.offset(0xf0).as_ptr::<u32>();
|
|
|
- let icr = apic_base.offset(0x300).as_ptr::<u32>();
|
|
|
+ let icr = APIC_BASE.interrupt_command();
|
|
|
|
|
|
- println_debug!("SPURIOUS: {:#x}", unsafe { spurious.read() });
|
|
|
-
|
|
|
- unsafe { icr.write_volatile(0xc4500) };
|
|
|
-
|
|
|
- while unsafe { icr.read_volatile() } & 0x1000 != 0 {
|
|
|
+ icr.write(0xc4500);
|
|
|
+ while icr.read() & 0x1000 != 0 {
|
|
|
pause();
|
|
|
}
|
|
|
|
|
|
- unsafe { icr.write_volatile(0xc4601) };
|
|
|
-
|
|
|
- while unsafe { icr.read_volatile() } & 0x1000 != 0 {
|
|
|
+ icr.write(0xc4601);
|
|
|
+ while icr.read() & 0x1000 != 0 {
|
|
|
pause();
|
|
|
}
|
|
|
|
|
|
- while AP_COUNT.load(Ordering::Acquire) != 3 {
|
|
|
+ while CPU_COUNT.load(Ordering::Acquire) != 3 {
|
|
|
if BOOT_STACK.load(Ordering::Acquire) == 0 {
|
|
|
let page = Page::alloc_many(9);
|
|
|
let stack_start = page.as_cached().as_ptr::<()>() as usize;
|