diff --git a/08_timestamps/README.md b/08_timestamps/README.md index 83e38ca5..0f8ec5d2 100644 --- a/08_timestamps/README.md +++ b/08_timestamps/README.md @@ -175,7 +175,7 @@ diff -uNr 07_uart_chainloader/src/_arch/aarch64/cpu.rs 08_timestamps/src/_arch/a diff -uNr 07_uart_chainloader/src/_arch/aarch64/time.rs 08_timestamps/src/_arch/aarch64/time.rs --- 07_uart_chainloader/src/_arch/aarch64/time.rs +++ 08_timestamps/src/_arch/aarch64/time.rs -@@ -0,0 +1,105 @@ +@@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2021 Andre Richter @@ -191,7 +191,7 @@ diff -uNr 07_uart_chainloader/src/_arch/aarch64/time.rs 08_timestamps/src/_arch/ + +use crate::{time, warn}; +use core::time::Duration; -+use cortex_a::regs::*; ++use cortex_a::{barrier, regs::*}; + +//-------------------------------------------------------------------------------------------------- +// Private Definitions @@ -209,6 +209,19 @@ diff -uNr 07_uart_chainloader/src/_arch/aarch64/time.rs 08_timestamps/src/_arch/ +static TIME_MANAGER: GenericTimer = GenericTimer; + +//-------------------------------------------------------------------------------------------------- ++// Private Code ++//-------------------------------------------------------------------------------------------------- ++ ++impl GenericTimer { ++ #[inline(always)] ++ fn read_cntpct(&self) -> u64 { ++ // Prevent that the counter is read ahead of time due to out-of-order execution. ++ unsafe { barrier::isb(barrier::SY) }; ++ CNTPCT_EL0.get() ++ } ++} ++ ++//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + @@ -227,8 +240,8 @@ diff -uNr 07_uart_chainloader/src/_arch/aarch64/time.rs 08_timestamps/src/_arch/ + } + + fn uptime(&self) -> Duration { ++ let current_count: u64 = self.read_cntpct() * NS_PER_S; + let frq: u64 = CNTFRQ_EL0.get() as u64; -+ let current_count: u64 = CNTPCT_EL0.get() * NS_PER_S; + + Duration::from_nanos(current_count / frq) + } diff --git a/08_timestamps/src/_arch/aarch64/time.rs b/08_timestamps/src/_arch/aarch64/time.rs index 3a766009..63017305 100644 --- a/08_timestamps/src/_arch/aarch64/time.rs +++ b/08_timestamps/src/_arch/aarch64/time.rs @@ -13,7 +13,7 @@ use crate::{time, warn}; use core::time::Duration; -use cortex_a::regs::*; +use cortex_a::{barrier, regs::*}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -30,6 +30,19 @@ struct GenericTimer; static TIME_MANAGER: GenericTimer = GenericTimer; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl GenericTimer { + #[inline(always)] + fn read_cntpct(&self) -> u64 { + // Prevent that the counter is read ahead of time due to out-of-order execution. + unsafe { barrier::isb(barrier::SY) }; + CNTPCT_EL0.get() + } +} + //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- @@ -49,8 +62,8 @@ impl time::interface::TimeManager for GenericTimer { } fn uptime(&self) -> Duration { + let current_count: u64 = self.read_cntpct() * NS_PER_S; let frq: u64 = CNTFRQ_EL0.get() as u64; - let current_count: u64 = CNTPCT_EL0.get() * NS_PER_S; Duration::from_nanos(current_count / frq) } diff --git a/09_hw_debug_JTAG/src/_arch/aarch64/time.rs b/09_hw_debug_JTAG/src/_arch/aarch64/time.rs index 3a766009..63017305 100644 --- a/09_hw_debug_JTAG/src/_arch/aarch64/time.rs +++ b/09_hw_debug_JTAG/src/_arch/aarch64/time.rs @@ -13,7 +13,7 @@ use crate::{time, warn}; use core::time::Duration; -use cortex_a::regs::*; +use cortex_a::{barrier, regs::*}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -30,6 +30,19 @@ struct GenericTimer; static TIME_MANAGER: GenericTimer = GenericTimer; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl GenericTimer { + #[inline(always)] + fn read_cntpct(&self) -> u64 { + // Prevent that the counter is read ahead of time due to out-of-order execution. + unsafe { barrier::isb(barrier::SY) }; + CNTPCT_EL0.get() + } +} + //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- @@ -49,8 +62,8 @@ impl time::interface::TimeManager for GenericTimer { } fn uptime(&self) -> Duration { + let current_count: u64 = self.read_cntpct() * NS_PER_S; let frq: u64 = CNTFRQ_EL0.get() as u64; - let current_count: u64 = CNTPCT_EL0.get() * NS_PER_S; Duration::from_nanos(current_count / frq) } diff --git a/10_privilege_level/src/_arch/aarch64/time.rs b/10_privilege_level/src/_arch/aarch64/time.rs index 3a766009..63017305 100644 --- a/10_privilege_level/src/_arch/aarch64/time.rs +++ b/10_privilege_level/src/_arch/aarch64/time.rs @@ -13,7 +13,7 @@ use crate::{time, warn}; use core::time::Duration; -use cortex_a::regs::*; +use cortex_a::{barrier, regs::*}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -30,6 +30,19 @@ struct GenericTimer; static TIME_MANAGER: GenericTimer = GenericTimer; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl GenericTimer { + #[inline(always)] + fn read_cntpct(&self) -> u64 { + // Prevent that the counter is read ahead of time due to out-of-order execution. + unsafe { barrier::isb(barrier::SY) }; + CNTPCT_EL0.get() + } +} + //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- @@ -49,8 +62,8 @@ impl time::interface::TimeManager for GenericTimer { } fn uptime(&self) -> Duration { + let current_count: u64 = self.read_cntpct() * NS_PER_S; let frq: u64 = CNTFRQ_EL0.get() as u64; - let current_count: u64 = CNTPCT_EL0.get() * NS_PER_S; Duration::from_nanos(current_count / frq) } diff --git a/11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/time.rs b/11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/time.rs index 3a766009..63017305 100644 --- a/11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/time.rs +++ b/11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/time.rs @@ -13,7 +13,7 @@ use crate::{time, warn}; use core::time::Duration; -use cortex_a::regs::*; +use cortex_a::{barrier, regs::*}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -30,6 +30,19 @@ struct GenericTimer; static TIME_MANAGER: GenericTimer = GenericTimer; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl GenericTimer { + #[inline(always)] + fn read_cntpct(&self) -> u64 { + // Prevent that the counter is read ahead of time due to out-of-order execution. + unsafe { barrier::isb(barrier::SY) }; + CNTPCT_EL0.get() + } +} + //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- @@ -49,8 +62,8 @@ impl time::interface::TimeManager for GenericTimer { } fn uptime(&self) -> Duration { + let current_count: u64 = self.read_cntpct() * NS_PER_S; let frq: u64 = CNTFRQ_EL0.get() as u64; - let current_count: u64 = CNTPCT_EL0.get() * NS_PER_S; Duration::from_nanos(current_count / frq) } diff --git a/12_exceptions_part1_groundwork/src/_arch/aarch64/time.rs b/12_exceptions_part1_groundwork/src/_arch/aarch64/time.rs index 3a766009..63017305 100644 --- a/12_exceptions_part1_groundwork/src/_arch/aarch64/time.rs +++ b/12_exceptions_part1_groundwork/src/_arch/aarch64/time.rs @@ -13,7 +13,7 @@ use crate::{time, warn}; use core::time::Duration; -use cortex_a::regs::*; +use cortex_a::{barrier, regs::*}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -30,6 +30,19 @@ struct GenericTimer; static TIME_MANAGER: GenericTimer = GenericTimer; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl GenericTimer { + #[inline(always)] + fn read_cntpct(&self) -> u64 { + // Prevent that the counter is read ahead of time due to out-of-order execution. + unsafe { barrier::isb(barrier::SY) }; + CNTPCT_EL0.get() + } +} + //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- @@ -49,8 +62,8 @@ impl time::interface::TimeManager for GenericTimer { } fn uptime(&self) -> Duration { + let current_count: u64 = self.read_cntpct() * NS_PER_S; let frq: u64 = CNTFRQ_EL0.get() as u64; - let current_count: u64 = CNTPCT_EL0.get() * NS_PER_S; Duration::from_nanos(current_count / frq) } diff --git a/13_integrated_testing/src/_arch/aarch64/time.rs b/13_integrated_testing/src/_arch/aarch64/time.rs index 3a766009..63017305 100644 --- a/13_integrated_testing/src/_arch/aarch64/time.rs +++ b/13_integrated_testing/src/_arch/aarch64/time.rs @@ -13,7 +13,7 @@ use crate::{time, warn}; use core::time::Duration; -use cortex_a::regs::*; +use cortex_a::{barrier, regs::*}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -30,6 +30,19 @@ struct GenericTimer; static TIME_MANAGER: GenericTimer = GenericTimer; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl GenericTimer { + #[inline(always)] + fn read_cntpct(&self) -> u64 { + // Prevent that the counter is read ahead of time due to out-of-order execution. + unsafe { barrier::isb(barrier::SY) }; + CNTPCT_EL0.get() + } +} + //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- @@ -49,8 +62,8 @@ impl time::interface::TimeManager for GenericTimer { } fn uptime(&self) -> Duration { + let current_count: u64 = self.read_cntpct() * NS_PER_S; let frq: u64 = CNTFRQ_EL0.get() as u64; - let current_count: u64 = CNTPCT_EL0.get() * NS_PER_S; Duration::from_nanos(current_count / frq) } diff --git a/14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/time.rs b/14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/time.rs index 3a766009..63017305 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/time.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/time.rs @@ -13,7 +13,7 @@ use crate::{time, warn}; use core::time::Duration; -use cortex_a::regs::*; +use cortex_a::{barrier, regs::*}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -30,6 +30,19 @@ struct GenericTimer; static TIME_MANAGER: GenericTimer = GenericTimer; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl GenericTimer { + #[inline(always)] + fn read_cntpct(&self) -> u64 { + // Prevent that the counter is read ahead of time due to out-of-order execution. + unsafe { barrier::isb(barrier::SY) }; + CNTPCT_EL0.get() + } +} + //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- @@ -49,8 +62,8 @@ impl time::interface::TimeManager for GenericTimer { } fn uptime(&self) -> Duration { + let current_count: u64 = self.read_cntpct() * NS_PER_S; let frq: u64 = CNTFRQ_EL0.get() as u64; - let current_count: u64 = CNTPCT_EL0.get() * NS_PER_S; Duration::from_nanos(current_count / frq) } diff --git a/15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/time.rs b/15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/time.rs index 3a766009..63017305 100644 --- a/15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/time.rs +++ b/15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/time.rs @@ -13,7 +13,7 @@ use crate::{time, warn}; use core::time::Duration; -use cortex_a::regs::*; +use cortex_a::{barrier, regs::*}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -30,6 +30,19 @@ struct GenericTimer; static TIME_MANAGER: GenericTimer = GenericTimer; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl GenericTimer { + #[inline(always)] + fn read_cntpct(&self) -> u64 { + // Prevent that the counter is read ahead of time due to out-of-order execution. + unsafe { barrier::isb(barrier::SY) }; + CNTPCT_EL0.get() + } +} + //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- @@ -49,8 +62,8 @@ impl time::interface::TimeManager for GenericTimer { } fn uptime(&self) -> Duration { + let current_count: u64 = self.read_cntpct() * NS_PER_S; let frq: u64 = CNTFRQ_EL0.get() as u64; - let current_count: u64 = CNTPCT_EL0.get() * NS_PER_S; Duration::from_nanos(current_count / frq) } diff --git a/X1_JTAG_boot/jtag_boot_rpi3.img b/X1_JTAG_boot/jtag_boot_rpi3.img index 9f8ada21..4cd44015 100755 Binary files a/X1_JTAG_boot/jtag_boot_rpi3.img and b/X1_JTAG_boot/jtag_boot_rpi3.img differ diff --git a/X1_JTAG_boot/jtag_boot_rpi4.img b/X1_JTAG_boot/jtag_boot_rpi4.img index e9d7e7dd..c7535115 100755 Binary files a/X1_JTAG_boot/jtag_boot_rpi4.img and b/X1_JTAG_boot/jtag_boot_rpi4.img differ diff --git a/X1_JTAG_boot/src/_arch/aarch64/time.rs b/X1_JTAG_boot/src/_arch/aarch64/time.rs index 3a766009..63017305 100644 --- a/X1_JTAG_boot/src/_arch/aarch64/time.rs +++ b/X1_JTAG_boot/src/_arch/aarch64/time.rs @@ -13,7 +13,7 @@ use crate::{time, warn}; use core::time::Duration; -use cortex_a::regs::*; +use cortex_a::{barrier, regs::*}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -30,6 +30,19 @@ struct GenericTimer; static TIME_MANAGER: GenericTimer = GenericTimer; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl GenericTimer { + #[inline(always)] + fn read_cntpct(&self) -> u64 { + // Prevent that the counter is read ahead of time due to out-of-order execution. + unsafe { barrier::isb(barrier::SY) }; + CNTPCT_EL0.get() + } +} + //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- @@ -49,8 +62,8 @@ impl time::interface::TimeManager for GenericTimer { } fn uptime(&self) -> Duration { + let current_count: u64 = self.read_cntpct() * NS_PER_S; let frq: u64 = CNTFRQ_EL0.get() as u64; - let current_count: u64 = CNTPCT_EL0.get() * NS_PER_S; Duration::from_nanos(current_count / frq) }