x86-64: keep HPET enabled even without interrupts

This commit is contained in:
Mark Poliakov 2023-08-31 09:25:46 +03:00
parent 9c419115e7
commit 9b9a1f68b5

View File

@ -107,6 +107,9 @@ pub struct Hpet {
impl Inner {
unsafe fn new(base: usize) -> Result<Self, Error> {
// Femtoseconds in a millisecond
const FS_IN_MS: u64 = 1000000000000;
let regs = DeviceMemoryIo::<Regs>::map("hpet", base)?;
// Disable the counter first
@ -127,9 +130,29 @@ impl Inner {
.modify(TimerConfigurationCapablities::TM_INT_ENB_CNF::InterruptDisabled);
}
// Calculate the interrupt period
let clk_period = regs
.GeneralCapabilities
.read(GeneralCapabilities::COUNTER_CLK_PERIOD);
// Will give an interrupt interval of 1ms
let tim0_period = FS_IN_MS / clk_period;
// if tim0_period > 0x100000000
// && !tim0
// .ConfigurationCapability
// .matches_all(TimerConfigurationCapablities::TM_SIZE_CAP::Timer64Bit)
// {
// panic!("Period is too large and timer doesn't support 64-bit");
// }
// Enable the main counter
regs.GeneralConfiguration
.modify(GeneralConfiguration::ENABLE_CNF::SET);
Ok(Self {
regs,
tim0_period: 0,
tim0_period,
tim0_counter: 0,
})
}
@ -138,7 +161,9 @@ impl Inner {
impl MonotonicTimestampProviderDevice for Hpet {
fn monotonic_timestamp(&self) -> Result<Duration, Error> {
let inner = self.inner.lock();
Ok(Duration::from_millis(inner.tim0_counter))
let counter = inner.regs.MainCounter.get();
let period = inner.tim0_period;
Ok(Duration::from_millis(counter / period))
}
}
@ -165,38 +190,22 @@ impl Device for Hpet {
}
unsafe fn init_irq(&'static self) -> Result<(), Error> {
// Femtoseconds in a millisecond
const FS_IN_MS: u64 = 1000000000000;
// Configure timer 0
let intc = ARCHITECTURE.external_interrupt_controller();
let mut inner = self.inner.lock();
// Calculate the interrupt period
let clk_period = inner
.regs
.GeneralCapabilities
.read(GeneralCapabilities::COUNTER_CLK_PERIOD);
// Will give an interrupt interval of 1ms
let period = FS_IN_MS / clk_period;
inner.tim0_period = period;
let tim0 = &inner.regs.Timers[0];
// Temporarily disable the main counter
inner
.regs
.GeneralConfiguration
.modify(GeneralConfiguration::ENABLE_CNF::CLEAR);
assert!(tim0
.ConfigurationCapability
.matches_all(TimerConfigurationCapablities::TM_PER_INT_CAP::SupportsPeriodic));
if period > 0x100000000
&& !tim0
.ConfigurationCapability
.matches_all(TimerConfigurationCapablities::TM_SIZE_CAP::Timer64Bit)
{
panic!("Period is too large and timer doesn't support 64-bit");
}
let mut tim0_irq = None;
let tim0_irqs = tim0
.ConfigurationCapability
@ -247,7 +256,7 @@ impl Device for Hpet {
tim0.ConfigurationCapability
.modify(TimerConfigurationCapablities::TM_INT_ENB_CNF::InterruptEnabled);
// Enable the main counter
// Reenable the main counter
inner
.regs
.GeneralConfiguration