starnix_core/task/
thread_state.rs1use crate::task::CurrentTask;
6use extended_pstate::{ExtendedPstatePointer, ExtendedPstateState};
7use starnix_registers::{HeapRegs, RegisterState, RegisterStorage, RegisterStorageEnum};
8use starnix_sync::{Locked, Unlocked};
9use starnix_syscalls::SyscallResult;
10use starnix_types::arch::ArchWidth;
11use starnix_uapi::errors::{Errno, ErrnoCode};
12use starnix_uapi::user_address::ArchSpecific;
13
14#[derive(Clone)]
15pub enum ArchExtendedPstateStorage {
16 State64(Box<ExtendedPstateState>),
18 #[cfg(target_arch = "aarch64")]
19 State32(Box<extended_pstate::ExtendedAarch32PstateState>),
21}
22
23impl ArchExtendedPstateStorage {
24 pub fn as_ptr(&mut self) -> ExtendedPstatePointer {
26 match self {
27 ArchExtendedPstateStorage::State64(state) => {
28 ExtendedPstatePointer { extended_pstate: state.as_mut() as *mut _ }
29 }
30 #[cfg(target_arch = "aarch64")]
31 ArchExtendedPstateStorage::State32(state) => {
32 ExtendedPstatePointer { extended_aarch32_pstate: state.as_mut() as *mut _ }
33 }
34 }
35 }
36
37 pub fn reset(&mut self) {
38 match self {
39 ArchExtendedPstateStorage::State64(state) => state.reset(),
40 #[cfg(target_arch = "aarch64")]
41 ArchExtendedPstateStorage::State32(state) => state.reset(),
42 }
43 }
44
45 fn with_arch(arch_width: ArchWidth) -> Self {
46 #[cfg(target_arch = "aarch64")]
47 if arch_width == ArchWidth::Arch32 {
48 return ArchExtendedPstateStorage::State32(Box::new(
49 extended_pstate::ExtendedAarch32PstateState::default(),
50 ));
51 }
52 let _ = arch_width;
53 ArchExtendedPstateStorage::State64(Box::new(ExtendedPstateState::default()))
54 }
55}
56
57pub struct ThreadState<T: RegisterStorage> {
60 pub registers: RegisterState<T>,
64
65 pub extended_pstate: ArchExtendedPstateStorage,
67
68 pub restart_code: Option<ErrnoCode>,
70
71 pub syscall_restart_func: Option<Box<SyscallRestartFunc>>,
75}
76
77impl<T: RegisterStorage + Default> Default for ThreadState<T> {
78 fn default() -> Self {
82 let registers = RegisterState::<T>::default();
83 let extended_pstate = ArchExtendedPstateStorage::with_arch(ArchWidth::Arch64);
84
85 Self { registers, extended_pstate, restart_code: None, syscall_restart_func: None }
86 }
87}
88
89impl<T: RegisterStorage> ThreadState<T> {
90 pub fn arch_width(&self) -> ArchWidth {
91 #[cfg(target_arch = "aarch64")]
92 {
93 return if self.registers.is_arch32() { ArchWidth::Arch32 } else { ArchWidth::Arch64 };
94 }
95 #[cfg(not(target_arch = "aarch64"))]
96 ArchWidth::Arch64
97 }
98
99 pub fn snapshot<R: RegisterStorage>(&self) -> ThreadState<R>
101 where
102 RegisterState<R>: From<RegisterState<T>>,
103 {
104 ThreadState::<R> {
105 registers: self.registers.clone().into(),
106 extended_pstate: self.extended_pstate.clone(),
107 restart_code: self.restart_code,
108 syscall_restart_func: None,
109 }
110 }
111
112 pub fn extended_snapshot<R: RegisterStorage>(&self) -> ThreadState<R>
113 where
114 RegisterState<R>: From<RegisterState<T>>,
115 {
116 ThreadState::<R> {
117 registers: self.registers.clone().into(),
118 extended_pstate: self.extended_pstate.clone(),
119 restart_code: self.restart_code,
120 syscall_restart_func: None,
121 }
122 }
123
124 pub fn replace_registers<O: RegisterStorage>(&mut self, other: &ThreadState<O>) {
125 let self_arch = self.arch_width();
126 let other_arch = other.arch_width();
127 self.registers.load(*other.registers);
128 self.extended_pstate = if self_arch == other_arch {
130 other.extended_pstate.clone()
131 } else {
132 ArchExtendedPstateStorage::with_arch(other_arch)
133 };
134 }
135
136 pub fn get_user_register(&mut self, offset: usize) -> Result<usize, Errno> {
137 let mut result: usize = 0;
138 self.registers.apply_user_register(offset, &mut |register| result = *register as usize)?;
139 Ok(result)
140 }
141
142 pub fn set_user_register(&mut self, offset: usize, value: usize) -> Result<(), Errno> {
143 let self_arch = self.arch_width();
144 let result =
145 self.registers.apply_user_register(offset, &mut |register| *register = value as u64);
146 if self_arch != self.arch_width() {
148 self.extended_pstate = ArchExtendedPstateStorage::with_arch(self.arch_width());
149 }
150 result
151 }
152}
153
154impl From<ThreadState<HeapRegs>> for ThreadState<RegisterStorageEnum> {
155 fn from(value: ThreadState<HeapRegs>) -> Self {
156 ThreadState {
157 registers: value.registers.into(),
158 extended_pstate: value.extended_pstate,
159 restart_code: value.restart_code,
160 syscall_restart_func: value.syscall_restart_func,
161 }
162 }
163}
164
165impl<T: RegisterStorage> ArchSpecific for ThreadState<T> {
166 fn is_arch32(&self) -> bool {
167 #[cfg(target_arch = "aarch64")]
168 return self.registers.is_arch32();
169 #[cfg(not(target_arch = "aarch64"))]
170 false
171 }
172}
173
174pub type SyscallRestartFunc = dyn FnOnce(&mut Locked<Unlocked>, &mut CurrentTask) -> Result<SyscallResult, Errno>
175 + Send
176 + Sync;