Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/mp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,13 @@ pub const MPLINTR: u8 = 0x04; // One per system interrupt source
pub struct MPWriteOnce {
pub lapic_base: OnceCell<*mut u32>,
pub ioapic_id: OnceCell<u8>,
pub cpus: OnceCell<[Cpu; NCPU]>
pub cpus: OnceCell<[Cpu; NCPU]>,
pub ncpu: OnceCell<usize>,
}

unsafe impl Sync for MPWriteOnce {}

pub static MP_ONCE: MPWriteOnce = MPWriteOnce { lapic_base: OnceCell::new(), ioapic_id: OnceCell::new(), cpus: OnceCell::new() };
pub static MP_ONCE: MPWriteOnce = MPWriteOnce { lapic_base: OnceCell::new(), ioapic_id: OnceCell::new(), cpus: OnceCell::new(), ncpu: OnceCell::new() };

/// Calculates sum of bytes in a memory region
///
Expand Down Expand Up @@ -141,7 +142,7 @@ fn mpsearch() -> Option<*mut Mp> {
} else {
let p = unsafe {(((*bda.add(0x14) as u32) << 8) | (*bda.add(0x13) as u32)) * 1024};
mp = mpsearch1(p - 1024, 1024);
if !mp.is_some() {
if mp.is_some() {
return mp;
}
}
Expand Down Expand Up @@ -233,6 +234,7 @@ pub fn mpinit() {
panic!("Didn't find a suitable machine");
}
MP_ONCE.cpus.set(cpus);
MP_ONCE.ncpu.set(ncpu);

if mp.imcrp != 0 {
// Bochs doesn't support IMCR, so this doesn't run on Bochs.
Expand Down
30 changes: 30 additions & 0 deletions src/proc.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
use crate::lapic::lapicid;
use crate::mp::MP_ONCE;
use crate::x86::readeflags;

const FL_IF: u32 = 0x00000200; // Interrupt flag

#[derive(Debug, Clone, Copy)]
pub struct Cpu {
pub apicid: u8, // Local APIC ID
Expand All @@ -7,4 +13,28 @@ impl Cpu {
pub const fn new() -> Self {
Self { apicid: 0 }
}
}

// Must be called with interrupts disabled to avoid the caller being
// rescheduled between reading lapicid and running through the loop.
pub fn mycpu() -> &'static Cpu {
if readeflags() & FL_IF != 0 {
panic!("mycpu called with interrupts enabled");
}
let apicid = lapicid() as u8;
let cpus = MP_ONCE.cpus.get().unwrap();
let ncpu = *MP_ONCE.ncpu.get().unwrap();
for i in 0..ncpu {
if cpus[i].apicid == apicid {
return &cpus[i];
}
}
panic!("unknown apicid");
}

// Must be called with interrupts disabled
pub fn cpuid() -> usize {
let cpu = mycpu() as *const Cpu;
let cpus = MP_ONCE.cpus.get().unwrap().as_ptr();
unsafe { cpu.offset_from(cpus) as usize }
}
8 changes: 8 additions & 0 deletions src/uart.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use crate::x86::{outb, inb};
use core::sync::atomic::{AtomicBool, Ordering};

const COM1: u16 = 0x3F8; // COM1 port address

static UART: AtomicBool = AtomicBool::new(false);

pub fn uartinit() {
// Turn off the FIFO.
outb(COM1 + 2, 0);
Expand All @@ -18,13 +22,17 @@ pub fn uartinit() {
if inb(COM1 + 5) == 0xFF {
return;
}
UART.store(true, Ordering::Relaxed);
// Announce that the UART is active.
for p in "xv6...\n".chars() {
uartputc(p);
}
}

pub fn uartputc(c: char) {
if !UART.load(Ordering::Relaxed) {
return;
}
for _ in 0..128 {
if inb(COM1 + 5) & 0x20 != 0 {
break;
Expand Down
13 changes: 13 additions & 0 deletions src/x86.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
use core::arch::asm;

pub fn readeflags() -> u32 {
let eflags: u32;
unsafe {
asm!(
"pushfd",
"pop {0:e}",
out(reg) eflags,
options(nomem, nostack)
);
}
eflags
}

pub fn inb(port: u16) -> u8 {
let result: u8;
unsafe {
Expand Down