From 2052cc8cdc07b3dff5b73a6a00bcadb9d1ea0e1d Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Mon, 14 Nov 2022 11:12:44 -0700 Subject: [PATCH] Allow arch to provide higher precision time --- src/arch/aarch64/mod.rs | 2 ++ src/arch/aarch64/time.rs | 4 ++++ src/arch/x86/device/hpet.rs | 34 +++++++++++++++++----------------- src/arch/x86/device/pit.rs | 18 +++++++++++------- src/arch/x86/mod.rs | 2 ++ src/arch/x86/time.rs | 16 ++++++++++++++++ src/arch/x86_64/device/hpet.rs | 34 +++++++++++++++++----------------- src/arch/x86_64/device/pit.rs | 18 +++++++++++------- src/arch/x86_64/mod.rs | 2 ++ src/arch/x86_64/time.rs | 16 ++++++++++++++++ src/time.rs | 2 +- 11 files changed, 99 insertions(+), 49 deletions(-) create mode 100644 src/arch/aarch64/time.rs create mode 100644 src/arch/x86/time.rs create mode 100644 src/arch/x86_64/time.rs diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index 1fd62895..0f353b39 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -33,4 +33,6 @@ pub mod vectors; /// Early init support pub mod init; +pub mod time; + pub use ::rmm::AArch64Arch as CurrentRmmArch; diff --git a/src/arch/aarch64/time.rs b/src/arch/aarch64/time.rs new file mode 100644 index 00000000..60809b40 --- /dev/null +++ b/src/arch/aarch64/time.rs @@ -0,0 +1,4 @@ +pub fn counter() -> u128 { + //TODO: aarch64 generic timer counter + 0 +} diff --git a/src/arch/x86/device/hpet.rs b/src/arch/x86/device/hpet.rs index 1ab3ce9f..40d7d4e0 100644 --- a/src/arch/x86/device/hpet.rs +++ b/src/arch/x86/device/hpet.rs @@ -1,22 +1,22 @@ use crate::acpi::hpet::Hpet; -static LEG_RT_CNF: u64 = 2; -static ENABLE_CNF: u64 = 1; - -static TN_VAL_SET_CNF: u64 = 0x40; -static TN_TYPE_CNF: u64 = 0x08; -static TN_INT_ENB_CNF: u64 = 0x04; - -static CAPABILITY_OFFSET: usize = 0x00; -static GENERAL_CONFIG_OFFSET: usize = 0x10; -static GENERAL_INTERRUPT_OFFSET: usize = 0x20; -static MAIN_COUNTER_OFFSET: usize = 0xF0; -// static NUM_TIMER_CAP_MASK: u64 = 0x0f00; -static LEG_RT_CAP: u64 = 0x8000; -static T0_CONFIG_CAPABILITY_OFFSET: usize = 0x100; -static T0_COMPARATOR_OFFSET: usize = 0x108; - -static PER_INT_CAP: u64 = 0x10; +const LEG_RT_CNF: u64 = 2; +const ENABLE_CNF: u64 = 1; + +const TN_VAL_SET_CNF: u64 = 0x40; +const TN_TYPE_CNF: u64 = 0x08; +const TN_INT_ENB_CNF: u64 = 0x04; + +pub(crate) const CAPABILITY_OFFSET: usize = 0x00; +const GENERAL_CONFIG_OFFSET: usize = 0x10; +const GENERAL_INTERRUPT_OFFSET: usize = 0x20; +pub(crate) const MAIN_COUNTER_OFFSET: usize = 0xF0; +// const NUM_TIMER_CAP_MASK: u64 = 0x0f00; +const LEG_RT_CAP: u64 = 0x8000; +const T0_CONFIG_CAPABILITY_OFFSET: usize = 0x100; +const T0_COMPARATOR_OFFSET: usize = 0x108; + +const PER_INT_CAP: u64 = 0x10; pub unsafe fn init(hpet: &mut Hpet) -> bool { println!("HPET Before Init"); diff --git a/src/arch/x86/device/pit.rs b/src/arch/x86/device/pit.rs index 7c96be16..fdf54a14 100644 --- a/src/arch/x86/device/pit.rs +++ b/src/arch/x86/device/pit.rs @@ -5,20 +5,24 @@ pub static mut CHAN1: Pio<u8> = Pio::new(0x41); pub static mut CHAN2: Pio<u8> = Pio::new(0x42); pub static mut COMMAND: Pio<u8> = Pio::new(0x43); -static SELECT_CHAN0: u8 = 0; -static LOHI: u8 = 0x30; +const SELECT_CHAN0: u8 = 0b00 << 6; +const ACCESS_LATCH: u8 = 0b00 << 4; +const ACCESS_LOHI: u8 = 0b11 << 4; +const MODE_2: u8 = 0b010 << 1; -static CHAN0_DIVISOR: u16 = 2685; +const CHAN0_DIVISOR: u16 = 2685; pub unsafe fn init() { - COMMAND.write(SELECT_CHAN0 | LOHI | 5); - CHAN0.write((CHAN0_DIVISOR & 0xFF) as u8); + COMMAND.write(SELECT_CHAN0 | ACCESS_LOHI | MODE_2); + CHAN0.write(CHAN0_DIVISOR as u8); CHAN0.write((CHAN0_DIVISOR >> 8) as u8); } pub unsafe fn read() -> u16 { - COMMAND.write(SELECT_CHAN0 | 0); + COMMAND.write(SELECT_CHAN0 | ACCESS_LATCH); let low = CHAN0.read(); let high = CHAN0.read(); - ((high as u16) << 8) | (low as u16) + let counter = ((high as u16) << 8) | (low as u16); + // Counter is inverted, subtract from CHAN0_DIVISOR + CHAN0_DIVISOR.saturating_sub(counter) } diff --git a/src/arch/x86/mod.rs b/src/arch/x86/mod.rs index df27301e..4c294ef1 100644 --- a/src/arch/x86/mod.rs +++ b/src/arch/x86/mod.rs @@ -40,6 +40,8 @@ pub mod start; /// Stop function pub mod stop; +pub mod time; + pub use ::rmm::X86Arch as CurrentRmmArch; // Flags diff --git a/src/arch/x86/time.rs b/src/arch/x86/time.rs new file mode 100644 index 00000000..ca1fa5ee --- /dev/null +++ b/src/arch/x86/time.rs @@ -0,0 +1,16 @@ +use crate::acpi::ACPI_TABLE; +use super::device::{hpet, pit}; + +pub fn counter() -> u128 { + if let Some(ref hpet) = *ACPI_TABLE.hpet.read() { + let capability = unsafe { hpet.base_address.read_u64(hpet::CAPABILITY_OFFSET) }; + let period_fs = (capability >> 32) as u128; + let counter = unsafe { hpet.base_address.read_u64(hpet::MAIN_COUNTER_OFFSET) }; + (counter as u128 * period_fs) / 1_000_000 + } else { + // 1.193182 MHz PIT is approximately 838.095 nanoseconds + let period_ns = 838; + let counter = unsafe { pit::read() }; + counter as u128 * period_ns + } +} diff --git a/src/arch/x86_64/device/hpet.rs b/src/arch/x86_64/device/hpet.rs index 1ab3ce9f..40d7d4e0 100644 --- a/src/arch/x86_64/device/hpet.rs +++ b/src/arch/x86_64/device/hpet.rs @@ -1,22 +1,22 @@ use crate::acpi::hpet::Hpet; -static LEG_RT_CNF: u64 = 2; -static ENABLE_CNF: u64 = 1; - -static TN_VAL_SET_CNF: u64 = 0x40; -static TN_TYPE_CNF: u64 = 0x08; -static TN_INT_ENB_CNF: u64 = 0x04; - -static CAPABILITY_OFFSET: usize = 0x00; -static GENERAL_CONFIG_OFFSET: usize = 0x10; -static GENERAL_INTERRUPT_OFFSET: usize = 0x20; -static MAIN_COUNTER_OFFSET: usize = 0xF0; -// static NUM_TIMER_CAP_MASK: u64 = 0x0f00; -static LEG_RT_CAP: u64 = 0x8000; -static T0_CONFIG_CAPABILITY_OFFSET: usize = 0x100; -static T0_COMPARATOR_OFFSET: usize = 0x108; - -static PER_INT_CAP: u64 = 0x10; +const LEG_RT_CNF: u64 = 2; +const ENABLE_CNF: u64 = 1; + +const TN_VAL_SET_CNF: u64 = 0x40; +const TN_TYPE_CNF: u64 = 0x08; +const TN_INT_ENB_CNF: u64 = 0x04; + +pub(crate) const CAPABILITY_OFFSET: usize = 0x00; +const GENERAL_CONFIG_OFFSET: usize = 0x10; +const GENERAL_INTERRUPT_OFFSET: usize = 0x20; +pub(crate) const MAIN_COUNTER_OFFSET: usize = 0xF0; +// const NUM_TIMER_CAP_MASK: u64 = 0x0f00; +const LEG_RT_CAP: u64 = 0x8000; +const T0_CONFIG_CAPABILITY_OFFSET: usize = 0x100; +const T0_COMPARATOR_OFFSET: usize = 0x108; + +const PER_INT_CAP: u64 = 0x10; pub unsafe fn init(hpet: &mut Hpet) -> bool { println!("HPET Before Init"); diff --git a/src/arch/x86_64/device/pit.rs b/src/arch/x86_64/device/pit.rs index 7c96be16..fdf54a14 100644 --- a/src/arch/x86_64/device/pit.rs +++ b/src/arch/x86_64/device/pit.rs @@ -5,20 +5,24 @@ pub static mut CHAN1: Pio<u8> = Pio::new(0x41); pub static mut CHAN2: Pio<u8> = Pio::new(0x42); pub static mut COMMAND: Pio<u8> = Pio::new(0x43); -static SELECT_CHAN0: u8 = 0; -static LOHI: u8 = 0x30; +const SELECT_CHAN0: u8 = 0b00 << 6; +const ACCESS_LATCH: u8 = 0b00 << 4; +const ACCESS_LOHI: u8 = 0b11 << 4; +const MODE_2: u8 = 0b010 << 1; -static CHAN0_DIVISOR: u16 = 2685; +const CHAN0_DIVISOR: u16 = 2685; pub unsafe fn init() { - COMMAND.write(SELECT_CHAN0 | LOHI | 5); - CHAN0.write((CHAN0_DIVISOR & 0xFF) as u8); + COMMAND.write(SELECT_CHAN0 | ACCESS_LOHI | MODE_2); + CHAN0.write(CHAN0_DIVISOR as u8); CHAN0.write((CHAN0_DIVISOR >> 8) as u8); } pub unsafe fn read() -> u16 { - COMMAND.write(SELECT_CHAN0 | 0); + COMMAND.write(SELECT_CHAN0 | ACCESS_LATCH); let low = CHAN0.read(); let high = CHAN0.read(); - ((high as u16) << 8) | (low as u16) + let counter = ((high as u16) << 8) | (low as u16); + // Counter is inverted, subtract from CHAN0_DIVISOR + CHAN0_DIVISOR.saturating_sub(counter) } diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 5dc0fd1a..ca21bb51 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -40,6 +40,8 @@ pub mod start; /// Stop function pub mod stop; +pub mod time; + pub use ::rmm::X8664Arch as CurrentRmmArch; // Flags diff --git a/src/arch/x86_64/time.rs b/src/arch/x86_64/time.rs new file mode 100644 index 00000000..ca1fa5ee --- /dev/null +++ b/src/arch/x86_64/time.rs @@ -0,0 +1,16 @@ +use crate::acpi::ACPI_TABLE; +use super::device::{hpet, pit}; + +pub fn counter() -> u128 { + if let Some(ref hpet) = *ACPI_TABLE.hpet.read() { + let capability = unsafe { hpet.base_address.read_u64(hpet::CAPABILITY_OFFSET) }; + let period_fs = (capability >> 32) as u128; + let counter = unsafe { hpet.base_address.read_u64(hpet::MAIN_COUNTER_OFFSET) }; + (counter as u128 * period_fs) / 1_000_000 + } else { + // 1.193182 MHz PIT is approximately 838.095 nanoseconds + let period_ns = 838; + let counter = unsafe { pit::read() }; + counter as u128 * period_ns + } +} diff --git a/src/time.rs b/src/time.rs index 75717f2f..3d82c390 100644 --- a/src/time.rs +++ b/src/time.rs @@ -8,7 +8,7 @@ pub static START: Mutex<u128> = Mutex::new(0); pub static OFFSET: Mutex<u128> = Mutex::new(0); pub fn monotonic() -> u128 { - *OFFSET.lock() + *OFFSET.lock() + crate::arch::time::counter() } pub fn realtime() -> u128 { -- GitLab