From e88e7d6df1c665694b3e3358591ec4b839b474f3 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Mon, 25 Apr 2022 15:08:09 -0600
Subject: [PATCH] Fix HPET on real hardware with better debugging

---
 src/arch/x86_64/device/hpet.rs | 66 ++++++++++++++++++++++------------
 1 file changed, 44 insertions(+), 22 deletions(-)

diff --git a/src/arch/x86_64/device/hpet.rs b/src/arch/x86_64/device/hpet.rs
index 72374a3d..12227796 100644
--- a/src/arch/x86_64/device/hpet.rs
+++ b/src/arch/x86_64/device/hpet.rs
@@ -9,8 +9,8 @@ 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 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;
@@ -19,25 +19,17 @@ static T0_COMPARATOR_OFFSET: usize = 0x108;
 static PER_INT_CAP: u64 = 0x10;
 
 pub unsafe fn init(hpet: &mut Hpet) -> bool {
+    println!("HPET Before Init");
+    debug(hpet);
+
     // Disable HPET
     {
         let mut config_word = hpet.base_address.read_u64(GENERAL_CONFIG_OFFSET);
-        log::info!("HPET config old: {:#x}", config_word);
-        config_word &= !ENABLE_CNF;
-        log::info!("HPET config new: {:#x}", config_word);
+        config_word &= !(LEG_RT_CNF | ENABLE_CNF);
         hpet.base_address.write_u64(GENERAL_CONFIG_OFFSET, config_word);
     }
 
     let capability = hpet.base_address.read_u64(CAPABILITY_OFFSET);
-    {
-        log::info!("HPET caps: {:#x}", capability);
-        log::info!("HPET caps clock period: {}", (capability >> 32) as u32);
-        log::info!("HPET caps ID: {:#x}", (capability >> 16) as u16);
-        log::info!("HPET caps LEG_RT_CAP: {}", capability & (1 << 15) == (1 << 15));
-        log::info!("HPET caps COUNT_SIZE_CAP: {}", capability & (1 << 13) == (1 << 13));
-        log::info!("HPET caps timers: {}", (capability >> 8) as u8 & 0x1F);
-        log::info!("HPET caps revision: {}", capability as u8);
-    }
     if capability & LEG_RT_CAP == 0 {
         log::warn!("HPET missing capability LEG_RT_CAP");
         return false;
@@ -49,31 +41,61 @@ pub unsafe fn init(hpet: &mut Hpet) -> bool {
     let clk_periods_per_kernel_tick: u64 = desired_fs_period / counter_clk_period_fs;
 
     let t0_capabilities = hpet.base_address.read_u64(T0_CONFIG_CAPABILITY_OFFSET);
-    {
-        log::info!("HPET T0 caps: {:#x}", t0_capabilities);
-        log::info!("HPET T0 caps interrupt routing: {:#x}", (t0_capabilities >> 32) as u32);
-        log::info!("HPET T0 caps flags: {:#x}", t0_capabilities as u16);
-    }
     if t0_capabilities & PER_INT_CAP == 0 {
         log::warn!("HPET T0 missing capability PER_INT_CAP");
         return false;
     }
 
+    let counter = hpet.base_address.read_u64(MAIN_COUNTER_OFFSET);
+
     let t0_config_word: u64 = TN_VAL_SET_CNF | TN_TYPE_CNF | TN_INT_ENB_CNF;
     hpet.base_address.write_u64(T0_CONFIG_CAPABILITY_OFFSET, t0_config_word);
     // set accumulator value
-    hpet.base_address.write_u64(T0_COMPARATOR_OFFSET, clk_periods_per_kernel_tick);
+    hpet.base_address.write_u64(T0_COMPARATOR_OFFSET, counter + clk_periods_per_kernel_tick);
     // set interval
     hpet.base_address.write_u64(T0_COMPARATOR_OFFSET, clk_periods_per_kernel_tick);
 
     // Enable interrupts from the HPET
     {
         let mut config_word: u64 = hpet.base_address.read_u64(GENERAL_CONFIG_OFFSET);
-        log::info!("HPET config old: {:#x}", config_word);
         config_word |= LEG_RT_CNF | ENABLE_CNF;
-        log::info!("HPET config new: {:#x}", config_word);
         hpet.base_address.write_u64(GENERAL_CONFIG_OFFSET, config_word);
     }
 
+    println!("HPET After Init");
+    debug(hpet);
+
     true
 }
+
+pub unsafe fn debug(hpet: &mut Hpet) {
+    println!("HPET @ {:#x}", hpet.base_address.address);
+
+    let capability = hpet.base_address.read_u64(CAPABILITY_OFFSET);
+    {
+        println!("  caps: {:#x}", capability);
+        println!("    clock period: {}", (capability >> 32) as u32);
+        println!("    ID: {:#x}", (capability >> 16) as u16);
+        println!("    LEG_RT_CAP: {}", capability & (1 << 15) == (1 << 15));
+        println!("    COUNT_SIZE_CAP: {}", capability & (1 << 13) == (1 << 13));
+        println!("    timers: {}", (capability >> 8) as u8 & 0x1F);
+        println!("    revision: {}", capability as u8);
+    }
+
+    let config_word = hpet.base_address.read_u64(GENERAL_CONFIG_OFFSET);
+    println!("  config: {:#x}", config_word);
+
+    let interrupt_status = hpet.base_address.read_u64(GENERAL_INTERRUPT_OFFSET);
+    println!("  interrupt status: {:#x}", interrupt_status);
+
+    let counter = hpet.base_address.read_u64(MAIN_COUNTER_OFFSET);
+    println!("  counter: {:#x}", counter);
+
+    let t0_capabilities = hpet.base_address.read_u64(T0_CONFIG_CAPABILITY_OFFSET);
+    println!("  T0 caps: {:#x}", t0_capabilities);
+    println!("    interrupt routing: {:#x}", (t0_capabilities >> 32) as u32);
+    println!("    flags: {:#x}", t0_capabilities as u16);
+
+    let t0_comparator = hpet.base_address.read_u64(T0_COMPARATOR_OFFSET);
+    println!("  T0 comparator: {:#x}", t0_comparator);
+}
-- 
GitLab