1use core::u64;
2
3#[cfg(target_arch = "x86_64")]
4pub use x64::X64 as Arch;
5
6#[cfg(target_arch = "aarch64")]
7pub use aarch64::Aarch64 as Arch;
8
9pub trait ArchFunctionality {
10 fn cpu_count() -> u64;
12 fn cpu_count_frequency() -> u64;
14 fn cpu_count_start() -> u64 {
16 0
17 }
18 fn cpu_count_end() -> u64 {
20 u64::MAX
21 }
22}
23
24#[cfg(target_arch = "x86_64")]
25pub(crate) mod x64 {
26 use super::*;
27 use core::arch::x86_64::{self, CpuidResult};
28
29 pub struct X64;
30 impl ArchFunctionality for X64 {
31 fn cpu_count() -> u64 {
32 #[cfg(feature = "validate_cpu_features")]
33 {
34 if (unsafe { x86_64::__cpuid(0x01) }.edx & 0x10) != 0x10 {
36 panic!("CPU does not support TSC");
37 }
38 if (unsafe { x86_64::__cpuid(0x80000007) }.edx & 0x100) != 0x100 {
40 panic!("CPU does not support Invariant TSC");
41 }
42 }
43 unsafe { x86_64::_rdtsc() }
44 }
45
46 fn cpu_count_frequency() -> u64 {
47 let CpuidResult {
49 eax, ebx, ecx, ..
53 } = unsafe { x86_64::__cpuid(0x15) };
54
55 #[cfg(feature = "validate_cpu_features")]
56 if ecx == 0 {
57 panic!("CPU does not support CPUID-based frequency determination");
58 }
59
60 (ecx * (ebx / eax)) as u64
61 }
62 }
63}
64
65#[cfg(target_arch = "aarch64")]
66pub(crate) mod aarch64 {
67 use super::*;
68 use aarch64_cpu::registers::{self, Readable};
69 pub struct Aarch64;
70 impl ArchFunctionality for Aarch64 {
71 fn cpu_count() -> u64 {
72 registers::CNTPCT_EL0.get()
73 }
74
75 fn cpu_count_frequency() -> u64 {
76 registers::CNTFRQ_EL0.get()
77 }
78 }
79}