Nothing to see here, move along meow
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 1.8 kB View raw
1static TSC_FREQ_HZ: spin::Once<u64> = spin::Once::new(); 2 3#[inline] 4pub fn read_tsc() -> u64 { 5 unsafe { core::arch::x86_64::_rdtsc() } 6} 7 8#[inline] 9pub fn read_tsc_fenced() -> u64 { 10 unsafe { 11 core::arch::x86_64::__cpuid(0); 12 core::arch::x86_64::_rdtsc() 13 } 14} 15 16struct Pit { 17 cmd: x86_64::instructions::port::Port<u8>, 18 data: x86_64::instructions::port::Port<u8>, 19} 20 21impl Pit { 22 fn channel0() -> Self { 23 Self { 24 cmd: x86_64::instructions::port::Port::<u8>::new(0x43), 25 data: x86_64::instructions::port::Port::<u8>::new(0x40), 26 } 27 } 28 29 fn start_oneshot(&mut self, count: u16) { 30 unsafe { 31 self.cmd.write(0x30); 32 self.data.write((count & 0xFF) as u8); 33 self.data.write(((count >> 8) & 0xFF) as u8); 34 } 35 } 36 37 fn poll_done(&mut self) -> bool { 38 unsafe { 39 self.cmd.write(0xE2); 40 self.data.read() & 0x80 != 0 41 } 42 } 43} 44 45pub fn calibrate() { 46 let pit_hz: u64 = 1_193_182; 47 let target_ms: u64 = 10; 48 let pit_count: u16 = (pit_hz * target_ms / 1000) as u16; 49 50 let mut pit = Pit::channel0(); 51 pit.start_oneshot(pit_count); 52 53 let start = read_tsc_fenced(); 54 55 const MAX_PIT_POLLS: u32 = 10_000_000; 56 let mut polls: u32 = 0; 57 while !pit.poll_done() { 58 polls += 1; 59 assert!(polls < MAX_PIT_POLLS, "PIT calibration timeout"); 60 } 61 62 let end = read_tsc_fenced(); 63 let elapsed = end - start; 64 let freq_hz = elapsed * 1000 / target_ms; 65 66 TSC_FREQ_HZ.call_once(|| freq_hz); 67} 68 69pub fn freq_hz() -> u64 { 70 *TSC_FREQ_HZ.get().expect("TSC not calibrated") 71} 72 73pub fn cycles_to_ns(cycles: u64) -> u64 { 74 let f = freq_hz(); 75 ((cycles as u128) * 1_000_000_000 / (f as u128)) as u64 76}