1#![cfg_attr(not(test), no_std)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![deny(missing_docs)]
4#![doc = include_str!("../README.md")]
5
6#[cfg(all(feature = "host-test", not(target_os = "none")))]
7extern crate std;
8
9#[macro_use]
10extern crate log;
11
12#[macro_use]
13extern crate ax_memory_addr;
14
15#[macro_use]
16pub mod trap;
17
18pub use trap::TrapOrigin;
19
20mod task_local;
21pub use task_local::TaskLocalState;
22
23pub mod cap;
24
25pub mod paging;
26
27#[repr(transparent)]
32#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
33pub struct KernelTlsBase(usize);
34
35impl KernelTlsBase {
36 pub const fn new(address: usize) -> Self {
38 Self(address)
39 }
40
41 pub const fn as_usize(self) -> usize {
43 self.0
44 }
45
46 pub(crate) fn for_task_context(requested: Self) -> Self {
47 if cfg!(kernel_tls) {
48 requested
49 } else {
50 assert!(
51 requested.0 == 0,
52 "LinuxCurrent task contexts must not own a kernel TLS register"
53 );
54 Self(0)
55 }
56 }
57}
58
59#[derive(Clone, Copy, Debug, Eq, PartialEq)]
61pub enum InstalledAddressSpaceMode {
62 Tagged,
65 FullFlush,
68}
69
70#[derive(Clone, Copy, Debug, Eq, PartialEq)]
76pub struct InstalledAddressSpace {
77 space_id: u64,
78 root: ax_memory_addr::PhysAddr,
79 hardware_tag: u16,
80 tag_generation: u64,
81 epoch: u64,
82 mode: InstalledAddressSpaceMode,
83}
84
85impl InstalledAddressSpace {
86 pub fn user(
91 space_id: u64,
92 root: ax_memory_addr::PhysAddr,
93 hardware_tag: u16,
94 tag_generation: u64,
95 epoch: u64,
96 mode: InstalledAddressSpaceMode,
97 ) -> Option<Self> {
98 if space_id == 0 || root.as_usize() == 0 {
99 return None;
100 }
101 match mode {
102 InstalledAddressSpaceMode::Tagged if hardware_tag == 0 => return None,
103 InstalledAddressSpaceMode::FullFlush if hardware_tag != 0 => return None,
104 InstalledAddressSpaceMode::Tagged | InstalledAddressSpaceMode::FullFlush => {}
105 }
106 Some(Self {
107 space_id,
108 root,
109 hardware_tag,
110 tag_generation,
111 epoch,
112 mode,
113 })
114 }
115
116 pub const fn kernel(root: ax_memory_addr::PhysAddr) -> Self {
119 Self {
120 space_id: 0,
121 root,
122 hardware_tag: 0,
123 tag_generation: 0,
124 epoch: 0,
125 mode: InstalledAddressSpaceMode::FullFlush,
126 }
127 }
128
129 pub const fn is_user(self) -> bool {
131 self.space_id != 0
132 }
133
134 pub const fn space_id(self) -> u64 {
136 self.space_id
137 }
138
139 pub const fn hardware_tag(self) -> u16 {
141 self.hardware_tag
142 }
143
144 pub const fn tag_generation(self) -> u64 {
146 self.tag_generation
147 }
148
149 pub const fn epoch(self) -> u64 {
151 self.epoch
152 }
153
154 pub const fn mode(self) -> InstalledAddressSpaceMode {
156 self.mode
157 }
158
159 #[cfg(feature = "uspace")]
160 pub(crate) const fn root(self) -> ax_memory_addr::PhysAddr {
161 self.root
162 }
163
164 #[cfg(feature = "uspace")]
165 pub(crate) fn validate_architecture_support(self) {
166 #[cfg(any(
167 target_arch = "x86_64",
168 target_arch = "riscv32",
169 target_arch = "riscv64",
170 target_arch = "loongarch64"
171 ))]
172 debug_assert!(
173 self.root.as_usize() != 0,
174 "this architecture requires a materialized kernel or userspace root"
175 );
176
177 #[cfg(target_arch = "aarch64")]
178 debug_assert!(
179 !self.is_user() || self.root.as_usize() != 0,
180 "a userspace identity always requires a materialized root"
181 );
182 }
183}
184
185impl Default for InstalledAddressSpace {
186 fn default() -> Self {
187 Self::kernel(ax_memory_addr::PhysAddr::from_usize(0))
188 }
189}
190
191#[cfg(feature = "exception-table")]
192mod exception_table;
193#[cfg(feature = "uspace")]
194mod user_access;
195#[cfg(feature = "uspace")]
196mod uspace_common;
197#[cfg(feature = "uspace")]
198pub use user_access::{
199 UserAccessError, UserAccessType, UserAtomicError, UserAtomicU32Op, user_atomic_u32,
200 user_read_u32,
201};
202
203cfg_if::cfg_if! {
204 if #[cfg(target_arch = "x86_64")] {
205 mod x86_64;
206 pub use self::x86_64::*;
207 } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] {
208 mod riscv;
209 pub use self::riscv::*;
210 } else if #[cfg(target_arch = "aarch64")]{
211 mod aarch64;
212 pub use self::aarch64::*;
213 } else if #[cfg(any(target_arch = "loongarch64"))] {
214 mod loongarch64;
215 pub use self::loongarch64::*;
216 }
217}