diff --git a/07_timestamps/README.md b/07_timestamps/README.md index a78e508b..c96a30e4 100644 --- a/07_timestamps/README.md +++ b/07_timestamps/README.md @@ -302,6 +302,15 @@ diff -uNr 06_uart_chainloader/src/_arch/aarch64/time.rs 07_timestamps/src/_arch/ +// Private Code +//-------------------------------------------------------------------------------------------------- + ++fn arch_timer_counter_frequency() -> NonZeroU32 { ++ // Read volatile is needed here to prevent the compiler from optimizing ++ // ARCH_TIMER_COUNTER_FREQUENCY away. ++ // ++ // This is safe, because all the safety requirements as stated in read_volatile()'s ++ // documentation are fulfilled. ++ unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } ++} ++ +impl GenericTimerCounterValue { + pub const MAX: Self = GenericTimerCounterValue(u64::MAX); +} @@ -320,13 +329,7 @@ diff -uNr 06_uart_chainloader/src/_arch/aarch64/time.rs 07_timestamps/src/_arch/ + return Duration::ZERO; + } + -+ // Read volatile is needed here to prevent the compiler from optimizing -+ // ARCH_TIMER_COUNTER_FREQUENCY away. -+ // -+ // This is safe, because all the safety requirements as stated in read_volatile()'s -+ // documentation are fulfilled. -+ let frequency: NonZeroU64 = -+ unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); ++ let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); + + // Div implementation for u64 cannot panic. + let secs = counter_value.0.div(frequency); @@ -361,10 +364,7 @@ diff -uNr 06_uart_chainloader/src/_arch/aarch64/time.rs 07_timestamps/src/_arch/ + return Err("Conversion error. Duration too big"); + } + -+ // This is safe, because all the safety requirements as stated in read_volatile()'s -+ // documentation are fulfilled. -+ let frequency: u128 = -+ unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; ++ let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; + let duration: u128 = duration.as_nanos(); + + // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/07_timestamps/src/_arch/aarch64/time.rs b/07_timestamps/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/07_timestamps/src/_arch/aarch64/time.rs +++ b/07_timestamps/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/08_hw_debug_JTAG/src/_arch/aarch64/time.rs b/08_hw_debug_JTAG/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/08_hw_debug_JTAG/src/_arch/aarch64/time.rs +++ b/08_hw_debug_JTAG/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/09_privilege_level/src/_arch/aarch64/time.rs b/09_privilege_level/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/09_privilege_level/src/_arch/aarch64/time.rs +++ b/09_privilege_level/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/time.rs b/10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/time.rs +++ b/10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/11_exceptions_part1_groundwork/src/_arch/aarch64/time.rs b/11_exceptions_part1_groundwork/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/11_exceptions_part1_groundwork/src/_arch/aarch64/time.rs +++ b/11_exceptions_part1_groundwork/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/12_integrated_testing/kernel/src/_arch/aarch64/time.rs b/12_integrated_testing/kernel/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/12_integrated_testing/kernel/src/_arch/aarch64/time.rs +++ b/12_integrated_testing/kernel/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/13_exceptions_part2_peripheral_IRQs/README.md b/13_exceptions_part2_peripheral_IRQs/README.md index 3b7a8f64..0bb676db 100644 --- a/13_exceptions_part2_peripheral_IRQs/README.md +++ b/13_exceptions_part2_peripheral_IRQs/README.md @@ -1249,7 +1249,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2/gicd.rs 1 diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs --- 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs -@@ -0,0 +1,221 @@ +@@ -0,0 +1,220 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2022 Andre Richter @@ -1337,7 +1337,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs 13_exc +// Private Definitions +//-------------------------------------------------------------------------------------------------- + -+type HandlerTable = [Option; GICv2::NUM_IRQS]; ++type HandlerTable = [Option; IRQNumber::NUM_TOTAL]; + +//-------------------------------------------------------------------------------------------------- +// Public Definitions @@ -1364,7 +1364,6 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs 13_exc + +impl GICv2 { + const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space. -+ const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1; + + pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Controller v2)"; + @@ -1377,7 +1376,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs 13_exc + Self { + gicd: gicd::GICD::new(gicd_mmio_start_addr), + gicc: gicc::GICC::new(gicc_mmio_start_addr), -+ handler_table: InitStateLock::new([None; Self::NUM_IRQS]), ++ handler_table: InitStateLock::new([None; IRQNumber::NUM_TOTAL]), + } + } +} @@ -1520,14 +1519,18 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs --- 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs -@@ -0,0 +1,167 @@ +@@ -0,0 +1,170 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2022 Andre Richter + +//! Peripheral Interrupt Controller Driver. ++//! ++//! # Resources ++//! ++//! - + -+use super::{InterruptController, PendingIRQs, PeripheralIRQ}; ++use super::{PendingIRQs, PeripheralIRQ}; +use crate::{ + bsp::device_driver::common::MMIODerefWrapper, + exception, synchronization, @@ -1569,8 +1572,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interru +/// Abstraction for the ReadOnly parts of the associated MMIO registers. +type ReadOnlyRegisters = MMIODerefWrapper; + -+type HandlerTable = -+ [Option; InterruptController::NUM_PERIPHERAL_IRQS]; ++type HandlerTable = [Option; PeripheralIRQ::NUM_TOTAL]; + +//-------------------------------------------------------------------------------------------------- +// Public Definitions @@ -1602,7 +1604,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interru + Self { + wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)), + ro_registers: ReadOnlyRegisters::new(mmio_start_addr), -+ handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]), ++ handler_table: InitStateLock::new([None; PeripheralIRQ::NUM_TOTAL]), + } + } + @@ -1692,7 +1694,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interru diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs --- 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs -@@ -0,0 +1,134 @@ +@@ -0,0 +1,131 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2022 Andre Richter @@ -1748,16 +1750,13 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interru + type Item = usize; + + fn next(&mut self) -> Option { -+ use core::intrinsics::cttz; -+ -+ let next = cttz(self.bitmask); -+ if next == 64 { ++ if self.bitmask == 0 { + return None; + } + -+ self.bitmask &= !(1 << next); -+ -+ Some(next as usize) ++ let next = self.bitmask.trailing_zeros() as usize; ++ self.bitmask &= self.bitmask.wrapping_sub(1); ++ Some(next) + } +} + @@ -1766,9 +1765,9 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interru +//-------------------------------------------------------------------------------------------------- + +impl InterruptController { -+ const MAX_LOCAL_IRQ_NUMBER: usize = 11; ++ // Restrict to 3 for now. This makes future code for local_ic.rs more straight forward. ++ const MAX_LOCAL_IRQ_NUMBER: usize = 3; + const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; -+ const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1; + + pub const COMPATIBLE: &'static str = "BCM Interrupt Controller"; + @@ -2230,7 +2229,7 @@ diff -uNr 12_integrated_testing/kernel/src/driver.rs 13_exceptions_part2_periphe diff -uNr 12_integrated_testing/kernel/src/exception/asynchronous.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs --- 12_integrated_testing/kernel/src/exception/asynchronous.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs -@@ -8,7 +8,149 @@ +@@ -8,7 +8,152 @@ #[path = "../_arch/aarch64/exception/asynchronous.rs"] mod arch_asynchronous; @@ -2343,6 +2342,9 @@ diff -uNr 12_integrated_testing/kernel/src/exception/asynchronous.rs 13_exceptio +} + +impl IRQNumber<{ MAX_INCLUSIVE }> { ++ /// The total number of IRQs this type supports. ++ pub const NUM_TOTAL: usize = MAX_INCLUSIVE + 1; ++ + /// Creates a new instance if number <= MAX_INCLUSIVE. + pub const fn new(number: usize) -> Self { + assert!(number <= MAX_INCLUSIVE); diff --git a/13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/time.rs b/13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/time.rs +++ b/13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs b/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs index 03c1fa0f..c810a59a 100644 --- a/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs +++ b/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs @@ -85,7 +85,7 @@ use crate::{bsp, cpu, driver, exception, synchronization, synchronization::InitS // Private Definitions //-------------------------------------------------------------------------------------------------- -type HandlerTable = [Option; GICv2::NUM_IRQS]; +type HandlerTable = [Option; IRQNumber::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -112,7 +112,6 @@ pub struct GICv2 { impl GICv2 { const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space. - const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Controller v2)"; @@ -125,7 +124,7 @@ impl GICv2 { Self { gicd: gicd::GICD::new(gicd_mmio_start_addr), gicc: gicc::GICC::new(gicc_mmio_start_addr), - handler_table: InitStateLock::new([None; Self::NUM_IRQS]), + handler_table: InitStateLock::new([None; IRQNumber::NUM_TOTAL]), } } } diff --git a/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs b/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs index d4acd275..a88899c2 100644 --- a/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ b/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs @@ -53,16 +53,13 @@ impl Iterator for PendingIRQs { type Item = usize; fn next(&mut self) -> Option { - use core::intrinsics::cttz; - - let next = cttz(self.bitmask); - if next == 64 { + if self.bitmask == 0 { return None; } - self.bitmask &= !(1 << next); - - Some(next as usize) + let next = self.bitmask.trailing_zeros() as usize; + self.bitmask &= self.bitmask.wrapping_sub(1); + Some(next) } } @@ -71,9 +68,9 @@ impl Iterator for PendingIRQs { //-------------------------------------------------------------------------------------------------- impl InterruptController { - const MAX_LOCAL_IRQ_NUMBER: usize = 11; + // Restrict to 3 for now. This makes future code for local_ic.rs more straight forward. + const MAX_LOCAL_IRQ_NUMBER: usize = 3; const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; - const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "BCM Interrupt Controller"; diff --git a/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs b/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs index 0900635e..90d9dd81 100644 --- a/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ b/13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs @@ -3,8 +3,12 @@ // Copyright (c) 2020-2022 Andre Richter //! Peripheral Interrupt Controller Driver. +//! +//! # Resources +//! +//! - -use super::{InterruptController, PendingIRQs, PeripheralIRQ}; +use super::{PendingIRQs, PeripheralIRQ}; use crate::{ bsp::device_driver::common::MMIODerefWrapper, exception, synchronization, @@ -46,8 +50,7 @@ type WriteOnlyRegisters = MMIODerefWrapper; /// Abstraction for the ReadOnly parts of the associated MMIO registers. type ReadOnlyRegisters = MMIODerefWrapper; -type HandlerTable = - [Option; InterruptController::NUM_PERIPHERAL_IRQS]; +type HandlerTable = [Option; PeripheralIRQ::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -79,7 +82,7 @@ impl PeripheralIC { Self { wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)), ro_registers: ReadOnlyRegisters::new(mmio_start_addr), - handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]), + handler_table: InitStateLock::new([None; PeripheralIRQ::NUM_TOTAL]), } } diff --git a/13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs b/13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs index 31800ffe..d55ce642 100644 --- a/13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs +++ b/13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs @@ -116,6 +116,9 @@ impl<'irq_context> IRQContext<'irq_context> { } impl IRQNumber<{ MAX_INCLUSIVE }> { + /// The total number of IRQs this type supports. + pub const NUM_TOTAL: usize = MAX_INCLUSIVE + 1; + /// Creates a new instance if number <= MAX_INCLUSIVE. pub const fn new(number: usize) -> Self { assert!(number <= MAX_INCLUSIVE); diff --git a/14_virtual_mem_part2_mmio_remap/README.md b/14_virtual_mem_part2_mmio_remap/README.md index 7dc0c7a3..c0db9938 100644 --- a/14_virtual_mem_part2_mmio_remap/README.md +++ b/14_virtual_mem_part2_mmio_remap/README.md @@ -948,7 +948,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/g } //-------------------------------------------------------------------------------------------------- -@@ -121,11 +129,16 @@ +@@ -120,11 +128,16 @@ /// # Safety /// /// - The user must ensure to provide a correct MMIO start address. @@ -961,12 +961,12 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/g Self { gicd: gicd::GICD::new(gicd_mmio_start_addr), gicc: gicc::GICC::new(gicc_mmio_start_addr), - handler_table: InitStateLock::new([None; Self::NUM_IRQS]), + handler_table: InitStateLock::new([None; IRQNumber::NUM_TOTAL]), + post_init_callback, } } } -@@ -148,6 +161,8 @@ +@@ -147,6 +160,8 @@ self.gicc.priority_accept_all(); self.gicc.enable(); @@ -1035,8 +1035,8 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/b diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs -@@ -7,7 +7,9 @@ - use super::{InterruptController, PendingIRQs, PeripheralIRQ}; +@@ -11,7 +11,9 @@ + use super::{PendingIRQs, PeripheralIRQ}; use crate::{ bsp::device_driver::common::MMIODerefWrapper, - exception, synchronization, @@ -1046,7 +1046,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/b synchronization::{IRQSafeNullLock, InitStateLock}, }; use tock_registers::{ -@@ -75,7 +77,7 @@ +@@ -78,7 +80,7 @@ /// # Safety /// /// - The user must ensure to provide a correct MMIO start address. @@ -1079,7 +1079,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/b } //-------------------------------------------------------------------------------------------------- -@@ -82,9 +86,13 @@ +@@ -79,9 +83,13 @@ /// # Safety /// /// - The user must ensure to provide a correct MMIO start address. @@ -1094,7 +1094,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/b } } } -@@ -97,6 +105,12 @@ +@@ -94,6 +102,12 @@ fn compatible(&self) -> &'static str { Self::COMPATIBLE } @@ -2302,7 +2302,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous. impl<'irq_context> IRQContext<'irq_context> { /// Creates an IRQContext token. -@@ -148,9 +158,17 @@ +@@ -151,9 +161,17 @@ ret } diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/time.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/time.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/arm/gicv2.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/arm/gicv2.rs index e72fde7b..ec65f1b2 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/arm/gicv2.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/arm/gicv2.rs @@ -90,7 +90,7 @@ use crate::{ // Private Definitions //-------------------------------------------------------------------------------------------------- -type HandlerTable = [Option; GICv2::NUM_IRQS]; +type HandlerTable = [Option; IRQNumber::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -120,7 +120,6 @@ pub struct GICv2 { impl GICv2 { const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space. - const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Controller v2)"; @@ -137,7 +136,7 @@ impl GICv2 { Self { gicd: gicd::GICD::new(gicd_mmio_start_addr), gicc: gicc::GICC::new(gicc_mmio_start_addr), - handler_table: InitStateLock::new([None; Self::NUM_IRQS]), + handler_table: InitStateLock::new([None; IRQNumber::NUM_TOTAL]), post_init_callback, } } diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs index 4908b8b6..b4dd530d 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs @@ -57,16 +57,13 @@ impl Iterator for PendingIRQs { type Item = usize; fn next(&mut self) -> Option { - use core::intrinsics::cttz; - - let next = cttz(self.bitmask); - if next == 64 { + if self.bitmask == 0 { return None; } - self.bitmask &= !(1 << next); - - Some(next as usize) + let next = self.bitmask.trailing_zeros() as usize; + self.bitmask &= self.bitmask.wrapping_sub(1); + Some(next) } } @@ -75,9 +72,9 @@ impl Iterator for PendingIRQs { //-------------------------------------------------------------------------------------------------- impl InterruptController { - const MAX_LOCAL_IRQ_NUMBER: usize = 11; + // Restrict to 3 for now. This makes future code for local_ic.rs more straight forward. + const MAX_LOCAL_IRQ_NUMBER: usize = 3; const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; - const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "BCM Interrupt Controller"; diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs index c9711049..06802d27 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs @@ -3,8 +3,12 @@ // Copyright (c) 2020-2022 Andre Richter //! Peripheral Interrupt Controller Driver. +//! +//! # Resources +//! +//! - -use super::{InterruptController, PendingIRQs, PeripheralIRQ}; +use super::{PendingIRQs, PeripheralIRQ}; use crate::{ bsp::device_driver::common::MMIODerefWrapper, exception, @@ -48,8 +52,7 @@ type WriteOnlyRegisters = MMIODerefWrapper; /// Abstraction for the ReadOnly parts of the associated MMIO registers. type ReadOnlyRegisters = MMIODerefWrapper; -type HandlerTable = - [Option; InterruptController::NUM_PERIPHERAL_IRQS]; +type HandlerTable = [Option; PeripheralIRQ::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -81,7 +84,7 @@ impl PeripheralIC { Self { wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)), ro_registers: ReadOnlyRegisters::new(mmio_start_addr), - handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]), + handler_table: InitStateLock::new([None; PeripheralIRQ::NUM_TOTAL]), } } diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/exception/asynchronous.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/exception/asynchronous.rs index 3544e621..83ca1aa6 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/exception/asynchronous.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/exception/asynchronous.rs @@ -126,6 +126,9 @@ impl<'irq_context> IRQContext<'irq_context> { } impl IRQNumber<{ MAX_INCLUSIVE }> { + /// The total number of IRQs this type supports. + pub const NUM_TOTAL: usize = MAX_INCLUSIVE + 1; + /// Creates a new instance if number <= MAX_INCLUSIVE. pub const fn new(number: usize) -> Self { assert!(number <= MAX_INCLUSIVE); diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/time.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/time.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/arm/gicv2.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/arm/gicv2.rs index e72fde7b..ec65f1b2 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/arm/gicv2.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/arm/gicv2.rs @@ -90,7 +90,7 @@ use crate::{ // Private Definitions //-------------------------------------------------------------------------------------------------- -type HandlerTable = [Option; GICv2::NUM_IRQS]; +type HandlerTable = [Option; IRQNumber::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -120,7 +120,6 @@ pub struct GICv2 { impl GICv2 { const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space. - const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Controller v2)"; @@ -137,7 +136,7 @@ impl GICv2 { Self { gicd: gicd::GICD::new(gicd_mmio_start_addr), gicc: gicc::GICC::new(gicc_mmio_start_addr), - handler_table: InitStateLock::new([None; Self::NUM_IRQS]), + handler_table: InitStateLock::new([None; IRQNumber::NUM_TOTAL]), post_init_callback, } } diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs index 4908b8b6..b4dd530d 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs @@ -57,16 +57,13 @@ impl Iterator for PendingIRQs { type Item = usize; fn next(&mut self) -> Option { - use core::intrinsics::cttz; - - let next = cttz(self.bitmask); - if next == 64 { + if self.bitmask == 0 { return None; } - self.bitmask &= !(1 << next); - - Some(next as usize) + let next = self.bitmask.trailing_zeros() as usize; + self.bitmask &= self.bitmask.wrapping_sub(1); + Some(next) } } @@ -75,9 +72,9 @@ impl Iterator for PendingIRQs { //-------------------------------------------------------------------------------------------------- impl InterruptController { - const MAX_LOCAL_IRQ_NUMBER: usize = 11; + // Restrict to 3 for now. This makes future code for local_ic.rs more straight forward. + const MAX_LOCAL_IRQ_NUMBER: usize = 3; const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; - const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "BCM Interrupt Controller"; diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs index c9711049..06802d27 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs @@ -3,8 +3,12 @@ // Copyright (c) 2020-2022 Andre Richter //! Peripheral Interrupt Controller Driver. +//! +//! # Resources +//! +//! - -use super::{InterruptController, PendingIRQs, PeripheralIRQ}; +use super::{PendingIRQs, PeripheralIRQ}; use crate::{ bsp::device_driver::common::MMIODerefWrapper, exception, @@ -48,8 +52,7 @@ type WriteOnlyRegisters = MMIODerefWrapper; /// Abstraction for the ReadOnly parts of the associated MMIO registers. type ReadOnlyRegisters = MMIODerefWrapper; -type HandlerTable = - [Option; InterruptController::NUM_PERIPHERAL_IRQS]; +type HandlerTable = [Option; PeripheralIRQ::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -81,7 +84,7 @@ impl PeripheralIC { Self { wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)), ro_registers: ReadOnlyRegisters::new(mmio_start_addr), - handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]), + handler_table: InitStateLock::new([None; PeripheralIRQ::NUM_TOTAL]), } } diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/exception/asynchronous.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/exception/asynchronous.rs index 3544e621..83ca1aa6 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/exception/asynchronous.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/exception/asynchronous.rs @@ -126,6 +126,9 @@ impl<'irq_context> IRQContext<'irq_context> { } impl IRQNumber<{ MAX_INCLUSIVE }> { + /// The total number of IRQs this type supports. + pub const NUM_TOTAL: usize = MAX_INCLUSIVE + 1; + /// Creates a new instance if number <= MAX_INCLUSIVE. pub const fn new(number: usize) -> Self { assert!(number <= MAX_INCLUSIVE); diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/_arch/aarch64/time.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/_arch/aarch64/time.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/arm/gicv2.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/arm/gicv2.rs index e72fde7b..ec65f1b2 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/arm/gicv2.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/arm/gicv2.rs @@ -90,7 +90,7 @@ use crate::{ // Private Definitions //-------------------------------------------------------------------------------------------------- -type HandlerTable = [Option; GICv2::NUM_IRQS]; +type HandlerTable = [Option; IRQNumber::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -120,7 +120,6 @@ pub struct GICv2 { impl GICv2 { const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space. - const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Controller v2)"; @@ -137,7 +136,7 @@ impl GICv2 { Self { gicd: gicd::GICD::new(gicd_mmio_start_addr), gicc: gicc::GICC::new(gicc_mmio_start_addr), - handler_table: InitStateLock::new([None; Self::NUM_IRQS]), + handler_table: InitStateLock::new([None; IRQNumber::NUM_TOTAL]), post_init_callback, } } diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs index 4908b8b6..b4dd530d 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs @@ -57,16 +57,13 @@ impl Iterator for PendingIRQs { type Item = usize; fn next(&mut self) -> Option { - use core::intrinsics::cttz; - - let next = cttz(self.bitmask); - if next == 64 { + if self.bitmask == 0 { return None; } - self.bitmask &= !(1 << next); - - Some(next as usize) + let next = self.bitmask.trailing_zeros() as usize; + self.bitmask &= self.bitmask.wrapping_sub(1); + Some(next) } } @@ -75,9 +72,9 @@ impl Iterator for PendingIRQs { //-------------------------------------------------------------------------------------------------- impl InterruptController { - const MAX_LOCAL_IRQ_NUMBER: usize = 11; + // Restrict to 3 for now. This makes future code for local_ic.rs more straight forward. + const MAX_LOCAL_IRQ_NUMBER: usize = 3; const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; - const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "BCM Interrupt Controller"; diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs index c9711049..06802d27 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs @@ -3,8 +3,12 @@ // Copyright (c) 2020-2022 Andre Richter //! Peripheral Interrupt Controller Driver. +//! +//! # Resources +//! +//! - -use super::{InterruptController, PendingIRQs, PeripheralIRQ}; +use super::{PendingIRQs, PeripheralIRQ}; use crate::{ bsp::device_driver::common::MMIODerefWrapper, exception, @@ -48,8 +52,7 @@ type WriteOnlyRegisters = MMIODerefWrapper; /// Abstraction for the ReadOnly parts of the associated MMIO registers. type ReadOnlyRegisters = MMIODerefWrapper; -type HandlerTable = - [Option; InterruptController::NUM_PERIPHERAL_IRQS]; +type HandlerTable = [Option; PeripheralIRQ::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -81,7 +84,7 @@ impl PeripheralIC { Self { wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)), ro_registers: ReadOnlyRegisters::new(mmio_start_addr), - handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]), + handler_table: InitStateLock::new([None; PeripheralIRQ::NUM_TOTAL]), } } diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/exception/asynchronous.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/exception/asynchronous.rs index 3544e621..83ca1aa6 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/exception/asynchronous.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/exception/asynchronous.rs @@ -126,6 +126,9 @@ impl<'irq_context> IRQContext<'irq_context> { } impl IRQNumber<{ MAX_INCLUSIVE }> { + /// The total number of IRQs this type supports. + pub const NUM_TOTAL: usize = MAX_INCLUSIVE + 1; + /// Creates a new instance if number <= MAX_INCLUSIVE. pub const fn new(number: usize) -> Self { assert!(number <= MAX_INCLUSIVE); diff --git a/17_kernel_symbols/README.md b/17_kernel_symbols/README.md index 699cfe2c..e88795ab 100644 --- a/17_kernel_symbols/README.md +++ b/17_kernel_symbols/README.md @@ -168,13 +168,18 @@ fn kernel_symbol_section_virt_start_addr() -> Address { Address::new(unsafe { __kernel_symbols_start.get() as usize }) } +fn num_kernel_symbols() -> usize { + unsafe { + // Read volatile is needed here to prevent the compiler from optimizing NUM_KERNEL_SYMBOLS + // away. + core::ptr::read_volatile(&NUM_KERNEL_SYMBOLS as *const u64) as usize + } +} + fn kernel_symbols_slice() -> &'static [Symbol] { let ptr = kernel_symbol_section_virt_start_addr().as_usize() as *const Symbol; - unsafe { - let num = core::ptr::read_volatile(&NUM_KERNEL_SYMBOLS as *const u64) as usize; - slice::from_raw_parts(ptr, num) - } + unsafe { slice::from_raw_parts(ptr, num_kernel_symbols()) } } ``` @@ -338,7 +343,7 @@ diff -uNr 16_virtual_mem_part4_higher_half_kernel/kernel/src/lib.rs 17_kernel_sy diff -uNr 16_virtual_mem_part4_higher_half_kernel/kernel/src/symbols.rs 17_kernel_symbols/kernel/src/symbols.rs --- 16_virtual_mem_part4_higher_half_kernel/kernel/src/symbols.rs +++ 17_kernel_symbols/kernel/src/symbols.rs -@@ -0,0 +1,83 @@ +@@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2022 Andre Richter @@ -375,13 +380,18 @@ diff -uNr 16_virtual_mem_part4_higher_half_kernel/kernel/src/symbols.rs 17_kerne + Address::new(unsafe { __kernel_symbols_start.get() as usize }) +} + ++fn num_kernel_symbols() -> usize { ++ unsafe { ++ // Read volatile is needed here to prevent the compiler from optimizing NUM_KERNEL_SYMBOLS ++ // away. ++ core::ptr::read_volatile(&NUM_KERNEL_SYMBOLS as *const u64) as usize ++ } ++} ++ +fn kernel_symbols_slice() -> &'static [Symbol] { + let ptr = kernel_symbol_section_virt_start_addr().as_usize() as *const Symbol; + -+ unsafe { -+ let num = core::ptr::read_volatile(&NUM_KERNEL_SYMBOLS as *const u64) as usize; -+ slice::from_raw_parts(ptr, num) -+ } ++ unsafe { slice::from_raw_parts(ptr, num_kernel_symbols()) } +} + +//-------------------------------------------------------------------------------------------------- diff --git a/17_kernel_symbols/kernel/src/_arch/aarch64/time.rs b/17_kernel_symbols/kernel/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/17_kernel_symbols/kernel/src/_arch/aarch64/time.rs +++ b/17_kernel_symbols/kernel/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/17_kernel_symbols/kernel/src/bsp/device_driver/arm/gicv2.rs b/17_kernel_symbols/kernel/src/bsp/device_driver/arm/gicv2.rs index e72fde7b..ec65f1b2 100644 --- a/17_kernel_symbols/kernel/src/bsp/device_driver/arm/gicv2.rs +++ b/17_kernel_symbols/kernel/src/bsp/device_driver/arm/gicv2.rs @@ -90,7 +90,7 @@ use crate::{ // Private Definitions //-------------------------------------------------------------------------------------------------- -type HandlerTable = [Option; GICv2::NUM_IRQS]; +type HandlerTable = [Option; IRQNumber::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -120,7 +120,6 @@ pub struct GICv2 { impl GICv2 { const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space. - const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Controller v2)"; @@ -137,7 +136,7 @@ impl GICv2 { Self { gicd: gicd::GICD::new(gicd_mmio_start_addr), gicc: gicc::GICC::new(gicc_mmio_start_addr), - handler_table: InitStateLock::new([None; Self::NUM_IRQS]), + handler_table: InitStateLock::new([None; IRQNumber::NUM_TOTAL]), post_init_callback, } } diff --git a/17_kernel_symbols/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs b/17_kernel_symbols/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs index 4908b8b6..b4dd530d 100644 --- a/17_kernel_symbols/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ b/17_kernel_symbols/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs @@ -57,16 +57,13 @@ impl Iterator for PendingIRQs { type Item = usize; fn next(&mut self) -> Option { - use core::intrinsics::cttz; - - let next = cttz(self.bitmask); - if next == 64 { + if self.bitmask == 0 { return None; } - self.bitmask &= !(1 << next); - - Some(next as usize) + let next = self.bitmask.trailing_zeros() as usize; + self.bitmask &= self.bitmask.wrapping_sub(1); + Some(next) } } @@ -75,9 +72,9 @@ impl Iterator for PendingIRQs { //-------------------------------------------------------------------------------------------------- impl InterruptController { - const MAX_LOCAL_IRQ_NUMBER: usize = 11; + // Restrict to 3 for now. This makes future code for local_ic.rs more straight forward. + const MAX_LOCAL_IRQ_NUMBER: usize = 3; const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; - const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "BCM Interrupt Controller"; diff --git a/17_kernel_symbols/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs b/17_kernel_symbols/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs index c9711049..06802d27 100644 --- a/17_kernel_symbols/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ b/17_kernel_symbols/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs @@ -3,8 +3,12 @@ // Copyright (c) 2020-2022 Andre Richter //! Peripheral Interrupt Controller Driver. +//! +//! # Resources +//! +//! - -use super::{InterruptController, PendingIRQs, PeripheralIRQ}; +use super::{PendingIRQs, PeripheralIRQ}; use crate::{ bsp::device_driver::common::MMIODerefWrapper, exception, @@ -48,8 +52,7 @@ type WriteOnlyRegisters = MMIODerefWrapper; /// Abstraction for the ReadOnly parts of the associated MMIO registers. type ReadOnlyRegisters = MMIODerefWrapper; -type HandlerTable = - [Option; InterruptController::NUM_PERIPHERAL_IRQS]; +type HandlerTable = [Option; PeripheralIRQ::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -81,7 +84,7 @@ impl PeripheralIC { Self { wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)), ro_registers: ReadOnlyRegisters::new(mmio_start_addr), - handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]), + handler_table: InitStateLock::new([None; PeripheralIRQ::NUM_TOTAL]), } } diff --git a/17_kernel_symbols/kernel/src/exception/asynchronous.rs b/17_kernel_symbols/kernel/src/exception/asynchronous.rs index 3544e621..83ca1aa6 100644 --- a/17_kernel_symbols/kernel/src/exception/asynchronous.rs +++ b/17_kernel_symbols/kernel/src/exception/asynchronous.rs @@ -126,6 +126,9 @@ impl<'irq_context> IRQContext<'irq_context> { } impl IRQNumber<{ MAX_INCLUSIVE }> { + /// The total number of IRQs this type supports. + pub const NUM_TOTAL: usize = MAX_INCLUSIVE + 1; + /// Creates a new instance if number <= MAX_INCLUSIVE. pub const fn new(number: usize) -> Self { assert!(number <= MAX_INCLUSIVE); diff --git a/17_kernel_symbols/kernel/src/symbols.rs b/17_kernel_symbols/kernel/src/symbols.rs index 7f439ce2..680b8eaf 100644 --- a/17_kernel_symbols/kernel/src/symbols.rs +++ b/17_kernel_symbols/kernel/src/symbols.rs @@ -34,13 +34,18 @@ fn kernel_symbol_section_virt_start_addr() -> Address { Address::new(unsafe { __kernel_symbols_start.get() as usize }) } +fn num_kernel_symbols() -> usize { + unsafe { + // Read volatile is needed here to prevent the compiler from optimizing NUM_KERNEL_SYMBOLS + // away. + core::ptr::read_volatile(&NUM_KERNEL_SYMBOLS as *const u64) as usize + } +} + fn kernel_symbols_slice() -> &'static [Symbol] { let ptr = kernel_symbol_section_virt_start_addr().as_usize() as *const Symbol; - unsafe { - let num = core::ptr::read_volatile(&NUM_KERNEL_SYMBOLS as *const u64) as usize; - slice::from_raw_parts(ptr, num) - } + unsafe { slice::from_raw_parts(ptr, num_kernel_symbols()) } } //-------------------------------------------------------------------------------------------------- diff --git a/18_backtrace/kernel/src/_arch/aarch64/time.rs b/18_backtrace/kernel/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/18_backtrace/kernel/src/_arch/aarch64/time.rs +++ b/18_backtrace/kernel/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/18_backtrace/kernel/src/bsp/device_driver/arm/gicv2.rs b/18_backtrace/kernel/src/bsp/device_driver/arm/gicv2.rs index e72fde7b..ec65f1b2 100644 --- a/18_backtrace/kernel/src/bsp/device_driver/arm/gicv2.rs +++ b/18_backtrace/kernel/src/bsp/device_driver/arm/gicv2.rs @@ -90,7 +90,7 @@ use crate::{ // Private Definitions //-------------------------------------------------------------------------------------------------- -type HandlerTable = [Option; GICv2::NUM_IRQS]; +type HandlerTable = [Option; IRQNumber::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -120,7 +120,6 @@ pub struct GICv2 { impl GICv2 { const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space. - const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Controller v2)"; @@ -137,7 +136,7 @@ impl GICv2 { Self { gicd: gicd::GICD::new(gicd_mmio_start_addr), gicc: gicc::GICC::new(gicc_mmio_start_addr), - handler_table: InitStateLock::new([None; Self::NUM_IRQS]), + handler_table: InitStateLock::new([None; IRQNumber::NUM_TOTAL]), post_init_callback, } } diff --git a/18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs b/18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs index 4908b8b6..b4dd530d 100644 --- a/18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ b/18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs @@ -57,16 +57,13 @@ impl Iterator for PendingIRQs { type Item = usize; fn next(&mut self) -> Option { - use core::intrinsics::cttz; - - let next = cttz(self.bitmask); - if next == 64 { + if self.bitmask == 0 { return None; } - self.bitmask &= !(1 << next); - - Some(next as usize) + let next = self.bitmask.trailing_zeros() as usize; + self.bitmask &= self.bitmask.wrapping_sub(1); + Some(next) } } @@ -75,9 +72,9 @@ impl Iterator for PendingIRQs { //-------------------------------------------------------------------------------------------------- impl InterruptController { - const MAX_LOCAL_IRQ_NUMBER: usize = 11; + // Restrict to 3 for now. This makes future code for local_ic.rs more straight forward. + const MAX_LOCAL_IRQ_NUMBER: usize = 3; const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; - const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1; pub const COMPATIBLE: &'static str = "BCM Interrupt Controller"; diff --git a/18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs b/18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs index c9711049..06802d27 100644 --- a/18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ b/18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs @@ -3,8 +3,12 @@ // Copyright (c) 2020-2022 Andre Richter //! Peripheral Interrupt Controller Driver. +//! +//! # Resources +//! +//! - -use super::{InterruptController, PendingIRQs, PeripheralIRQ}; +use super::{PendingIRQs, PeripheralIRQ}; use crate::{ bsp::device_driver::common::MMIODerefWrapper, exception, @@ -48,8 +52,7 @@ type WriteOnlyRegisters = MMIODerefWrapper; /// Abstraction for the ReadOnly parts of the associated MMIO registers. type ReadOnlyRegisters = MMIODerefWrapper; -type HandlerTable = - [Option; InterruptController::NUM_PERIPHERAL_IRQS]; +type HandlerTable = [Option; PeripheralIRQ::NUM_TOTAL]; //-------------------------------------------------------------------------------------------------- // Public Definitions @@ -81,7 +84,7 @@ impl PeripheralIC { Self { wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)), ro_registers: ReadOnlyRegisters::new(mmio_start_addr), - handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]), + handler_table: InitStateLock::new([None; PeripheralIRQ::NUM_TOTAL]), } } diff --git a/18_backtrace/kernel/src/exception/asynchronous.rs b/18_backtrace/kernel/src/exception/asynchronous.rs index 3544e621..83ca1aa6 100644 --- a/18_backtrace/kernel/src/exception/asynchronous.rs +++ b/18_backtrace/kernel/src/exception/asynchronous.rs @@ -126,6 +126,9 @@ impl<'irq_context> IRQContext<'irq_context> { } impl IRQNumber<{ MAX_INCLUSIVE }> { + /// The total number of IRQs this type supports. + pub const NUM_TOTAL: usize = MAX_INCLUSIVE + 1; + /// Creates a new instance if number <= MAX_INCLUSIVE. pub const fn new(number: usize) -> Self { assert!(number <= MAX_INCLUSIVE); diff --git a/18_backtrace/kernel/src/symbols.rs b/18_backtrace/kernel/src/symbols.rs index 7f439ce2..680b8eaf 100644 --- a/18_backtrace/kernel/src/symbols.rs +++ b/18_backtrace/kernel/src/symbols.rs @@ -34,13 +34,18 @@ fn kernel_symbol_section_virt_start_addr() -> Address { Address::new(unsafe { __kernel_symbols_start.get() as usize }) } +fn num_kernel_symbols() -> usize { + unsafe { + // Read volatile is needed here to prevent the compiler from optimizing NUM_KERNEL_SYMBOLS + // away. + core::ptr::read_volatile(&NUM_KERNEL_SYMBOLS as *const u64) as usize + } +} + fn kernel_symbols_slice() -> &'static [Symbol] { let ptr = kernel_symbol_section_virt_start_addr().as_usize() as *const Symbol; - unsafe { - let num = core::ptr::read_volatile(&NUM_KERNEL_SYMBOLS as *const u64) as usize; - slice::from_raw_parts(ptr, num) - } + unsafe { slice::from_raw_parts(ptr, num_kernel_symbols()) } } //-------------------------------------------------------------------------------------------------- diff --git a/19_kernel_heap/README.md b/19_kernel_heap/README.md index 11417c2f..b1463fc5 100644 --- a/19_kernel_heap/README.md +++ b/19_kernel_heap/README.md @@ -298,57 +298,44 @@ diff -uNr 18_backtrace/kernel/src/bsp/device_driver/arm/gicv2.rs 19_kernel_heap/ // Private Definitions //-------------------------------------------------------------------------------------------------- --type HandlerTable = [Option; GICv2::NUM_IRQS]; +-type HandlerTable = [Option; IRQNumber::NUM_TOTAL]; +type HandlerTable = Vec>; //-------------------------------------------------------------------------------------------------- // Public Definitions -@@ -119,8 +120,7 @@ +@@ -119,7 +120,7 @@ //-------------------------------------------------------------------------------------------------- impl GICv2 { - const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space. -- const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1; + const MAX_IRQ_NUMBER: usize = 1019; pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Controller v2)"; -@@ -137,7 +137,7 @@ +@@ -136,7 +137,7 @@ Self { gicd: gicd::GICD::new(gicd_mmio_start_addr), gicc: gicc::GICC::new(gicc_mmio_start_addr), -- handler_table: InitStateLock::new([None; Self::NUM_IRQS]), +- handler_table: InitStateLock::new([None; IRQNumber::NUM_TOTAL]), + handler_table: InitStateLock::new(Vec::new()), post_init_callback, } } -@@ -178,6 +178,12 @@ - self.handler_table.write(|table| { - let irq_number = irq_number.get(); - -+ if table.len() < irq_number { -+ // IRQDescriptor has an integrated range sanity check on construction, so this -+ // vector can't grow arbitrarily big. -+ table.resize(irq_number + 1, None); -+ } +@@ -153,6 +154,9 @@ + } + + unsafe fn init(&self) -> Result<(), &'static str> { ++ self.handler_table ++ .write(|table| table.resize(IRQNumber::NUM_TOTAL, None)); + - if table[irq_number].is_some() { - return Err("IRQ handler already registered"); - } + if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() { + self.gicd.boot_core_init(); + } diff -uNr 18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs 19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs --- 18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ 19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs -@@ -4,7 +4,7 @@ - - //! Peripheral Interrupt Controller Driver. - --use super::{InterruptController, PendingIRQs, PeripheralIRQ}; -+use super::{PendingIRQs, PeripheralIRQ}; - use crate::{ - bsp::device_driver::common::MMIODerefWrapper, - exception, -@@ -12,6 +12,7 @@ +@@ -16,6 +16,7 @@ synchronization, synchronization::{IRQSafeNullLock, InitStateLock}, }; @@ -356,50 +343,46 @@ diff -uNr 18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_contro use tock_registers::{ interfaces::{Readable, Writeable}, register_structs, -@@ -48,8 +49,7 @@ +@@ -52,7 +53,7 @@ /// Abstraction for the ReadOnly parts of the associated MMIO registers. type ReadOnlyRegisters = MMIODerefWrapper; --type HandlerTable = -- [Option; InterruptController::NUM_PERIPHERAL_IRQS]; +-type HandlerTable = [Option; PeripheralIRQ::NUM_TOTAL]; +type HandlerTable = Vec>; //-------------------------------------------------------------------------------------------------- // Public Definitions -@@ -81,7 +81,7 @@ +@@ -84,10 +85,16 @@ Self { wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)), ro_registers: ReadOnlyRegisters::new(mmio_start_addr), -- handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]), +- handler_table: InitStateLock::new([None; PeripheralIRQ::NUM_TOTAL]), + handler_table: InitStateLock::new(Vec::new()), } } -@@ -110,6 +110,12 @@ - self.handler_table.write(|table| { - let irq_number = irq.get(); - -+ if table.len() < irq_number { -+ // IRQDescriptor has an integrated range sanity check on construction, so this -+ // vector can't grow arbitrarily big. -+ table.resize(irq_number + 1, None); -+ } ++ /// Called by the kernel to bring up the device. ++ pub fn init(&self) { ++ self.handler_table ++ .write(|table| table.resize(PeripheralIRQ::NUM_TOTAL, None)); ++ } + - if table[irq_number].is_some() { - return Err("IRQ handler already registered"); - } + /// Query the list of pending IRQs. + fn pending_irqs(&self) -> PendingIRQs { + let pending_mask: u64 = (u64::from(self.ro_registers.PENDING_2.get()) << 32) diff -uNr 18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs 19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs --- 18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ 19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs -@@ -77,7 +77,6 @@ - impl InterruptController { - const MAX_LOCAL_IRQ_NUMBER: usize = 11; - const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; -- const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1; +@@ -104,6 +104,8 @@ + } - pub const COMPATIBLE: &'static str = "BCM Interrupt Controller"; + unsafe fn init(&self) -> Result<(), &'static str> { ++ self.periph.init(); ++ + (self.post_init_callback)(); + Ok(()) diff -uNr 18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs --- 18_backtrace/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs diff --git a/19_kernel_heap/kernel/src/_arch/aarch64/time.rs b/19_kernel_heap/kernel/src/_arch/aarch64/time.rs index 255a5a45..ad8ba84d 100644 --- a/19_kernel_heap/kernel/src/_arch/aarch64/time.rs +++ b/19_kernel_heap/kernel/src/_arch/aarch64/time.rs @@ -42,6 +42,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -60,13 +69,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -101,10 +104,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and diff --git a/19_kernel_heap/kernel/src/bsp/device_driver/arm/gicv2.rs b/19_kernel_heap/kernel/src/bsp/device_driver/arm/gicv2.rs index cb7c69ee..69ba8513 100644 --- a/19_kernel_heap/kernel/src/bsp/device_driver/arm/gicv2.rs +++ b/19_kernel_heap/kernel/src/bsp/device_driver/arm/gicv2.rs @@ -154,6 +154,9 @@ impl driver::interface::DeviceDriver for GICv2 { } unsafe fn init(&self) -> Result<(), &'static str> { + self.handler_table + .write(|table| table.resize(IRQNumber::NUM_TOTAL, None)); + if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() { self.gicd.boot_core_init(); } @@ -178,12 +181,6 @@ impl exception::asynchronous::interface::IRQManager for GICv2 { self.handler_table.write(|table| { let irq_number = irq_number.get(); - if table.len() < irq_number { - // IRQDescriptor has an integrated range sanity check on construction, so this - // vector can't grow arbitrarily big. - table.resize(irq_number + 1, None); - } - if table[irq_number].is_some() { return Err("IRQ handler already registered"); } diff --git a/19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs b/19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs index a93b0bc9..658d3705 100644 --- a/19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ b/19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs @@ -57,16 +57,13 @@ impl Iterator for PendingIRQs { type Item = usize; fn next(&mut self) -> Option { - use core::intrinsics::cttz; - - let next = cttz(self.bitmask); - if next == 64 { + if self.bitmask == 0 { return None; } - self.bitmask &= !(1 << next); - - Some(next as usize) + let next = self.bitmask.trailing_zeros() as usize; + self.bitmask &= self.bitmask.wrapping_sub(1); + Some(next) } } @@ -75,7 +72,8 @@ impl Iterator for PendingIRQs { //-------------------------------------------------------------------------------------------------- impl InterruptController { - const MAX_LOCAL_IRQ_NUMBER: usize = 11; + // Restrict to 3 for now. This makes future code for local_ic.rs more straight forward. + const MAX_LOCAL_IRQ_NUMBER: usize = 3; const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; pub const COMPATIBLE: &'static str = "BCM Interrupt Controller"; @@ -106,6 +104,8 @@ impl driver::interface::DeviceDriver for InterruptController { } unsafe fn init(&self) -> Result<(), &'static str> { + self.periph.init(); + (self.post_init_callback)(); Ok(()) diff --git a/19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs b/19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs index 65a9e7a0..90b56378 100644 --- a/19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ b/19_kernel_heap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs @@ -3,6 +3,10 @@ // Copyright (c) 2020-2022 Andre Richter //! Peripheral Interrupt Controller Driver. +//! +//! # Resources +//! +//! - use super::{PendingIRQs, PeripheralIRQ}; use crate::{ @@ -85,6 +89,12 @@ impl PeripheralIC { } } + /// Called by the kernel to bring up the device. + pub fn init(&self) { + self.handler_table + .write(|table| table.resize(PeripheralIRQ::NUM_TOTAL, None)); + } + /// Query the list of pending IRQs. fn pending_irqs(&self) -> PendingIRQs { let pending_mask: u64 = (u64::from(self.ro_registers.PENDING_2.get()) << 32) @@ -110,12 +120,6 @@ impl exception::asynchronous::interface::IRQManager for PeripheralIC { self.handler_table.write(|table| { let irq_number = irq.get(); - if table.len() < irq_number { - // IRQDescriptor has an integrated range sanity check on construction, so this - // vector can't grow arbitrarily big. - table.resize(irq_number + 1, None); - } - if table[irq_number].is_some() { return Err("IRQ handler already registered"); } diff --git a/19_kernel_heap/kernel/src/exception/asynchronous.rs b/19_kernel_heap/kernel/src/exception/asynchronous.rs index 3544e621..83ca1aa6 100644 --- a/19_kernel_heap/kernel/src/exception/asynchronous.rs +++ b/19_kernel_heap/kernel/src/exception/asynchronous.rs @@ -126,6 +126,9 @@ impl<'irq_context> IRQContext<'irq_context> { } impl IRQNumber<{ MAX_INCLUSIVE }> { + /// The total number of IRQs this type supports. + pub const NUM_TOTAL: usize = MAX_INCLUSIVE + 1; + /// Creates a new instance if number <= MAX_INCLUSIVE. pub const fn new(number: usize) -> Self { assert!(number <= MAX_INCLUSIVE); diff --git a/19_kernel_heap/kernel/src/symbols.rs b/19_kernel_heap/kernel/src/symbols.rs index 7f439ce2..680b8eaf 100644 --- a/19_kernel_heap/kernel/src/symbols.rs +++ b/19_kernel_heap/kernel/src/symbols.rs @@ -34,13 +34,18 @@ fn kernel_symbol_section_virt_start_addr() -> Address { Address::new(unsafe { __kernel_symbols_start.get() as usize }) } +fn num_kernel_symbols() -> usize { + unsafe { + // Read volatile is needed here to prevent the compiler from optimizing NUM_KERNEL_SYMBOLS + // away. + core::ptr::read_volatile(&NUM_KERNEL_SYMBOLS as *const u64) as usize + } +} + fn kernel_symbols_slice() -> &'static [Symbol] { let ptr = kernel_symbol_section_virt_start_addr().as_usize() as *const Symbol; - unsafe { - let num = core::ptr::read_volatile(&NUM_KERNEL_SYMBOLS as *const u64) as usize; - slice::from_raw_parts(ptr, num) - } + unsafe { slice::from_raw_parts(ptr, num_kernel_symbols()) } } //-------------------------------------------------------------------------------------------------- diff --git a/X1_JTAG_boot/src/_arch/aarch64/time.rs b/X1_JTAG_boot/src/_arch/aarch64/time.rs index 3d3a20d7..54db51c3 100644 --- a/X1_JTAG_boot/src/_arch/aarch64/time.rs +++ b/X1_JTAG_boot/src/_arch/aarch64/time.rs @@ -43,6 +43,15 @@ static ARCH_TIMER_COUNTER_FREQUENCY: NonZeroU32 = NonZeroU32::MIN; // Private Code //-------------------------------------------------------------------------------------------------- +fn arch_timer_counter_frequency() -> NonZeroU32 { + // Read volatile is needed here to prevent the compiler from optimizing + // ARCH_TIMER_COUNTER_FREQUENCY away. + // + // This is safe, because all the safety requirements as stated in read_volatile()'s + // documentation are fulfilled. + unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) } +} + impl GenericTimerCounterValue { pub const MAX: Self = GenericTimerCounterValue(u64::MAX); } @@ -61,13 +70,7 @@ impl From for Duration { return Duration::ZERO; } - // Read volatile is needed here to prevent the compiler from optimizing - // ARCH_TIMER_COUNTER_FREQUENCY away. - // - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: NonZeroU64 = - unsafe { core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY) }.into(); + let frequency: NonZeroU64 = arch_timer_counter_frequency().into(); // Div implementation for u64 cannot panic. let secs = counter_value.0.div(frequency); @@ -102,10 +105,7 @@ impl TryFrom for GenericTimerCounterValue { return Err("Conversion error. Duration too big"); } - // This is safe, because all the safety requirements as stated in read_volatile()'s - // documentation are fulfilled. - let frequency: u128 = - unsafe { u32::from(core::ptr::read_volatile(&ARCH_TIMER_COUNTER_FREQUENCY)) as u128 }; + let frequency: u128 = u32::from(arch_timer_counter_frequency()) as u128; let duration: u128 = duration.as_nanos(); // This is safe, because frequency can never be greater than u32::MAX, and