feat: elf loading
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user