feat: elf loading

This commit is contained in:
Zoe
2026-09-05 10:12:42 -05:00
parent b0f804e412
commit dd596d5378
21 changed files with 1000 additions and 313 deletions
-22
View File
@@ -183,28 +183,6 @@ impl LocalApic {
self.access.write(APIC_TIMER_INITIAL_COUNT, 0);
}
// pub fn delay_ticks(&self, count: u32) {
// if count == 0 {
// return;
// }
// APIC_TIMER_COUNT.store(0, Ordering::SeqCst);
// self.access
// .write(APIC_LVT_TIMER, APIC_TIMER_VECTOR as u64 | APIC_LVT_MASKED);
// self.access.write(APIC_TIMER_DIVIDE_CONFIG, 0b11);
// self.access.write(APIC_TIMER_INITIAL_COUNT, count as u64);
// self.access.write(APIC_LVT_TIMER, APIC_TIMER_VECTOR as u64);
// while APIC_TIMER_COUNT.load(Ordering::SeqCst) == 0 {
// unsafe {
// core::arch::asm!("sti", "hlt", "cli", options(nomem, nostack));
// }
// }
// self.stop_timer();
// }
pub fn id(&self) -> u32 {
self.id
}
-31
View File
@@ -132,37 +132,6 @@ pub fn init_interrupt_controller(
})
}
// #[derive(Debug)]
// pub enum TimerError {
// DurationOverflow,
// }
// impl InterruptController {
// pub fn delay(&self, duration: core::time::Duration) -> Result<(), TimerError> {
// let nanoseconds = duration.as_nanos();
// let ticks = (nanoseconds
// .checked_mul(self.local_timer_frequency as u128)
// .ok_or(TimerError::DurationOverflow)?
// + 999_999_999)
// / 1_000_000_000;
// if ticks == 0 {
// return Ok(());
// }
// let mut remaining = ticks;
// while remaining > 0 {
// let chunk = remaining.min(u32::MAX as u128) as u32;
// self.local_apic.delay_ticks(chunk);
// remaining -= chunk as u128;
// }
// Ok(())
// }
// }
/// # Safety
///
/// The caller must ensure:
+14 -41
View File
@@ -390,16 +390,6 @@ impl PageTable {
.ok_or(UnmapError::PageNotMapped)
}
fn discard_private_tables(
frames: &mut [Option<OwnedFrame>; MAX_INTERMEDIATE_LEVELS],
count: usize,
allocator: &mut FrameAllocator,
) {
for frame in frames[..count].iter_mut().rev().filter_map(Option::take) {
unsafe { allocator.dealloc(frame) };
}
}
fn apply_user_upgrades(
&mut self,
upgrades: &[Option<EntryLocation>; MAX_INTERMEDIATE_LEVELS],
@@ -509,34 +499,18 @@ impl PageTable {
let private_table_count = levels.len() - missing_depth;
let mut private_tables: [Option<OwnedFrame>; MAX_INTERMEDIATE_LEVELS] =
core::array::from_fn(|_| None);
let mut allocated_count = 0;
while allocated_count < private_table_count {
let private_frame = match allocator.alloc() {
Some(frame) => frame,
None => {
Self::discard_private_tables(&mut private_tables, allocated_count, allocator);
return Err(MapError::OutOfFrames);
}
};
if PageTableEntry::new_table(
private_frame.frame_address(),
permissions.user_accessible,
self.config,
)
.is_err()
{
unsafe { allocator.dealloc(private_frame) };
Self::discard_private_tables(&mut private_tables, allocated_count, allocator);
return Err(MapError::PhysicalAddressTooLarge);
}
private_tables[allocated_count] = Some(private_frame);
allocated_count += 1;
}
let prepare_result = (|| {
for slot in &mut private_tables[..private_table_count] {
let frame = allocator.alloc().ok_or(MapError::OutOfFrames)?;
let address = frame.frame_address();
// Track ownership before validation so every error uses the same cleanup.
*slot = Some(frame);
PageTableEntry::new_table(address, permissions.user_accessible, self.config)
.map_err(|_| MapError::PhysicalAddressTooLarge)?;
}
for private_index in 0..private_table_count {
let private_frame = private_tables[private_index]
.as_ref()
@@ -572,7 +546,9 @@ impl PageTable {
let publication_entry = match prepare_result {
Ok(entry) => entry,
Err(error) => {
Self::discard_private_tables(&mut private_tables, allocated_count, allocator);
for frame in private_tables.into_iter().rev().flatten() {
unsafe { allocator.dealloc(frame) };
}
return Err(error);
}
};
@@ -583,10 +559,7 @@ impl PageTable {
[publication_location.index] = publication_entry;
// The published page table now owns these frames.
for frame in private_tables[..allocated_count]
.iter_mut()
.flat_map(Option::take)
{
for frame in private_tables.into_iter().flatten() {
let _ = frame.into_raw();
}
+5 -9
View File
@@ -13,15 +13,11 @@ const BINARY: u8 = 0;
pub const PIT_FREQUENCY: u64 = 1_193_182;
pub const PIT_CALIBRATION_COUNT: u16 = u16::MAX;
pub struct Pit;
pub fn start_pit_one_shot(count: u16) {
unsafe {
write_u8(PIT_COMMAND, CHANNEL_0 | LOW_HIGH | MODE_0 | BINARY);
impl Pit {
pub fn start_one_shot(count: u16) {
unsafe {
write_u8(PIT_COMMAND, CHANNEL_0 | LOW_HIGH | MODE_0 | BINARY);
write_u8(PIT_CHANNEL_0, count as u8);
write_u8(PIT_CHANNEL_0, (count >> 8) as u8);
}
write_u8(PIT_CHANNEL_0, count as u8);
write_u8(PIT_CHANNEL_0, (count >> 8) as u8);
}
}
+2 -2
View File
@@ -7,7 +7,7 @@ use crate::{
io_apic::IoApic,
x86_64::{
interrupts::enable_interrupts,
pit::{PIT_CALIBRATION_COUNT, PIT_FREQUENCY, Pit},
pit::{PIT_CALIBRATION_COUNT, PIT_FREQUENCY, start_pit_one_shot},
},
},
platform::acpi::IsaIrqRoute,
@@ -37,7 +37,7 @@ pub fn calibrate_local_apic(
.map_err(|_| TimerCalibrationError::IoApicNotHandled)?;
local_apic.start_calibration_counter();
Pit::start_one_shot(PIT_CALIBRATION_COUNT);
start_pit_one_shot(PIT_CALIBRATION_COUNT);
enable_interrupts();