strat9_kernel/ostd/cpu.rs
1//! CPU abstraction layer
2//!
3//! Provides safe abstractions for CPU-related operations including:
4//! - CPU identification and topology
5//! - Per-CPU data access
6//! - CPU control (halt, interrupt control)
7//!
8//! Inspired by Asterinas OSTD CPU module.
9
10#![allow(unsafe_code)]
11
12/// CPU identifier
13///
14/// Represents a logical CPU in the system. On x86_64, this corresponds
15/// to the APIC ID.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
17#[repr(transparent)]
18pub struct CpuId {
19 id: usize,
20}
21
22impl CpuId {
23 /// Creates a new CpuId from a raw ID
24 pub const fn new(id: usize) -> Self {
25 Self { id }
26 }
27
28 /// Returns the raw CPU ID value
29 pub const fn id(&self) -> usize {
30 self.id
31 }
32
33 /// Returns the CpuId of the bootstrap processor (BSP)
34 pub const fn bsp() -> Self {
35 Self::new(0)
36 }
37
38 /// Returns the CpuId of the currently executing CPU
39 ///
40 /// # Safety
41 ///
42 /// This function reads the per-CPU GS base to determine the current CPU.
43 /// It requires that per-CPU data has been initialized for this CPU.
44 #[inline]
45 pub fn current_racy() -> Self {
46 // This is safe if per-CPU data has been set up via
47 // arch::x86_64::percpu::init_gs_base(). The "racy" suffix indicates
48 // that no additional synchronization is performed.
49 let cpu_index = crate::arch::x86_64::percpu::current_cpu_index();
50 Self::new(cpu_index)
51 }
52
53 /// Returns the number of CPUs in the system
54 pub fn num_cpus() -> usize {
55 crate::arch::x86_64::percpu::get_cpu_count()
56 }
57
58 /// Returns an iterator over all CPUs
59 pub fn iter() -> CpuIter {
60 CpuIter {
61 current: 0,
62 end: Self::num_cpus(),
63 }
64 }
65}
66
67impl From<usize> for CpuId {
68 /// Performs the from operation.
69 fn from(id: usize) -> Self {
70 Self::new(id)
71 }
72}
73
74impl From<CpuId> for usize {
75 /// Performs the from operation.
76 fn from(cpu_id: CpuId) -> Self {
77 cpu_id.id
78 }
79}
80
81impl core::fmt::Display for CpuId {
82 /// Performs the fmt operation.
83 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
84 write!(f, "CPU #{}", self.id)
85 }
86}
87
88/// Iterator over all CPUs
89pub struct CpuIter {
90 current: usize,
91 end: usize,
92}
93
94impl Iterator for CpuIter {
95 type Item = CpuId;
96
97 /// Performs the next operation.
98 fn next(&mut self) -> Option<Self::Item> {
99 if self.current < self.end {
100 let cpu = CpuId::new(self.current);
101 self.current += 1;
102 Some(cpu)
103 } else {
104 None
105 }
106 }
107}
108
109/// CPU halt function
110///
111/// Halts the CPU until the next interrupt arrives.
112#[inline]
113pub fn halt_cpu() {
114 // hlt is a privileged instruction that halts the CPU until
115 // the next interrupt. This is safe to call in kernel mode.
116 crate::arch::x86_64::hlt();
117}
118
119/// Disable interrupts on the current CPU
120#[inline]
121pub fn disable_irqs() {
122 // cli is a privileged instruction that disables interrupts.
123 // This is safe to call in kernel mode and is commonly used to
124 // protect critical sections.
125 crate::arch::x86_64::cli();
126}
127
128/// Enable interrupts on the current CPU
129#[inline]
130pub fn enable_irqs() {
131 // sti is a privileged instruction that enables interrupts.
132 // This is safe to call in kernel mode.
133 crate::arch::x86_64::sti();
134}
135
136/// Check if interrupts are enabled on the current CPU
137#[inline]
138pub fn irqs_enabled() -> bool {
139 crate::arch::x86_64::interrupts_enabled()
140}
141
142/// Save interrupt flags and disable interrupts
143///
144/// Returns the previous interrupt state.
145#[inline]
146pub fn save_and_disable_irqs() -> bool {
147 let flags = crate::arch::x86_64::save_flags_and_cli();
148 (flags & 0x200) != 0
149}
150
151/// Restore interrupt flags
152///
153/// Restores the interrupt state to a previous value.
154#[inline]
155pub fn restore_irqs(enabled: bool) {
156 if enabled {
157 enable_irqs();
158 } else {
159 disable_irqs();
160 }
161}
162
163/// Execute a closure with interrupts disabled
164///
165/// Returns the result of the closure.
166pub fn without_interrupts<F, R>(f: F) -> R
167where
168 F: FnOnce() -> R,
169{
170 let irq_enabled = save_and_disable_irqs();
171 let result = f();
172 restore_irqs(irq_enabled);
173 result
174}