blob: c5cb6ffa4322854563dc14e1e8b9dde7c0dfaf06 [file] [log] [blame]
Imre Kisd5b96fd2024-09-11 17:04:32 +02001// SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
Imre Kis5f960442024-11-29 16:49:43 +01004use core::{fmt, ops::Range};
Imre Kisd5b96fd2024-09-11 17:04:32 +02005
Imre Kisc9a55ff2025-01-17 15:06:50 +01006use crate::TranslationRegime;
7
Imre Kis631127d2024-11-21 13:09:01 +01008use super::TranslationGranule;
Imre Kisd5b96fd2024-09-11 17:04:32 +02009
Imre Kis5f960442024-11-29 16:49:43 +010010#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
Imre Kisd5b96fd2024-09-11 17:04:32 +020011pub struct PhysicalAddress(pub(super) usize);
12
13impl PhysicalAddress {
Imre Kis1278c9f2025-01-15 19:48:36 +010014 /// Create a new PhysicalAddress from the raw address value
15 ///
16 /// # Safety
17 /// The address has to be a valid physical address
Imre Kisd5b96fd2024-09-11 17:04:32 +020018 pub const unsafe fn new(address: usize) -> Self {
19 Self(address)
20 }
21
22 pub const fn add_offset(self, offset: usize) -> Option<Self> {
23 if let Some(address) = self.0.checked_add(offset) {
24 Some(Self(address))
25 } else {
26 None
27 }
28 }
29
30 pub const fn identity_va(self) -> VirtualAddress {
31 VirtualAddress(self.0)
32 }
33
34 pub const fn diff(self, rhs: Self) -> Option<usize> {
35 self.0.checked_sub(rhs.0)
36 }
37}
38
39impl From<PhysicalAddress> for usize {
40 fn from(value: PhysicalAddress) -> Self {
41 value.0
42 }
43}
44
45impl From<PhysicalAddress> for u64 {
46 fn from(value: PhysicalAddress) -> Self {
47 value.0 as u64
48 }
49}
50
Imre Kis5f960442024-11-29 16:49:43 +010051impl fmt::Debug for PhysicalAddress {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
53 f.debug_tuple("PA")
54 .field(&format_args!("{:#x}", self.0))
55 .finish()
56 }
57}
58
59#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
Imre Kisd5b96fd2024-09-11 17:04:32 +020060pub struct VirtualAddress(pub(super) usize);
61
62impl VirtualAddress {
Imre Kis1278c9f2025-01-15 19:48:36 +010063 /// Create a new VirtualAddress from the raw address value
64 ///
65 /// # Safety
66 /// The address has to be a valid virtual address
Imre Kisd5b96fd2024-09-11 17:04:32 +020067 pub const unsafe fn new(address: usize) -> Self {
68 Self(address)
69 }
70
71 pub const fn add_offset(self, offset: usize) -> Option<Self> {
72 if let Some(address) = self.0.checked_add(offset) {
73 Some(Self(address))
74 } else {
75 None
76 }
77 }
78
79 pub const fn identity_pa(self) -> PhysicalAddress {
80 PhysicalAddress(self.0)
81 }
82
Imre Kis631127d2024-11-21 13:09:01 +010083 pub const fn mask_for_level<const VA_BITS: usize>(
84 self,
85 translation_granule: TranslationGranule<VA_BITS>,
86 level: isize,
87 ) -> Self {
88 Self(self.0 & (translation_granule.block_size_at_level(level) - 1))
Imre Kisd5b96fd2024-09-11 17:04:32 +020089 }
90
Imre Kis631127d2024-11-21 13:09:01 +010091 pub const fn get_level_index<const VA_BITS: usize>(
92 self,
93 translation_granule: TranslationGranule<VA_BITS>,
94 level: isize,
95 ) -> usize {
96 self.0 >> translation_granule.total_bits_at_level(level)
Imre Kisd5b96fd2024-09-11 17:04:32 +020097 }
98
Imre Kisc9a55ff2025-01-17 15:06:50 +010099 pub fn is_valid_in_regime<const VA_BITS: usize>(&self, regime: TranslationRegime) -> bool {
100 let mask = Self::get_upper_bit_mask::<VA_BITS>();
101 let required_upper_bits = if regime.is_upper_va_range() { mask } else { 0 };
102
103 (self.0 & mask) == required_upper_bits
104 }
105
106 pub fn set_upper_bits<const VA_BITS: usize>(self, regime: TranslationRegime) -> Self {
107 let mask = Self::get_upper_bit_mask::<VA_BITS>();
108
109 Self(if regime.is_upper_va_range() {
110 self.0 | mask
111 } else {
112 self.0 & !mask
113 })
114 }
115
116 pub fn remove_upper_bits<const VA_BITS: usize>(self) -> Self {
117 Self(self.0 & !Self::get_upper_bit_mask::<VA_BITS>())
118 }
119
Imre Kisd5b96fd2024-09-11 17:04:32 +0200120 pub const fn mask_bits(self, mask: usize) -> Self {
121 Self(self.0 & mask)
122 }
123
124 pub const fn diff(self, rhs: Self) -> Option<usize> {
125 self.0.checked_sub(rhs.0)
126 }
Imre Kisf0370e82024-11-18 16:24:55 +0100127
128 pub const fn align_up(self, alignment: usize) -> Self {
129 Self(self.0.next_multiple_of(alignment))
130 }
Imre Kisc9a55ff2025-01-17 15:06:50 +0100131
132 const fn get_upper_bit_mask<const VA_BITS: usize>() -> usize {
133 !((1 << VA_BITS) - 1)
134 }
Imre Kisd5b96fd2024-09-11 17:04:32 +0200135}
136
137impl From<VirtualAddress> for usize {
138 fn from(value: VirtualAddress) -> Self {
139 value.0
140 }
141}
142
143impl From<VirtualAddress> for u64 {
144 fn from(value: VirtualAddress) -> Self {
145 value.0 as u64
146 }
147}
148
Imre Kis5f960442024-11-29 16:49:43 +0100149impl fmt::Debug for VirtualAddress {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
151 f.debug_tuple("VA")
152 .field(&format_args!("{:#x}", self.0))
153 .finish()
154 }
155}
156
Imre Kisc9a55ff2025-01-17 15:06:50 +0100157#[derive(Debug)]
Imre Kisd5b96fd2024-09-11 17:04:32 +0200158pub struct VirtualAddressRange {
159 pub(super) start: VirtualAddress,
160 pub(super) end: VirtualAddress,
161}
162
163impl VirtualAddressRange {
164 pub fn new(start: VirtualAddress, end: VirtualAddress) -> Self {
165 Self { start, end }
166 }
167
Imre Kis1278c9f2025-01-15 19:48:36 +0100168 /// Create a new VirtualAddressRange from the raw address values
169 ///
170 /// # Safety
171 /// The addresses have to be valid virtual addresses
Imre Kisd5b96fd2024-09-11 17:04:32 +0200172 pub unsafe fn from_range(value: Range<usize>) -> Self {
173 Self::new(
174 VirtualAddress::new(value.start),
175 VirtualAddress::new(value.end),
176 )
177 }
178
179 pub fn len(&self) -> Option<usize> {
180 self.end.diff(self.start)
181 }
182
183 pub fn step_by(self, step: usize) -> VirtualAddressIterator {
184 VirtualAddressIterator {
185 next: self.start,
186 end: self.end,
187 step,
188 }
189 }
190}
191
192pub struct VirtualAddressIterator {
193 next: VirtualAddress,
194 end: VirtualAddress,
195 step: usize,
196}
197
198impl Iterator for VirtualAddressIterator {
199 type Item = VirtualAddress;
200
201 fn next(&mut self) -> Option<Self::Item> {
202 if self.next < self.end {
203 let current = self.next;
204
205 self.next = if let Some(next) = self.next.add_offset(self.step) {
206 next
207 } else {
208 self.end
209 };
210
211 Some(current)
212 } else {
213 None
214 }
215 }
216}