sparreal_kernel/mem/
addr.rs1use core::fmt::{Debug, Display};
2use core::marker::PhantomData;
3use core::ops::{Add, Deref, Range, Sub};
4use core::ptr::NonNull;
5
6#[derive(Debug, Clone, Copy)]
7pub struct Address {
8 pub cpu: usize,
9 pub virt: Option<usize>,
10 pub bus: Option<u64>,
11}
12
13impl Address {
14 pub fn new(cpu: usize, virt: Option<*mut u8>, bus: Option<u64>) -> Self {
15 Self {
16 cpu,
17 virt: virt.map(|s| s as usize),
18 bus,
19 }
20 }
21
22 pub fn as_ptr(&self) -> *const u8 {
23 match self.virt {
24 Some(virt) => virt as *const u8,
25 None => self.cpu as *const u8,
26 }
27 }
28
29 pub fn bus(&self) -> u64 {
30 match self.bus {
31 Some(bus) => bus,
32 None => self.cpu as _,
33 }
34 }
35
36 pub fn physical(&self) -> usize {
37 self.cpu
38 }
39}
40
41impl Add<usize> for Address {
42 type Output = Self;
43
44 fn add(self, rhs: usize) -> Self::Output {
45 Self {
46 cpu: self.cpu + rhs,
47 virt: self.virt.map(|s| s + rhs),
48 bus: self.bus.map(|s| s + rhs as u64),
49 }
50 }
51}
52
53impl Sub<usize> for Address {
54 type Output = Self;
55
56 fn sub(self, rhs: usize) -> Self::Output {
57 Self {
58 cpu: self.cpu - rhs,
59 virt: self.virt.map(|s| s - rhs),
60 bus: self.bus.map(|s| s - rhs as u64),
61 }
62 }
63}
64
65macro_rules! def_addr {
66 ($name:ident, $t:ty) => {
67 #[repr(transparent)]
68 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
69 pub struct $name<T>($t, core::marker::PhantomData<T>);
70
71 impl<T> $name<T> {
72 pub const fn new(val: $t) -> Self {
73 Self(val, core::marker::PhantomData)
74 }
75
76 pub fn raw(self) -> $t {
77 self.0
78 }
79
80 pub fn align_down(self, align: usize) -> Self {
81 (align_down(self.0 as _, align) as $t).into()
82 }
83
84 pub fn align_up(self, align: usize) -> Self {
85 (align_up(self.0 as _, align) as $t).into()
86 }
87
88 pub fn align_offset(self, align: usize) -> usize {
89 align_offset(self.0 as _, align)
90 }
91
92 pub fn is_aligned_4k(self) -> bool {
93 self.is_aligned_to(0x1000)
94 }
95
96 pub fn is_aligned_to(self, align: usize) -> bool {
97 self.align_offset(align) == 0
98 }
99 }
100 impl<T> core::fmt::Debug for $name<T> {
101 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
102 write!(f, "{:#x}", self.0)
103 }
104 }
105 impl<T> core::fmt::Display for $name<T> {
106 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107 write!(f, "{:#x}", self.0)
108 }
109 }
110 impl<T> From<$t> for $name<T> {
111 fn from(value: $t) -> Self {
112 Self(value, core::marker::PhantomData)
113 }
114 }
115 impl<T> From<$name<T>> for $t {
116 fn from(value: $name<T>) -> Self {
117 value.0
118 }
119 }
120
121 impl<T> core::ops::Add<usize> for $name<T> {
122 type Output = Self;
123
124 fn add(self, rhs: usize) -> Self::Output {
125 Self(self.0 as usize + rhs, core::marker::PhantomData)
126 }
127 }
128
129 impl<T> core::ops::Sub<usize> for $name<T> {
130 type Output = Self;
131
132 fn sub(self, rhs: usize) -> Self::Output {
133 Self(self.0 as usize - rhs, core::marker::PhantomData)
134 }
135 }
136
137 impl<T> core::ops::Sub<Self> for $name<T> {
138 type Output = usize;
139
140 fn sub(self, rhs: Self) -> Self::Output {
141 self.0 as usize - rhs.0 as usize
142 }
143 }
144 };
145}
146
147#[repr(C)]
148#[derive(Clone, Copy)]
149pub struct CRange<T: Debug + Sized + Clone + Copy> {
150 pub start: T,
151 pub end: T,
152}
153
154impl<T: Debug + Sized + Clone + Copy> CRange<T> {
155 pub fn to_range(&self) -> Range<T> {
156 self.start..self.end
157 }
158}
159
160impl<T: Debug + Sized + Clone + Copy> From<Range<T>> for CRange<T> {
161 fn from(value: Range<T>) -> Self {
162 Self {
163 start: value.start,
164 end: value.end,
165 }
166 }
167}
168
169impl<T: Debug + Sized + Clone + Copy> Debug for CRange<T> {
170 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
171 write!(f, "[{:?}, {:?})", self.start, self.end)
172 }
173}
174
175def_addr!(Virt, usize);
176def_addr!(Phys, usize);
177
178pub type VirtAddr = Virt<u8>;
179pub type PhysAddr = Phys<u8>;
180pub type VirtCRange = CRange<VirtAddr>;
181pub type PhysCRange = CRange<PhysAddr>;
182
183pub struct RunAddr(usize);
185
186pub const fn align_offset(addr: usize, align: usize) -> usize {
187 addr & (align - 1)
188}
189
190pub const fn align_down(addr: usize, align: usize) -> usize {
191 addr & !(align - 1)
192}
193
194pub const fn align_up(addr: usize, align: usize) -> usize {
195 (addr + align - 1) & !(align - 1)
196}
197
198impl<T> From<Virt<T>> for *const T {
199 fn from(value: Virt<T>) -> Self {
200 value.0 as _
201 }
202}
203
204impl<T> From<Virt<T>> for *mut T {
205 fn from(value: Virt<T>) -> *mut T {
206 value.0 as _
207 }
208}
209
210impl<T> From<NonNull<T>> for Virt<T> {
211 fn from(value: NonNull<T>) -> Self {
212 Self(value.as_ptr() as _, core::marker::PhantomData)
213 }
214}
215
216#[macro_export]
217macro_rules! pa {
218 (val: $val:expr) => {
219 Phys::new($val as _)
220 };
221}
222
223#[macro_export]
224macro_rules! va {
225 (val: $val:expr) => {
226 Virt::new($val as _)
227 };
228}