aboutsummaryrefslogtreecommitdiff
path: root/bunny/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'bunny/src/main.rs')
-rw-r--r--bunny/src/main.rs111
1 files changed, 32 insertions, 79 deletions
diff --git a/bunny/src/main.rs b/bunny/src/main.rs
index 21fa9cc..e7f5c70 100644
--- a/bunny/src/main.rs
+++ b/bunny/src/main.rs
@@ -21,40 +21,14 @@ use core::slice;
use efi::types::Handle;
use efi::SystemTable;
use x86_64::instructions::interrupts;
-use x86_64::registers::control;
-use interrupt::*;
-use lapic::*;
-use inttraits::*;
+use self::interrupt::*;
+use self::lapic::*;
+use self::inttraits::*;
-static mut SYSTEM_TABLE: *const SystemTable = 0 as *const SystemTable;
-
-fn serial_poke() {
- const PORT: u16 = 0x3f8;
-
- unsafe {
- asm!("out dx, al" :: "{dx}"(PORT+1), "{al}"(0x00) :: "intel", "volatile");
- asm!("out dx, al" :: "{dx}"(PORT+3), "{al}"(0x80) :: "intel", "volatile");
- asm!("out dx, al" :: "{dx}"(PORT+0), "{al}"(0x03) :: "intel", "volatile");
- asm!("out dx, al" :: "{dx}"(PORT+1), "{al}"(0x00) :: "intel", "volatile");
- asm!("out dx, al" :: "{dx}"(PORT+3), "{al}"(0x03) :: "intel", "volatile");
- asm!("out dx, al" :: "{dx}"(PORT+2), "{al}"(0xc7) :: "intel", "volatile");
- asm!("out dx, al" :: "{dx}"(PORT+4), "{al}"(0x0b) :: "intel", "volatile");
- }
+const NUM_CORES: u8 = 4;
- for c in b"###*-*-*-*-*-*-*-*-*-*-###\r\n\r\n" {
- let mut status: u8 = 0;
- while status & 0x20 == 0 {
- unsafe {
- asm!("in al, dx" : "={al}"(status) : "{dx}"(PORT+5) :: "intel", "volatile");
- }
- }
-
- unsafe {
- asm!("out dx, al" :: "{dx}"(PORT), "{al}"(c) :: "intel", "volatile");
- }
- }
-}
+static mut SYSTEM_TABLE: *const SystemTable = 0 as *const SystemTable;
#[allow(improper_ctypes)]
extern "C" {
@@ -62,6 +36,7 @@ extern "C" {
fn rdtsc() -> i64;
}
+/* Awful way of busy-waiting some constant-ish number of cycle-ish intervals */
fn busy() {
let init = unsafe { rdtsc() } as u64;
let future = init + 1_000_000;
@@ -91,79 +66,63 @@ pub extern fn efi_main(_handle: Handle, systab: &SystemTable) -> ! {
println!("FUZZY BUNNIES {}", env!("CARGO_PKG_VERSION"));
println!("efi_main @ 0x{:x}", efi_main as *const u8 as usize);
- dprintln!("CR0: {:x?}, CR3: {:x?}", control::Cr0::read(), control::Cr3::read());
/* Set up basic exception handlers */
register_handlers();
- // serial_poke();
-
- // unsafe { asm!("hlt"); }
- // let _mapkey = uefi::dump_mem_map().expect("Unable to read UEFI memory map");
-
+ /* Set up AP bootstrap (real->long transition) code */
let code = include_bytes!(concat!(env!("OUT_DIR"), "/ap_boot.bin"));
let dest = unsafe {
+ /* Copy the code to somewhere in the first 1MB of memory */
slice::from_raw_parts_mut(0x8000 as *mut u8, code.len())
};
- let idtr = interrupt::descriptor();
- dprintln!("copy {} bytes from 0x{:x} to 0x{:x}",
- code.len(),
- code.as_ptr() as usize,
- dest.as_ptr() as usize);
-
dest.copy_from_slice(code);
+ /* Read initial CR3 register to pass off to other cores */
let cr3_val: u64;
unsafe {
asm!("mov $0, cr3" : "=r" (cr3_val) ::: "intel");
}
- dest[code.len()-14..code.len()-10].copy_from_slice(&(cr3_val as u32).as_bytes());
- dest[code.len()-10..code.len()-8].copy_from_slice(&idtr.0.as_bytes());
- dest[code.len()-8..].copy_from_slice(&idtr.1.as_bytes());
- dprintln!("patched: {:x?}", &dest[code.len()-14..]);
+ let idtr = interrupt::descriptor();
+
+ /* Fill in CR3 (u32) and IDTR (u16; u64) at the end of the bootstrap code */
+ dest[code.len()-14..code.len()-10]
+ .copy_from_slice(&(cr3_val as u32).as_bytes());
+ dest[code.len()-10..code.len()-8]
+ .copy_from_slice(&idtr.0.as_bytes());
+ dest[code.len()-8..]
+ .copy_from_slice(&idtr.1.as_bytes());
+
+ /* Initialize AP mutex (unlocked) and count (0) */
unsafe {
- ptr::write_volatile(0x6000 as *mut u64, 0);
- ptr::write_volatile(0x6008 as *mut u64, 0);
- ptr::write_volatile(0x600c as *mut u64, 0);
- ptr::write_volatile(0x6010 as *mut u64, 0);
- asm!("mfence; lfence");
+ ptr::write_volatile(0x6000 as *mut u16, 0);
}
- /* Disable the PICs to prepare for APIC/IOAPIC */
+ /* Disable the PICs to prepare for other cores */
unsafe {
io::out::<u8>(io::PIC1_DATA, io::PIC_DISABLE);
io::out::<u8>(io::PIC2_DATA, io::PIC_DISABLE);
}
let mut bsp_apic = LocalApic::init();
- println!("APIC ID: {}, VERSION: {}", bsp_apic.id(), bsp_apic.version());
-
bsp_apic.enable();
- dprintln!("APIC enabled");
-
- /* INIT-SIPI-SIPI */
- dprintln!("INIT ASSERT");
+ /* INIT-SIPI-SIPI: Brings up other cores */
bsp_apic.send_ipi(IpiDestination::AllButMe,
IpiTriggerMode::Edge,
IpiLevel::Assert,
IpiDeliveryMode::Init,
0);
busy();
- // println!("INIT LEVEL DEASSERT");
- // bsp_apic.send_ipi(IpiDestination::AllButMe,
- // IpiTriggerMode::Level,
- // IpiLevel::Deassert,
- // IpiDeliveryMode::Init,
- // 0);
- // busy();
- println!("SIPI spam");
+
+ /*
+ * Wait for cores to get themselves figured out, retrying the SIPI
+ * broadcast until everyone is accounted for.
+ */
let mut n_aps: u8 = 0;
- // let mut ap_lock: u8;
- while n_aps < 3 {
- dprintln!("SIPI");
+ while n_aps < NUM_CORES-1 {
bsp_apic.send_ipi(IpiDestination::AllButMe,
IpiTriggerMode::Edge,
IpiLevel::Assert,
@@ -171,18 +130,12 @@ pub extern fn efi_main(_handle: Handle, systab: &SystemTable) -> ! {
0x08);
busy();
- unsafe { asm!("mfence; lfence"); }
-
- // ap_lock = unsafe { ptr::read_volatile(0x6000 as *const u8) };
n_aps = unsafe { ptr::read_volatile(0x6001 as *const u8) };
-
- // println!("ap_lock: {}, n_aps: {}", ap_lock, n_aps);
- // {
- // let ap_stats = unsafe { slice::from_raw_parts(0x6002 as *const u8, n_aps as usize) };
- // println!("stat: {:x?}", ap_stats);
- // }
}
+ dprintln!("All cores online");
+
+ /* All good, turn interrupts back on and idle */
interrupts::enable();
loop {