starnix_core/task/
thread_state.rs1use 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 fn with_arch(arch_width: ArchWidth) -> Self {
45 #[cfg(target_arch = "aarch64")]
46 if arch_width == ArchWidth::Arch32 {
47 return ArchExtendedPstateStorage::State32(Box::new(
48 extended_pstate::ExtendedAarch32PstateState::default(),
49 ));
50 }
51 let _ = arch_width;
52 ArchExtendedPstateStorage::State64(Box::new(ExtendedPstateState::default()))
53 }
54}
55
56pub struct ThreadState<T: RegisterStorage> {
59 pub registers: RegisterState<T>,
63
64 pub extended_pstate: ArchExtendedPstateStorage,
66
67 pub restart_code: Option<ErrnoCode>,
69
70 pub syscall_restart_func: Option<Box<SyscallRestartFunc>>,
74}
75
76impl<T: RegisterStorage + Default> Default for ThreadState<T> {
77 fn default() -> Self {
81 let registers = RegisterState::<T>::default();
82 let extended_pstate = ArchExtendedPstateStorage::with_arch(ArchWidth::Arch64);
83
84 Self { registers, extended_pstate, restart_code: None, syscall_restart_func: None }
85 }
86}
87
88impl<T: RegisterStorage> ThreadState<T> {
89 pub fn arch_width(&self) -> ArchWidth {
90 #[cfg(target_arch = "aarch64")]
91 {
92 return if self.registers.is_arch32() { ArchWidth::Arch32 } else { ArchWidth::Arch64 };
93 }
94 #[cfg(not(target_arch = "aarch64"))]
95 ArchWidth::Arch64
96 }
97
98 pub fn snapshot<R: RegisterStorage>(&self) -> ThreadState<R>
100 where
101 RegisterState<R>: From<RegisterState<T>>,
102 {
103 ThreadState::<R> {
104 registers: self.registers.clone().into(),
105 extended_pstate: self.extended_pstate.clone(),
106 restart_code: self.restart_code,
107 syscall_restart_func: None,
108 }
109 }
110
111 pub fn extended_snapshot<R: RegisterStorage>(&self) -> ThreadState<R>
112 where
113 RegisterState<R>: From<RegisterState<T>>,
114 {
115 ThreadState::<R> {
116 registers: self.registers.clone().into(),
117 extended_pstate: self.extended_pstate.clone(),
118 restart_code: self.restart_code,
119 syscall_restart_func: None,
120 }
121 }
122
123 pub fn replace_registers<O: RegisterStorage>(&mut self, other: &ThreadState<O>) {
124 let self_arch = self.arch_width();
125 let other_arch = other.arch_width();
126 self.registers.load(*other.registers);
127 self.extended_pstate = if self_arch == other_arch {
129 other.extended_pstate.clone()
130 } else {
131 ArchExtendedPstateStorage::with_arch(other_arch)
132 };
133 }
134
135 pub fn get_user_register(&mut self, offset: usize) -> Result<usize, Errno> {
136 let mut result: usize = 0;
137 self.registers.apply_user_register(offset, &mut |register| result = *register as usize)?;
138 Ok(result)
139 }
140
141 pub fn set_user_register(&mut self, offset: usize, value: usize) -> Result<(), Errno> {
142 let self_arch = self.arch_width();
143 let result =
144 self.registers.apply_user_register(offset, &mut |register| *register = value as u64);
145 if self_arch != self.arch_width() {
147 self.extended_pstate = ArchExtendedPstateStorage::with_arch(self.arch_width());
148 }
149 result
150 }
151}
152
153impl From<ThreadState<HeapRegs>> for ThreadState<RegisterStorageEnum> {
154 fn from(value: ThreadState<HeapRegs>) -> Self {
155 ThreadState {
156 registers: value.registers.into(),
157 extended_pstate: value.extended_pstate,
158 restart_code: value.restart_code,
159 syscall_restart_func: value.syscall_restart_func,
160 }
161 }
162}
163
164impl<T: RegisterStorage> ArchSpecific for ThreadState<T> {
165 fn is_arch32(&self) -> bool {
166 #[cfg(target_arch = "aarch64")]
167 return self.registers.is_arch32();
168 #[cfg(not(target_arch = "aarch64"))]
169 false
170 }
171}
172
173pub type SyscallRestartFunc =
174 dyn FnOnce(&mut CurrentTask) -> Result<SyscallResult, Errno> + Send + Sync;