1use crate::task::CurrentTask;
6use extended_pstate::{ExtendedPstatePointer, ExtendedPstateState};
7use starnix_registers::{HeapRegs, RegisterState, RegisterStorage, RegisterStorageEnum};
8use starnix_syscalls::SyscallResult;
9use starnix_types::arch::ArchWidth;
10use starnix_uapi::errors::{Errno, ErrnoCode};
11use starnix_uapi::user_address::ArchSpecific;
12
13#[derive(Clone)]
14pub enum ArchExtendedPstateStorage {
15 State64(Box<ExtendedPstateState>),
17 #[cfg(target_arch = "aarch64")]
18 State32(Box<extended_pstate::ExtendedAarch32PstateState>),
20}
21
22impl ArchExtendedPstateStorage {
23 pub fn as_ptr(&mut self) -> ExtendedPstatePointer {
25 match self {
26 ArchExtendedPstateStorage::State64(state) => {
27 ExtendedPstatePointer { extended_pstate: state.as_mut() as *mut _ }
28 }
29 #[cfg(target_arch = "aarch64")]
30 ArchExtendedPstateStorage::State32(state) => {
31 ExtendedPstatePointer { extended_aarch32_pstate: state.as_mut() as *mut _ }
32 }
33 }
34 }
35
36 pub fn reset(&mut self) {
37 match self {
38 ArchExtendedPstateStorage::State64(state) => state.reset(),
39 #[cfg(target_arch = "aarch64")]
40 ArchExtendedPstateStorage::State32(state) => state.reset(),
41 }
42 }
43
44 pub fn reset_with_arch(&mut self, arch_width: ArchWidth) {
45 match (self, arch_width) {
46 #[cfg(target_arch = "aarch64")]
47 (ArchExtendedPstateStorage::State32(state), ArchWidth::Arch32) => state.reset(),
48 #[cfg(target_arch = "aarch64")]
49 (this @ ArchExtendedPstateStorage::State64(_), ArchWidth::Arch32)
50 | (this @ ArchExtendedPstateStorage::State32(_), ArchWidth::Arch64) => {
51 *this = Self::with_arch(arch_width);
52 }
53 (ArchExtendedPstateStorage::State64(state), _) => state.reset(),
54 }
55 }
56
57 #[cfg(target_arch = "aarch64")]
58 pub fn has_sve(&self) -> bool {
59 match self {
60 ArchExtendedPstateStorage::State64(state) => state.has_arm64_sve(),
61 ArchExtendedPstateStorage::State32(_) => false,
62 }
63 }
64
65 #[cfg(target_arch = "aarch64")]
67 pub fn sve_vl_inherit(&self) -> bool {
68 match self {
69 ArchExtendedPstateStorage::State64(state) => state.get_arm64_sve_vl_inherit(),
70 ArchExtendedPstateStorage::State32(_) => false,
71 }
72 }
73
74 #[cfg(target_arch = "aarch64")]
75 pub fn set_sve_vl_inherit(&mut self, inherit: bool) {
76 if let ArchExtendedPstateStorage::State64(state) = self {
77 state.set_arm64_sve_vl_inherit(inherit);
78 }
79 }
80
81 fn with_arch(arch_width: ArchWidth) -> Self {
82 #[cfg(target_arch = "aarch64")]
83 if arch_width == ArchWidth::Arch32 {
84 return ArchExtendedPstateStorage::State32(Box::new(
85 extended_pstate::ExtendedAarch32PstateState::default(),
86 ));
87 }
88 let _ = arch_width;
89 ArchExtendedPstateStorage::State64(Box::new(ExtendedPstateState::default()))
90 }
91}
92
93pub struct ThreadState<T: RegisterStorage> {
96 pub registers: RegisterState<T>,
100
101 pub extended_pstate: ArchExtendedPstateStorage,
103
104 pub restart_code: Option<ErrnoCode>,
106
107 pub syscall_restart_func: Option<Box<SyscallRestartFunc>>,
111}
112
113impl<T: RegisterStorage + Default> Default for ThreadState<T> {
114 fn default() -> Self {
118 let registers = RegisterState::<T>::default();
119 let extended_pstate = ArchExtendedPstateStorage::with_arch(ArchWidth::Arch64);
120
121 Self { registers, extended_pstate, restart_code: None, syscall_restart_func: None }
122 }
123}
124
125impl<T: RegisterStorage> ThreadState<T> {
126 pub fn arch_width(&self) -> ArchWidth {
127 #[cfg(target_arch = "aarch64")]
128 {
129 return if self.registers.is_arch32() { ArchWidth::Arch32 } else { ArchWidth::Arch64 };
130 }
131 #[cfg(not(target_arch = "aarch64"))]
132 ArchWidth::Arch64
133 }
134
135 pub fn snapshot<R: RegisterStorage>(&self) -> ThreadState<R>
137 where
138 RegisterState<R>: From<RegisterState<T>>,
139 {
140 ThreadState::<R> {
141 registers: self.registers.clone().into(),
142 extended_pstate: self.extended_pstate.clone(),
143 restart_code: self.restart_code,
144 syscall_restart_func: None,
145 }
146 }
147
148 pub fn extended_snapshot<R: RegisterStorage>(&self) -> ThreadState<R>
149 where
150 RegisterState<R>: From<RegisterState<T>>,
151 {
152 ThreadState::<R> {
153 registers: self.registers.clone().into(),
154 extended_pstate: self.extended_pstate.clone(),
155 restart_code: self.restart_code,
156 syscall_restart_func: None,
157 }
158 }
159
160 pub fn replace_registers<O: RegisterStorage>(&mut self, other: &ThreadState<O>) {
161 let self_arch = self.arch_width();
162 let other_arch = other.arch_width();
163 self.registers.copy_from(&other.registers);
164 self.extended_pstate = if self_arch == other_arch {
166 other.extended_pstate.clone()
167 } else {
168 ArchExtendedPstateStorage::with_arch(other_arch)
169 };
170 }
171
172 pub fn get_user_register(&mut self, offset: usize) -> Result<usize, Errno> {
173 let mut result: usize = 0;
174 self.registers.apply_user_register(offset, &mut |register| result = *register as usize)?;
175 Ok(result)
176 }
177
178 pub fn set_user_register(&mut self, offset: usize, value: usize) -> Result<(), Errno> {
179 let self_arch = self.arch_width();
180 let result =
181 self.registers.apply_user_register(offset, &mut |register| *register = value as u64);
182 if self_arch != self.arch_width() {
184 self.extended_pstate = ArchExtendedPstateStorage::with_arch(self.arch_width());
185 }
186 result
187 }
188}
189
190impl From<ThreadState<HeapRegs>> for ThreadState<RegisterStorageEnum> {
191 fn from(value: ThreadState<HeapRegs>) -> Self {
192 ThreadState {
193 registers: value.registers.into(),
194 extended_pstate: value.extended_pstate,
195 restart_code: value.restart_code,
196 syscall_restart_func: value.syscall_restart_func,
197 }
198 }
199}
200
201impl<T: RegisterStorage> ArchSpecific for ThreadState<T> {
202 fn is_arch32(&self) -> bool {
203 #[cfg(target_arch = "aarch64")]
204 return self.registers.is_arch32();
205 #[cfg(not(target_arch = "aarch64"))]
206 false
207 }
208}
209
210pub type SyscallRestartFunc =
211 dyn FnOnce(&mut CurrentTask) -> Result<SyscallResult, Errno> + Send + Sync;
212
213#[cfg(all(test, target_arch = "aarch64"))]
214mod tests {
215 use super::*;
216
217 #[::fuchsia::test]
218 fn test_arch_extended_pstate_storage_sve() {
219 let mut pstate = ExtendedPstateState::with_sve(true);
220 let qregs = [0x112233445566778899aabbccddeeff00u128; 32];
221 let pregs = [0x5a5au16; 16];
222 pstate.set_arm64_state(&qregs, 0x10, 0x20);
223 pstate.set_arm64_sve_state(&pregs, 0x00ff);
224
225 let mut storage = ArchExtendedPstateStorage::State64(Box::new(pstate));
226 assert!(storage.has_sve());
227
228 assert!(!storage.sve_vl_inherit());
230 storage.set_sve_vl_inherit(true);
231 assert!(storage.sve_vl_inherit());
232 let ArchExtendedPstateStorage::State64(state) = &storage else { unreachable!() };
233 assert_eq!(state.get_arm64_qregs(), &qregs);
234 assert_eq!(state.get_arm64_p_regs(), &pregs);
235 assert_eq!(state.get_arm64_ffr(), 0x00ff);
236
237 storage.reset();
240 assert!(storage.has_sve());
241 assert!(storage.sve_vl_inherit());
242 let ArchExtendedPstateStorage::State64(state) = &storage else { unreachable!() };
243 assert_eq!(state.get_arm64_qregs(), &[0u128; 32]);
244 assert_eq!(state.get_arm64_fpsr(), 0);
245 assert_eq!(state.get_arm64_fpcr(), 0);
246 assert_eq!(state.get_arm64_p_regs(), &[0u16; 16]);
247 assert_eq!(state.get_arm64_ffr(), 0);
248
249 storage.set_sve_vl_inherit(false);
250 storage.reset();
251 assert!(storage.has_sve());
252 assert!(!storage.sve_vl_inherit());
253
254 let mut storage32 = ArchExtendedPstateStorage::State32(Box::default());
256 assert!(!storage32.has_sve());
257 storage32.set_sve_vl_inherit(true);
258 assert!(!storage32.sve_vl_inherit());
259 }
260
261 #[::fuchsia::test]
262 fn test_arch_extended_pstate_storage_reset_with_arch() {
263 let mut pstate = ExtendedPstateState::with_sve(true);
264 let qregs = [0x112233445566778899aabbccddeeff00u128; 32];
265 let pregs = [0x5a5au16; 16];
266 pstate.set_arm64_state(&qregs, 0x10, 0x20);
267 pstate.set_arm64_sve_state(&pregs, 0x00ff);
268
269 let mut storage = ArchExtendedPstateStorage::State64(Box::new(pstate));
270 storage.set_sve_vl_inherit(true);
271
272 storage.reset_with_arch(ArchWidth::Arch64);
275 assert!(storage.has_sve());
276 assert!(storage.sve_vl_inherit());
277 let ArchExtendedPstateStorage::State64(state) = &storage else { unreachable!() };
278 assert_eq!(state.get_arm64_qregs(), &[0u128; 32]);
279 assert_eq!(state.get_arm64_p_regs(), &[0u16; 16]);
280 assert_eq!(state.get_arm64_ffr(), 0);
281
282 storage.reset_with_arch(ArchWidth::Arch32);
284 assert!(matches!(storage, ArchExtendedPstateStorage::State32(_)));
285 assert!(!storage.has_sve());
286 assert!(!storage.sve_vl_inherit());
287
288 storage.reset_with_arch(ArchWidth::Arch32);
290 let ArchExtendedPstateStorage::State32(state32) = &storage else { unreachable!() };
291 assert_eq!(state32.get_arm32_qregs(), &[0u128; 16]);
292 assert_eq!(state32.get_arm32_fpsr(), 0);
293 assert_eq!(state32.get_arm32_fpcr(), 0);
294
295 storage.reset_with_arch(ArchWidth::Arch64);
297 assert!(matches!(storage, ArchExtendedPstateStorage::State64(_)));
298 assert!(!storage.sve_vl_inherit());
299 }
300
301 fn state64_ptr(storage: &ArchExtendedPstateStorage) -> *const ExtendedPstateState {
303 let ArchExtendedPstateStorage::State64(state) = storage else { unreachable!() };
304 std::ptr::from_ref(state.as_ref())
305 }
306
307 fn assert_state64_regs(
308 storage: &ArchExtendedPstateStorage,
309 qregs: &[u128; 32],
310 fpsr: u32,
311 fpcr: u32,
312 pregs: &[u16; 16],
313 ffr: u16,
314 context: &str,
315 ) {
316 let ArchExtendedPstateStorage::State64(state) = storage else { unreachable!() };
317 assert_eq!(state.get_arm64_qregs(), qregs, "{context}");
318 assert_eq!(state.get_arm64_fpsr(), fpsr, "{context}");
319 assert_eq!(state.get_arm64_fpcr(), fpcr, "{context}");
320 assert_eq!(state.get_arm64_p_regs(), pregs, "{context}");
321 assert_eq!(state.get_arm64_ffr(), ffr, "{context}");
322 }
323
324 #[::fuchsia::test]
325 fn test_arch_extended_pstate_storage_clone_and_reset_preserve_sve_flags() {
326 let qregs = [0x00112233445566778899aabbccddeeffu128; 32];
327 let pregs = [0x0f0fu16; 16];
328 for has_sve in [false, true] {
332 for inherit in [false, true] {
333 let context = format!("has_sve={has_sve} inherit={inherit}");
334 let mut pstate = ExtendedPstateState::with_sve(has_sve);
335 pstate.set_arm64_state(&qregs, 0x10, 0x20);
336 pstate.set_arm64_sve_state(&pregs, 0x00ff);
337 let mut storage = ArchExtendedPstateStorage::State64(Box::new(pstate));
338 storage.set_sve_vl_inherit(inherit);
339 assert_eq!(storage.has_sve(), has_sve, "{context}");
340 assert_eq!(storage.sve_vl_inherit(), inherit, "{context}");
341
342 let mut cloned = storage.clone();
344 assert_eq!(cloned.has_sve(), has_sve, "{context}");
345 assert_eq!(cloned.sve_vl_inherit(), inherit, "{context}");
346 assert_ne!(state64_ptr(&cloned), state64_ptr(&storage), "{context}");
347 assert_state64_regs(&cloned, &qregs, 0x10, 0x20, &pregs, 0x00ff, &context);
348
349 cloned.set_sve_vl_inherit(!inherit);
351 cloned.reset();
352 assert_eq!(cloned.has_sve(), has_sve, "{context}");
353 assert_eq!(cloned.sve_vl_inherit(), !inherit, "{context}");
354 assert_state64_regs(&cloned, &[0u128; 32], 0, 0, &[0u16; 16], 0, &context);
355 assert_eq!(storage.has_sve(), has_sve, "{context}");
356 assert_eq!(storage.sve_vl_inherit(), inherit, "{context}");
357 assert_state64_regs(&storage, &qregs, 0x10, 0x20, &pregs, 0x00ff, &context);
358
359 let ptr_before_reset = state64_ptr(&storage);
361 storage.reset();
362 assert_eq!(storage.has_sve(), has_sve, "{context}");
363 assert_eq!(storage.sve_vl_inherit(), inherit, "{context}");
364 assert_eq!(state64_ptr(&storage), ptr_before_reset, "{context}");
365 assert_state64_regs(&storage, &[0u128; 32], 0, 0, &[0u16; 16], 0, &context);
366
367 let ArchExtendedPstateStorage::State64(state) = &mut storage else {
369 unreachable!()
370 };
371 state.set_arm64_state(&qregs, 0x30, 0x40);
372 state.set_arm64_sve_state(&pregs, 0x0001);
373 storage.reset_with_arch(ArchWidth::Arch64);
374 assert_eq!(storage.has_sve(), has_sve, "{context}");
375 assert_eq!(storage.sve_vl_inherit(), inherit, "{context}");
376 assert_eq!(state64_ptr(&storage), ptr_before_reset, "{context}");
377 assert_state64_regs(&storage, &[0u128; 32], 0, 0, &[0u16; 16], 0, &context);
378 }
379 }
380 }
381
382 #[::fuchsia::test]
383 fn test_thread_state_snapshot_preserves_sve_state() {
384 let qregs = [0x0123456789abcdef0123456789abcdefu128; 32];
388 let pregs = [0x8001u16; 16];
389 for has_sve in [false, true] {
390 for inherit in [false, true] {
391 let context = format!("has_sve={has_sve} inherit={inherit}");
392 let mut parent = ThreadState::<HeapRegs>::default();
393 let mut pstate = ExtendedPstateState::with_sve(has_sve);
394 pstate.set_arm64_state(&qregs, 0x10, 0x20);
395 pstate.set_arm64_sve_state(&pregs, 0x0007);
396 parent.extended_pstate = ArchExtendedPstateStorage::State64(Box::new(pstate));
397 parent.extended_pstate.set_sve_vl_inherit(inherit);
398
399 for mut child in
400 [parent.snapshot::<HeapRegs>(), parent.extended_snapshot::<HeapRegs>()]
401 {
402 assert_eq!(child.arch_width(), ArchWidth::Arch64, "{context}");
403 assert_eq!(child.extended_pstate.has_sve(), has_sve, "{context}");
404 assert_eq!(child.extended_pstate.sve_vl_inherit(), inherit, "{context}");
405 assert_ne!(
406 state64_ptr(&child.extended_pstate),
407 state64_ptr(&parent.extended_pstate),
408 "{context}"
409 );
410 assert_state64_regs(
411 &child.extended_pstate,
412 &qregs,
413 0x10,
414 0x20,
415 &pregs,
416 0x0007,
417 &context,
418 );
419
420 child.extended_pstate.set_sve_vl_inherit(!inherit);
422 child.extended_pstate.reset_with_arch(child.arch_width());
423 assert_eq!(child.extended_pstate.has_sve(), has_sve, "{context}");
424 assert_eq!(child.extended_pstate.sve_vl_inherit(), !inherit, "{context}");
425 assert_state64_regs(
426 &child.extended_pstate,
427 &[0u128; 32],
428 0,
429 0,
430 &[0u16; 16],
431 0,
432 &context,
433 );
434 assert_eq!(parent.extended_pstate.has_sve(), has_sve, "{context}");
435 assert_eq!(parent.extended_pstate.sve_vl_inherit(), inherit, "{context}");
436 assert_state64_regs(
437 &parent.extended_pstate,
438 &qregs,
439 0x10,
440 0x20,
441 &pregs,
442 0x0007,
443 &context,
444 );
445 }
446
447 let child = parent.snapshot::<HeapRegs>();
449 parent.extended_pstate.reset_with_arch(parent.arch_width());
450 assert_state64_regs(
451 &child.extended_pstate,
452 &qregs,
453 0x10,
454 0x20,
455 &pregs,
456 0x0007,
457 &context,
458 );
459 assert_eq!(child.extended_pstate.sve_vl_inherit(), inherit, "{context}");
460 }
461 }
462
463 let mut parent32 = ThreadState::<HeapRegs>::default();
465 let mut regs32 = zx::sys::zx_restricted_state_t::default();
466 regs32.cpsr = zx::sys::ZX_REG_CPSR_ARCH_32_MASK as u32;
467 parent32.registers.load(regs32);
468 parent32.extended_pstate.reset_with_arch(parent32.arch_width());
469 assert!(matches!(parent32.extended_pstate, ArchExtendedPstateStorage::State32(_)));
470 let child32 = parent32.snapshot::<HeapRegs>();
471 assert_eq!(child32.arch_width(), ArchWidth::Arch32);
472 assert!(matches!(child32.extended_pstate, ArchExtendedPstateStorage::State32(_)));
473 assert!(!child32.extended_pstate.has_sve());
474 assert!(!child32.extended_pstate.sve_vl_inherit());
475 }
476
477 #[::fuchsia::test]
478 fn test_thread_state_finish_exec_cross_arch_and_sve_inheritance() {
479 fn simulate_finish_exec(
483 thread_state: &mut ThreadState<HeapRegs>,
484 regs: zx::sys::zx_restricted_state_t,
485 ) {
486 thread_state.registers.load(regs);
487 thread_state.extended_pstate.reset_with_arch(thread_state.arch_width());
488 }
489
490 let qregs = [0x112233445566778899aabbccddeeff00u128; 32];
491 let pregs = [0x5a5au16; 16];
492
493 let mut thread_state = ThreadState::<HeapRegs>::default();
494 assert_eq!(thread_state.arch_width(), ArchWidth::Arch64);
495 assert!(!thread_state.is_arch32());
496
497 let mut pstate = ExtendedPstateState::with_sve(true);
498 pstate.set_arm64_state(&qregs, 0x10, 0x20);
499 pstate.set_arm64_sve_state(&pregs, 0x00ff);
500 thread_state.extended_pstate = ArchExtendedPstateStorage::State64(Box::new(pstate));
501
502 thread_state.extended_pstate.set_sve_vl_inherit(false);
506 let state64_box_ptr = match &thread_state.extended_pstate {
507 ArchExtendedPstateStorage::State64(state) => {
508 assert_eq!(state.get_arm64_qregs(), &qregs);
509 assert_eq!(state.get_arm64_p_regs(), &pregs);
510 assert_eq!(state.get_arm64_ffr(), 0x00ff);
511 std::ptr::from_ref(state.as_ref())
512 }
513 ArchExtendedPstateStorage::State32(_) => unreachable!(),
514 };
515
516 let mut regs64 = zx::sys::zx_restricted_state_t::default();
517 regs64.cpsr = 0;
518 simulate_finish_exec(&mut thread_state, regs64);
519 assert_eq!(thread_state.arch_width(), ArchWidth::Arch64);
520 assert!(thread_state.extended_pstate.has_sve());
521 assert!(!thread_state.extended_pstate.sve_vl_inherit());
522 let raw_ptr64 =
524 unsafe { thread_state.extended_pstate.as_ptr().extended_pstate.cast_const() };
525 assert_eq!(raw_ptr64, state64_box_ptr);
526 let ArchExtendedPstateStorage::State64(state) = &mut thread_state.extended_pstate else {
527 unreachable!()
528 };
529 assert_eq!(state.get_arm64_qregs(), &[0u128; 32]);
530 assert_eq!(state.get_arm64_fpsr(), 0);
531 assert_eq!(state.get_arm64_fpcr(), 0);
532 assert_eq!(state.get_arm64_p_regs(), &[0u16; 16]);
533 assert_eq!(state.get_arm64_ffr(), 0);
534
535 state.set_arm64_state(&qregs, 0x33, 0x44);
538 state.set_arm64_sve_state(&pregs, 0x00ff);
539 thread_state.extended_pstate.set_sve_vl_inherit(true);
540 simulate_finish_exec(&mut thread_state, regs64);
541 assert_eq!(thread_state.arch_width(), ArchWidth::Arch64);
542 assert!(thread_state.extended_pstate.has_sve());
543 assert!(thread_state.extended_pstate.sve_vl_inherit());
544 let ArchExtendedPstateStorage::State64(state) = &mut thread_state.extended_pstate else {
545 unreachable!()
546 };
547 assert_eq!(state.get_arm64_qregs(), &[0u128; 32]);
548 assert_eq!(state.get_arm64_fpsr(), 0);
549 assert_eq!(state.get_arm64_fpcr(), 0);
550 assert_eq!(state.get_arm64_p_regs(), &[0u16; 16]);
551 assert_eq!(state.get_arm64_ffr(), 0);
552
553 state.set_arm64_state(&qregs, 0x55, 0x66);
556 state.set_arm64_sve_state(&pregs, 0x00ff);
557 let mut regs32 = zx::sys::zx_restricted_state_t::default();
558 regs32.cpsr = zx::sys::ZX_REG_CPSR_ARCH_32_MASK as u32;
559 simulate_finish_exec(&mut thread_state, regs32);
560 assert_eq!(thread_state.arch_width(), ArchWidth::Arch32);
561 assert!(thread_state.is_arch32());
562 assert!(!thread_state.extended_pstate.has_sve());
563 assert!(!thread_state.extended_pstate.sve_vl_inherit());
564 let state32_box_ptr = match &thread_state.extended_pstate {
565 ArchExtendedPstateStorage::State32(state32) => {
566 assert_eq!(state32.get_arm32_qregs(), &[0u128; 16]);
567 assert_eq!(state32.get_arm32_fpsr(), 0);
568 assert_eq!(state32.get_arm32_fpcr(), 0);
569 std::ptr::from_ref(state32.as_ref())
570 }
571 ArchExtendedPstateStorage::State64(_) => unreachable!(),
572 };
573 let raw_ptr32 =
575 unsafe { thread_state.extended_pstate.as_ptr().extended_aarch32_pstate.cast_const() };
576 assert_eq!(raw_ptr32, state32_box_ptr);
577
578 simulate_finish_exec(&mut thread_state, regs64);
581 assert_eq!(thread_state.arch_width(), ArchWidth::Arch64);
582 assert!(!thread_state.is_arch32());
583 assert_eq!(
584 thread_state.extended_pstate.has_sve(),
585 ExtendedPstateState::default().has_arm64_sve()
586 );
587 assert!(!thread_state.extended_pstate.sve_vl_inherit());
588 let new_state64_box_ptr = match &thread_state.extended_pstate {
589 ArchExtendedPstateStorage::State64(state64) => {
590 assert_eq!(state64.get_arm64_qregs(), &[0u128; 32]);
591 assert_eq!(state64.get_arm64_fpsr(), 0);
592 assert_eq!(state64.get_arm64_fpcr(), 0);
593 assert_eq!(state64.get_arm64_p_regs(), &[0u16; 16]);
594 assert_eq!(state64.get_arm64_ffr(), 0);
595 std::ptr::from_ref(state64.as_ref())
596 }
597 ArchExtendedPstateStorage::State32(_) => unreachable!(),
598 };
599 let new_raw_ptr64 =
601 unsafe { thread_state.extended_pstate.as_ptr().extended_pstate.cast_const() };
602 assert_eq!(new_raw_ptr64, new_state64_box_ptr);
603 }
604}