1#[cfg(target_arch = "x86_64")]
6pub mod x86_64;
7
8#[cfg(target_arch = "x86_64")]
9pub use x86_64::XSAVE_AREA_SIZE as X64_XSAVE_AREA_SIZE;
10
11#[cfg(target_arch = "x86_64")]
12pub use x86_64::SUPPORTED_XSAVE_FEATURES as X64_SUPPORTED_XSAVE_FEATURES;
13
14#[cfg(target_arch = "aarch64")]
15mod aarch64;
16
17#[cfg(target_arch = "riscv64")]
18pub mod riscv64;
19
20#[derive(Clone, Copy, Default)]
21pub struct ExtendedPstateState {
22 #[cfg(target_arch = "x86_64")]
23 state: x86_64::State,
24
25 #[cfg(target_arch = "aarch64")]
26 state: aarch64::State,
27
28 #[cfg(target_arch = "riscv64")]
29 state: riscv64::State,
30}
31
32#[cfg(target_arch = "aarch64")]
33#[derive(Clone, Copy, Default)]
36pub struct ExtendedAarch32PstateState {
37 state: aarch64::Aarch32State,
38}
39
40#[cfg(target_arch = "aarch64")]
41impl ExtendedAarch32PstateState {
42 #[inline(always)]
43 pub fn save(&mut self) {
44 self.state.save()
45 }
46
47 #[inline(always)]
56 pub unsafe fn restore(&self) {
57 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
58 unsafe {
59 self.state.restore()
60 }
61 }
62
63 pub fn reset(&mut self) {
64 self.state.reset()
65 }
66}
67
68impl ExtendedPstateState {
69 #[cfg(target_arch = "x86_64")]
70 pub fn with_strategy(strategy: x86_64::Strategy) -> Self {
71 Self { state: x86_64::State::with_strategy(strategy) }
72 }
73
74 #[inline(always)]
76 fn save(&mut self) {
77 self.state.save()
78 }
79
80 #[inline(always)]
81 unsafe fn restore(&self) {
88 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
89 unsafe {
90 self.state.restore()
91 }
92 }
93
94 pub fn reset(&mut self) {
95 self.state.reset()
96 }
97
98 #[cfg(target_arch = "aarch64")]
99 pub fn get_arm64_qregs(&self) -> &[u128; 32] {
100 &self.state.q
101 }
102
103 #[cfg(target_arch = "aarch64")]
104 pub fn get_arm64_fpsr(&self) -> u32 {
105 self.state.fpsr
106 }
107
108 #[cfg(target_arch = "aarch64")]
109 pub fn get_arm64_fpcr(&self) -> u32 {
110 self.state.fpcr
111 }
112
113 #[cfg(target_arch = "aarch64")]
114 pub fn set_arm64_state(&mut self, qregs: &[u128; 32], fpsr: u32, fpcr: u32) {
115 self.state.q = *qregs;
116 self.state.fpsr = fpsr;
117 self.state.fpcr = fpcr;
118 }
119
120 #[cfg(target_arch = "riscv64")]
121 pub fn get_riscv64_state(&self) -> &riscv64::State {
122 &self.state
123 }
124
125 #[cfg(target_arch = "riscv64")]
126 pub fn get_riscv64_state_mut(&mut self) -> &mut riscv64::State {
127 &mut self.state
128 }
129
130 #[cfg(target_arch = "x86_64")]
131 pub fn get_x64_xsave_area(&self) -> [u8; X64_XSAVE_AREA_SIZE] {
132 #[allow(
133 clippy::undocumented_unsafe_blocks,
134 reason = "Force documented unsafe blocks in Starnix"
135 )]
136 unsafe {
137 std::mem::transmute(self.state.buffer)
138 }
139 }
140
141 #[cfg(target_arch = "x86_64")]
142 pub fn set_x64_xsave_area(&mut self, xsave_area: [u8; X64_XSAVE_AREA_SIZE]) {
143 self.state.set_xsave_area(xsave_area);
144 }
145}
146
147#[repr(C)]
151pub union ExtendedPstatePointer {
152 pub extended_pstate: *mut ExtendedPstateState,
153 #[cfg(target_arch = "aarch64")]
154 pub extended_aarch32_pstate: *mut ExtendedAarch32PstateState,
155}
156
157#[unsafe(no_mangle)]
158pub unsafe extern "C" fn restore_extended_pstate(state_addr: usize) {
164 let pointer = state_addr as *const ExtendedPstatePointer;
165 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
166 unsafe {
167 let state = (*pointer).extended_pstate;
168 (*state).restore()
169 }
170}
171
172#[unsafe(no_mangle)]
173pub unsafe extern "C" fn save_extended_pstate(state_addr: usize) {
179 let pointer = state_addr as *const ExtendedPstatePointer;
180 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
181 unsafe {
182 let state = (*pointer).extended_pstate;
183 (*state).save()
184 }
185}
186
187#[cfg(target_arch = "aarch64")]
188#[unsafe(no_mangle)]
189pub unsafe extern "C" fn restore_extended_aarch32_pstate(state_addr: usize) {
195 let pointer = state_addr as *const ExtendedPstatePointer;
196 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
197 unsafe {
198 let state = (*pointer).extended_aarch32_pstate;
199 (*state).restore()
200 }
201}
202
203#[cfg(target_arch = "aarch64")]
204#[unsafe(no_mangle)]
205pub unsafe extern "C" fn save_extended_aarch32_pstate(state_addr: usize) {
211 let pointer = state_addr as *const ExtendedPstatePointer;
212 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
213 unsafe {
214 let state = (*pointer).extended_aarch32_pstate;
215 (*state).save()
216 }
217}
218
219#[cfg(test)]
220mod test {
221 use super::*;
222
223 #[::fuchsia::test]
224 fn extended_pstate_state_lifecycle() {
225 let mut state = ExtendedPstateState::default();
226 #[allow(
227 clippy::undocumented_unsafe_blocks,
228 reason = "Force documented unsafe blocks in Starnix"
229 )]
230 unsafe {
231 state.save();
232 state.restore();
233 }
234 }
235}