extended_pstate/
lib.rs
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
32impl ExtendedPstateState {
33 pub unsafe fn run_with_saved_state<F, R>(&mut self, f: F) -> R
41 where
42 F: FnOnce() -> R,
43 {
44 self.restore();
45 let r = f();
46 self.save();
47 r
48 }
49
50 #[cfg(target_arch = "x86_64")]
51 pub fn with_strategy(strategy: x86_64::Strategy) -> Self {
52 Self { state: x86_64::State::with_strategy(strategy) }
53 }
54
55 #[inline(always)]
57 fn save(&mut self) {
58 self.state.save()
59 }
60
61 #[inline(always)]
62 unsafe fn restore(&self) {
69 self.state.restore()
70 }
71
72 pub fn reset(&mut self) {
73 self.state.reset()
74 }
75
76 #[cfg(target_arch = "aarch64")]
77 pub fn get_arm64_qregs(&self) -> &[u128; 32] {
78 &self.state.q
79 }
80
81 #[cfg(target_arch = "aarch64")]
82 pub fn get_arm64_fpsr(&self) -> u32 {
83 self.state.fpsr
84 }
85
86 #[cfg(target_arch = "aarch64")]
87 pub fn get_arm64_fpcr(&self) -> u32 {
88 self.state.fpcr
89 }
90
91 #[cfg(target_arch = "aarch64")]
92 pub fn set_arm64_state(&mut self, qregs: &[u128; 32], fpsr: u32, fpcr: u32) {
93 self.state.q = *qregs;
94 self.state.fpsr = fpsr;
95 self.state.fpcr = fpcr;
96 }
97
98 #[cfg(target_arch = "riscv64")]
99 pub fn get_riscv64_state(&self) -> &riscv64::State {
100 &self.state
101 }
102
103 #[cfg(target_arch = "riscv64")]
104 pub fn get_riscv64_state_mut(&mut self) -> &mut riscv64::State {
105 &mut self.state
106 }
107
108 #[cfg(target_arch = "x86_64")]
109 pub fn get_x64_xsave_area(&self) -> [u8; X64_XSAVE_AREA_SIZE] {
110 unsafe { std::mem::transmute(self.state.buffer) }
111 }
112
113 #[cfg(target_arch = "x86_64")]
114 pub fn set_x64_xsave_area(&mut self, xsave_area: [u8; X64_XSAVE_AREA_SIZE]) {
115 self.state.set_xsave_area(xsave_area);
116 }
117}
118
119#[no_mangle]
120unsafe extern "C" fn restore_extended_pstate(state_addr: usize) {
121 let state = state_addr as *mut ExtendedPstateState;
122 (&*state).restore()
123}
124
125#[no_mangle]
126unsafe extern "C" fn save_extended_pstate(state_addr: usize) {
127 let state = state_addr as *mut ExtendedPstateState;
128 (&mut *state).save()
129}
130
131#[cfg(test)]
132mod test {
133 use super::*;
134
135 #[::fuchsia::test]
136 fn extended_pstate_state_lifecycle() {
137 let mut state = ExtendedPstateState::default();
138 unsafe {
139 state.save();
140 state.restore();
141 }
142 }
143}