mielin_hal/lib.rs
1//! MielinOS Hardware Abstraction Layer
2//!
3//! A `no_std` hardware abstraction layer providing unified interfaces across
4//! x86_64, AArch64, RISC-V, and ARM Cortex-M architectures.
5//!
6//! ## Quick Start
7//!
8//! ```no_run
9//! use mielin_hal::{detect_architecture, capabilities, cache, system};
10//!
11//! // Detect architecture
12//! let arch = detect_architecture();
13//! println!("Running on: {}", arch);
14//!
15//! // Get hardware capabilities
16//! let profile = capabilities::HardwareProfile::detect();
17//! println!("Cores: {}, Memory: {} MB", profile.core_count, profile.memory_size / 1024 / 1024);
18//!
19//! // Cache information
20//! let cache = cache::CacheTopology::detect();
21//! println!("L1: {} KB", cache.l1_total_size() / 1024);
22//! ```
23//!
24//! ## Modules
25//!
26//! - [`arch`]: Architecture-specific implementations (x86_64, AArch64, RISC-V, Cortex-M)
27//! - [`capabilities`]: SIMD and hardware feature detection
28//! - [`cache`]: Cache topology and size information
29//! - [`system`]: Memory and CPU topology
30//! - [`platform`]: Platform-specific detection (Raspberry Pi, STM32, ESP32, BeagleBone)
31//! - [`gpu`]: GPU detection and capabilities
32//! - [`accelerator`]: NPU/TPU accelerator detection
33//! - [`power`]: Power management and frequency information
34//! - [`pmu`]: Performance Monitoring Unit (PMU) and hardware counters
35//! - [`virtualization`]: Hypervisor and container detection
36//! - [`devicetree`]: Device Tree parsing and querying
37//! - [`acpi`]: ACPI table parsing and hardware enumeration
38//! - [`runtime`]: Runtime capability switching and optimal path selection
39//! - [`error`]: Error types and handling
40//! - [`traits`]: Common trait abstractions
41//!
42//! ## Common Use Cases
43//!
44//! ### SIMD Feature Detection
45//!
46//! ```no_run
47//! use mielin_hal::capabilities::{HardwareProfile, HardwareCapabilities};
48//!
49//! let caps = HardwareProfile::detect();
50//!
51//! // x86_64
52//! if caps.capabilities.contains(HardwareCapabilities::AVX2) {
53//! println!("AVX2 available for 256-bit SIMD");
54//! }
55//!
56//! // AArch64
57//! if caps.capabilities.contains(HardwareCapabilities::SVE) {
58//! println!("SVE available with {} -bit vectors", caps.max_vector_width());
59//! }
60//!
61//! // RISC-V (note: RVV feature flag not yet added, use NEON as placeholder)
62//! if caps.capabilities.contains(HardwareCapabilities::NEON) {
63//! println!("Vector extension available");
64//! }
65//! ```
66//!
67//! ### Platform-Specific Code
68//!
69//! ```no_run
70//! use mielin_hal::platform::{detect_platform, Platform, RaspberryPiCapabilities};
71//!
72//! match detect_platform() {
73//! Platform::RaspberryPi(model) => {
74//! let caps = RaspberryPiCapabilities::detect();
75//! println!("Raspberry Pi {} with {} GPIO pins", model, caps.gpio_pins);
76//! }
77//! Platform::Stm32(family) => {
78//! println!("STM32{} microcontroller", family);
79//! }
80//! Platform::Esp32(variant) => {
81//! println!("ESP32 {} with WiFi/Bluetooth", variant);
82//! }
83//! _ => println!("Generic platform"),
84//! }
85//! ```
86//!
87//! ### Cache-Aware Optimization
88//!
89//! ```no_run
90//! use mielin_hal::cache::CacheTopology;
91//!
92//! let cache = CacheTopology::detect();
93//! let l1_size = cache.l1_total_size();
94//!
95//! // Use cache size for optimization
96//! println!("L1 cache: {} KB", l1_size / 1024);
97//! ```
98//!
99//! ### Power Management
100//!
101//! ```no_run
102//! use mielin_hal::power::detect_power_info;
103//!
104//! let power = detect_power_info();
105//! println!("CPU: {} - {} MHz", power.frequency.min_mhz, power.frequency.max_mhz);
106//!
107//! if power.turbo_supported {
108//! println!("Turbo boost available");
109//! }
110//! ```
111//!
112//! ## Architecture Coverage
113//!
114//! | Architecture | Detection | SIMD | Caches | Platform | Power |
115//! |--------------|-----------|------|--------|----------|-------|
116//! | x86_64 | ✓ | ✓ | ✓ | Generic | ✓ |
117//! | AArch64 | ✓ | ✓ | ✓ | RPi, BB | Partial |
118//! | RISC-V | ✓ | ✓ | ✓ | Generic | Partial |
119//! | Cortex-M | ✓ | Partial | ✓ | STM32, ESP32 | Limited |
120//!
121//! ## Common Traits
122//!
123//! The `traits` module provides common abstractions:
124//! - `Named` - For types with human-readable names
125//! - `DeviceInfo` - Basic device information
126//! - `ComputeDevice` - Compute-capable device interface
127//! - `MemoryDevice` - Memory information interface
128//! - `PowerDevice` - Power-aware device interface
129//!
130//! ## Safety Requirements for Architecture-Specific Code
131//!
132//! This crate contains architecture-specific code that directly accesses hardware
133//! registers and uses platform-specific instructions. When using this crate, the
134//! following safety requirements must be met:
135//!
136//! ### General Safety Requirements
137//!
138//! 1. **Correct Target Configuration**: The crate must be compiled with the correct
139//! target triple for your hardware. Mismatched configurations may result in
140//! undefined behavior or incorrect hardware access.
141//!
142//! 2. **Hardware Availability**: Detection functions assume the presence of standard
143//! hardware components (e.g., CPUID on x86_64, system registers on AArch64).
144//! Attempting to access non-existent hardware may cause faults.
145//!
146//! 3. **Privilege Level**: Some hardware detection requires specific privilege levels:
147//! - x86_64: CPUID is generally unprivileged, but some MSRs require ring 0
148//! - AArch64: System registers may require EL1 or higher
149//! - Cortex-M: Some registers require privileged mode
150//!
151//! ### Architecture-Specific Safety Requirements
152//!
153//! #### x86_64
154//!
155//! - **CPUID Instructions**: The crate uses inline assembly to execute CPUID instructions.
156//! These are safe on all x86_64 processors but may return different results based on
157//! the CPU vendor and model.
158//!
159//! - **Register Clobbering**: Inline assembly carefully preserves register state, but
160//! calling code should be aware of potential side effects.
161//!
162//! - **Feature Detection**: Capability detection via CPUID is inherently safe but may
163//! not reflect runtime state (e.g., features disabled by hypervisor).
164//!
165//! #### AArch64
166//!
167//! - **System Registers**: Reading system registers (e.g., CTR_EL0) requires appropriate
168//! exception level. The crate uses registers accessible from EL0 when possible.
169//!
170//! - **SVE/SME Detection**: Vector length detection assumes SVE/SME is enabled in the
171//! system. Accessing disabled vector units may cause undefined instruction exceptions.
172//!
173//! #### RISC-V
174//!
175//! - **CSR Access**: Control and Status Register access may require M-mode or S-mode.
176//! User-mode code may trap when accessing privileged CSRs.
177//!
178//! - **Vector Extension**: RVV detection assumes the vector extension is present and
179//! enabled. Accessing disabled vector units causes illegal instruction exceptions.
180//!
181//! #### Cortex-M
182//!
183//! - **Memory-Mapped Registers**: The Cortex-M module directly accesses memory-mapped
184//! peripheral registers. These accesses are safe ONLY when:
185//! - Running on actual Cortex-M hardware
186//! - The memory map matches standard Cortex-M layout (SCB at 0xE000_ED00)
187//! - The processor is in a valid state (not halted, not in fault handler)
188//!
189//! - **Privileged Operations**: Some register reads require privileged (Handler/Thread)
190//! mode. Unprivileged access may result in faults.
191//!
192//! - **MPU Considerations**: If the Memory Protection Unit (MPU) is enabled, it must
193//! allow read access to SCB/NVIC registers.
194//!
195//! ### Error Handling
196//!
197//! The crate provides error types via the `error` module to handle:
198//! - Unsupported architecture features
199//! - Detection failures
200//! - Invalid parameters
201//! - Hardware access errors
202//!
203//! Always check return values and handle errors appropriately in production code.
204//!
205//! ### Testing Safety
206//!
207//! When writing tests:
208//! - Use `#[cfg(target_arch = "...")]` to ensure tests only run on supported architectures
209//! - Stub out hardware access for unit tests when possible
210//! - Use integration tests on real hardware for validation
211//! - Be aware that tests in CI may run on different hardware than production
212//!
213//! ### Examples
214//!
215//! ```no_run
216//! use mielin_hal::{Architecture, detect_architecture, error::check_architecture_support};
217//!
218//! // Check if a feature is supported before using it
219//! let result = check_architecture_support(
220//! "SVE2",
221//! &[Architecture::AArch64]
222//! );
223//!
224//! match result {
225//! Ok(()) => {
226//! // Safe to use SVE2 features
227//! }
228//! Err(e) => {
229//! // Handle unsupported architecture
230//! eprintln!("Error: {}", e);
231//! }
232//! }
233//! ```
234
235#![no_std]
236
237extern crate alloc;
238
239pub mod accelerator;
240pub mod acpi;
241pub mod arch;
242pub mod cache;
243pub mod capabilities;
244pub mod devicetree;
245pub mod error;
246pub mod gpu;
247pub mod hardware_db;
248pub mod platform;
249pub mod pmu;
250pub mod power;
251pub mod runtime;
252pub mod system;
253pub mod traits;
254pub mod virtualization;
255
256// Re-export common traits and types at crate root
257pub use traits::{ComputeDevice, DeviceInfo, MemoryDevice, Named, PowerDevice};
258
259// Re-export error types
260pub use error::{Error, Result};
261
262// Re-export Cortex-M types when on Cortex-M architecture
263#[cfg(all(target_arch = "arm", target_os = "none"))]
264pub use arch::cortex_m::{CortexMCapabilities, DspInfo, FpuInfo, FpuVariant, MpuInfo, NvicInfo};
265
266// Re-export platform types
267pub use platform::{
268 BeagleBoneModel, Esp32Capabilities, Esp32Variant, JetsonModel, Platform, PlatformCapabilities,
269 RaspberryPiCapabilities, RaspberryPiModel, Stm32Capabilities, Stm32Family,
270};
271
272use core::fmt;
273
274#[derive(Debug, Clone, Copy, PartialEq, Eq)]
275pub enum Architecture {
276 AArch64,
277 RiscV64,
278 X86_64,
279 ArmCortexM,
280 CortexM,
281 LoongArch64,
282 Xtensa,
283}
284
285impl fmt::Display for Architecture {
286 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287 match self {
288 Architecture::AArch64 => write!(f, "aarch64"),
289 Architecture::RiscV64 => write!(f, "riscv64"),
290 Architecture::X86_64 => write!(f, "x86_64"),
291 Architecture::ArmCortexM => write!(f, "arm-cortex-m"),
292 Architecture::CortexM => write!(f, "cortex-m"),
293 Architecture::LoongArch64 => write!(f, "loongarch64"),
294 Architecture::Xtensa => write!(f, "xtensa"),
295 }
296 }
297}
298
299pub fn detect_architecture() -> Architecture {
300 #[cfg(target_arch = "aarch64")]
301 return Architecture::AArch64;
302
303 #[cfg(target_arch = "riscv64")]
304 return Architecture::RiscV64;
305
306 #[cfg(target_arch = "x86_64")]
307 return Architecture::X86_64;
308
309 #[cfg(all(target_arch = "arm", target_os = "none"))]
310 return Architecture::ArmCortexM;
311}
312
313#[cfg(test)]
314mod tests {
315 use super::*;
316
317 #[test]
318 fn test_architecture_detection() {
319 let arch = detect_architecture();
320 assert!(matches!(
321 arch,
322 Architecture::AArch64
323 | Architecture::RiscV64
324 | Architecture::X86_64
325 | Architecture::ArmCortexM
326 ));
327 }
328}