From 9f189efa8bca085bb1252d5b28a02cff70081d3f Mon Sep 17 00:00:00 2001 From: Nick Shipp Date: Sun, 30 Sep 2018 17:52:49 -0400 Subject: Some cleanup + bump to Rust 2018 --- bunny/src/main.rs | 111 ++++++++++++++++-------------------------------------- 1 file changed, 32 insertions(+), 79 deletions(-) (limited to 'bunny/src/main.rs') 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::(io::PIC1_DATA, io::PIC_DISABLE); io::out::(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 { -- cgit v1.2.3-54-g00ecf