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#[unsafe(no_mangle)]
148pub unsafe extern "C" fn restore_extended_pstate(state_addr: usize) {
153 let state = state_addr as *const ExtendedPstateState;
154 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
155 unsafe {
156 (*state).restore()
157 }
158}
159
160#[unsafe(no_mangle)]
161pub unsafe extern "C" fn save_extended_pstate(state_addr: usize) {
166 let state = state_addr as *mut ExtendedPstateState;
167 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
168 unsafe {
169 (*state).save()
170 }
171}
172
173#[cfg(target_arch = "aarch64")]
174#[unsafe(no_mangle)]
175pub unsafe extern "C" fn restore_extended_aarch32_pstate(state_addr: usize) {
180 let state = state_addr as *const ExtendedAarch32PstateState;
181 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
182 unsafe {
183 (*state).restore()
184 }
185}
186
187#[cfg(target_arch = "aarch64")]
188#[unsafe(no_mangle)]
189pub unsafe extern "C" fn save_extended_aarch32_pstate(state_addr: usize) {
194 let state = state_addr as *mut ExtendedAarch32PstateState;
195 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
196 unsafe {
197 (*state).save()
198 }
199}
200
201#[cfg(test)]
202mod test {
203 use super::*;
204
205 #[::fuchsia::test]
206 fn extended_pstate_state_lifecycle() {
207 let mut state = ExtendedPstateState::default();
208 #[allow(
209 clippy::undocumented_unsafe_blocks,
210 reason = "Force documented unsafe blocks in Starnix"
211 )]
212 unsafe {
213 state.save();
214 state.restore();
215 }
216 }
217}