Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add more dump commands #375

Merged
merged 7 commits into from
Dec 1, 2022
Merged
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
11 changes: 10 additions & 1 deletion bitfield/src/bitfield.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,16 @@ macro_rules! bitfield {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut dbg = f.debug_struct(stringify!($Name));
$(
dbg.field(stringify!($Field), &self.get(Self::$Field));
{
// skip reserved fields (names starting with `_`).
//
// NOTE(eliza): i hope this `if` gets const-folded...we
// could probably do this in a macro and guarantee that
// it happens at compile-time, but this is fine for now.
if !stringify!($Field).starts_with('_') {
dbg.field(stringify!($Field), &self.get(Self::$Field));
}
}
)+
dbg.finish()

Expand Down
4 changes: 4 additions & 0 deletions hal-x86_64/src/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ static INTERRUPT_CONTROLLER: InitOnce<Controller> = InitOnce::uninitialized();
impl Controller {
// const DEFAULT_IOAPIC_BASE_PADDR: u64 = 0xFEC00000;

pub fn idt() -> spin::MutexGuard<'static, idt::Idt> {
IDT.lock()
}

#[tracing::instrument(level = "info", name = "interrupt::Controller::init")]
pub fn init<H: Handlers<Registers>>() {
tracing::info!("intializing IDT...");
Expand Down
15 changes: 11 additions & 4 deletions hal-x86_64/src/interrupt/idt.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use super::apic::IoApic;
use crate::{cpu, segment};
use core::fmt;
use mycelium_util::bits;
use crate::{
cpu::{self, DescriptorTable},
segment,
};
use mycelium_util::{bits, fmt};

#[repr(C)]
#[repr(align(16))]
Expand Down Expand Up @@ -205,7 +207,12 @@ impl Idt {
impl fmt::Debug for Idt {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let Self { descriptors } = self;
f.debug_list().entries(descriptors[..].iter()).finish()
let descriptors = descriptors[..]
.iter()
.filter(|&descr| descr != &Descriptor::null())
.enumerate()
.map(|(i, descr)| (fmt::hex(i), descr));
f.debug_map().entries(descriptors).finish()
}
}

Expand Down
5 changes: 1 addition & 4 deletions src/arch/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod framebuf;
pub mod interrupt;
mod oops;
pub mod pci;
pub mod shell;
pub use self::{
boot::ArchInfo,
oops::{oops, Oops},
Expand All @@ -24,10 +25,6 @@ mod tests;

pub type MinPageSize = mm::size::Size4Kb;

pub fn tick_timer() {
interrupt::TIMER.advance_ticks(0);
}

#[cfg(target_os = "none")]
bootloader::entry_point!(arch_entry);

Expand Down
9 changes: 3 additions & 6 deletions src/arch/x86_64/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ pub fn enable_hardware_interrupts(acpi: Option<&acpi::InterruptModel>) {
controller
.start_periodic_timer(TIMER_INTERVAL)
.expect("10ms should be a reasonable interval for the PIT or local APIC timer...");
time::set_global_timer(&TIMER)
.expect("`enable_hardware_interrupts` should only be called once!");
tracing::info!(granularity = ?TIMER_INTERVAL, "global timer initialized")
}

Expand Down Expand Up @@ -54,10 +52,9 @@ static TSS: sync::Lazy<task::StateSegment> = sync::Lazy::new(|| {
tss
});

static GDT: sync::InitOnce<Gdt> = sync::InitOnce::uninitialized();
pub(in crate::arch) static GDT: sync::InitOnce<Gdt> = sync::InitOnce::uninitialized();

const TIMER_INTERVAL: time::Duration = time::Duration::from_millis(10);
pub(super) static TIMER: time::Timer = time::Timer::new(TIMER_INTERVAL);
pub const TIMER_INTERVAL: time::Duration = time::Duration::from_millis(10);

static TEST_INTERRUPT_WAS_FIRED: AtomicUsize = AtomicUsize::new(0);

Expand Down Expand Up @@ -96,7 +93,7 @@ impl hal_core::interrupt::Handlers<Registers> for InterruptHandlers {
}

fn timer_tick() {
TIMER.pend_ticks(1);
crate::rt::TIMER.pend_ticks(1);
}

fn ps2_keyboard(scancode: u8) {
Expand Down
20 changes: 20 additions & 0 deletions src/arch/x86_64/shell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::shell::{self, Command};

pub const DUMP_ARCH: Command = Command::new("arch")
.with_help("dump architecture-specific structures")
.with_subcommands(&[
Command::new("gdt")
.with_help("print the global descriptor table (GDT)")
.with_fn(|_| {
let gdt = super::interrupt::GDT.get();
tracing::info!(GDT = ?gdt);
Ok(())
}),
Command::new("idt")
.with_help("print the interrupt descriptor table (IDT)")
.with_fn(|_| {
let idt = super::interrupt::Controller::idt();
tracing::info!(IDT = ?idt);
Ok(())
}),
]);
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ pub fn kernel_start(bootinfo: impl BootInfo, archinfo: crate::arch::ArchInfo) ->
// tracing.
arch::init(&bootinfo, &archinfo);

// initialize the kernel runtime.
rt::init();

#[cfg(test)]
arch::run_tests();

Expand Down
36 changes: 33 additions & 3 deletions src/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ use core::{
future::Future,
sync::atomic::{AtomicBool, AtomicUsize, Ordering::*},
};
use maitake::scheduler::{self, StaticScheduler, Stealer};
use mycelium_util::sync::InitOnce;
use maitake::{
scheduler::{self, StaticScheduler, Stealer},
time,
};
use mycelium_util::{fmt, sync::InitOnce};
use rand::Rng;

pub use maitake::task::JoinHandle;
Expand Down Expand Up @@ -49,6 +52,8 @@ struct Runtime {
/// 512 CPU cores ought to be enough for anybody...
pub const MAX_CORES: usize = 512;

pub static TIMER: time::Timer = time::Timer::new(arch::interrupt::TIMER_INTERVAL);

static RUNTIME: Runtime = {
// This constant is used as an array initializer; the clippy warning that it
// contains interior mutability is not actually a problem here, since we
Expand Down Expand Up @@ -83,6 +88,20 @@ where
})
}

/// Initialize the kernel runtime.
pub fn init() {
time::set_global_timer(&TIMER).expect("`rt::init` should only be called once!");

tracing::info!("kernel runtime initialized");
}

pub const DUMP_RT: crate::shell::Command = crate::shell::Command::new("rt")
.with_help("print the kernel's async runtime")
.with_fn(|_| {
tracing::info!(runtime = ?RUNTIME);
Ok(())
});

static SCHEDULER: arch::LocalKey<Cell<Option<&'static StaticScheduler>>> =
arch::LocalKey::new(|| Cell::new(None));

Expand All @@ -108,7 +127,7 @@ impl Core {

// turn the timer wheel if it wasn't turned recently and no one else is
// holding a lock, ensuring any pending timer ticks are consumed.
arch::tick_timer();
TIMER.advance_ticks(0);

// if there are remaining tasks to poll, continue without stealing.
if tick.has_remaining {
Expand Down Expand Up @@ -269,3 +288,14 @@ impl Runtime {
self.cores[idx].try_get()?.try_steal().ok()
}
}

impl fmt::Debug for Runtime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let cores = self.active_cores();
f.debug_struct("Runtime")
.field("active_cores", &cores)
.field("cores", &&self.cores[..cores])
.field("injector", &self.injector)
.finish()
}
}
8 changes: 8 additions & 0 deletions src/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ pub fn eval(line: &str) {
Command::new("archinfo")
.with_help("print the architecture information structure")
.with_fn(|line| Err(Error::other(line, "not yet implemented"))),
Command::new("timer")
.with_help("print the timer wheel")
.with_fn(|_| {
tracing::info!(timer = ?crate::rt::TIMER);
Ok(())
}),
crate::rt::DUMP_RT,
crate::arch::shell::DUMP_ARCH,
Command::new("heap")
.with_help("print kernel heap statistics")
.with_fn(|_| {
Expand Down
20 changes: 9 additions & 11 deletions util/src/sync/once.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,10 @@ impl<T> InitOnce<T> {

impl<T: fmt::Debug> fmt::Debug for InitOnce<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct("InitOnce");
d.field("type", &any::type_name::<T>());
match self.state.load(Ordering::Acquire) {
INITIALIZED => d.field("value", self.get()).finish(),
INITIALIZING => d.field("value", &format_args!("<initializing>")).finish(),
UNINITIALIZED => d.field("value", &format_args!("<uninitialized>")).finish(),
INITIALIZED => self.get().fmt(f),
INITIALIZING => f.pad("<initializing>"),
UNINITIALIZED => f.pad("<uninitialized>"),
_state => unsafe {
unreachable_unchecked!("unexpected state value {}, this is a bug!", _state)
},
Expand Down Expand Up @@ -358,13 +356,13 @@ where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct("Lazy");
d.field("type", &any::type_name::<T>())
.field("initializer", &format_args!("..."));
match self.state.load(Ordering::Acquire) {
INITIALIZED => d.field("value", self.get_if_present().unwrap()).finish(),
INITIALIZING => d.field("value", &format_args!("<initializing>")).finish(),
UNINITIALIZED => d.field("value", &format_args!("<uninitialized>")).finish(),
INITIALIZED => self
.get_if_present()
.expect("if state is `INITIALIZED`, value should be present")
.fmt(f),
INITIALIZING => f.pad("<initializing>"),
UNINITIALIZED => f.pad("<uninitialized>"),
_state => unsafe {
unreachable_unchecked!("unexpected state value {}, this is a bug!", _state)
},
Expand Down