blob: 5068f29cf647db2039b21ff6ef60b20e796e8548 [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 Kis631127d2024-11-21 13:09:01 +01006use super::TranslationGranule;
Imre Kisd5b96fd2024-09-11 17:04:32 +02007
Imre Kis5f960442024-11-29 16:49:43 +01008#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
Imre Kisd5b96fd2024-09-11 17:04:32 +02009pub struct PhysicalAddress(pub(super) usize);
10
11impl PhysicalAddress {
Imre Kis1278c9f2025-01-15 19:48:36 +010012 /// Create a new PhysicalAddress from the raw address value
13 ///
14 /// # Safety
15 /// The address has to be a valid physical address
Imre Kisd5b96fd2024-09-11 17:04:32 +020016 pub const unsafe fn new(address: usize) -> Self {
17 Self(address)
18 }
19
20 pub const fn add_offset(self, offset: usize) -> Option<Self> {
21 if let Some(address) = self.0.checked_add(offset) {
22 Some(Self(address))
23 } else {
24 None
25 }
26 }
27
28 pub const fn identity_va(self) -> VirtualAddress {
29 VirtualAddress(self.0)
30 }
31
32 pub const fn diff(self, rhs: Self) -> Option<usize> {
33 self.0.checked_sub(rhs.0)
34 }
35}
36
37impl From<PhysicalAddress> for usize {
38 fn from(value: PhysicalAddress) -> Self {
39 value.0
40 }
41}
42
43impl From<PhysicalAddress> for u64 {
44 fn from(value: PhysicalAddress) -> Self {
45 value.0 as u64
46 }
47}
48
Imre Kis5f960442024-11-29 16:49:43 +010049impl fmt::Debug for PhysicalAddress {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
51 f.debug_tuple("PA")
52 .field(&format_args!("{:#x}", self.0))
53 .finish()
54 }
55}
56
57#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
Imre Kisd5b96fd2024-09-11 17:04:32 +020058pub struct VirtualAddress(pub(super) usize);
59
60impl VirtualAddress {
Imre Kis1278c9f2025-01-15 19:48:36 +010061 /// Create a new VirtualAddress from the raw address value
62 ///
63 /// # Safety
64 /// The address has to be a valid virtual address
Imre Kisd5b96fd2024-09-11 17:04:32 +020065 pub const unsafe fn new(address: usize) -> Self {
66 Self(address)
67 }
68
69 pub const fn add_offset(self, offset: usize) -> Option<Self> {
70 if let Some(address) = self.0.checked_add(offset) {
71 Some(Self(address))
72 } else {
73 None
74 }
75 }
76
77 pub const fn identity_pa(self) -> PhysicalAddress {
78 PhysicalAddress(self.0)
79 }
80
Imre Kis631127d2024-11-21 13:09:01 +010081 pub const fn mask_for_level<const VA_BITS: usize>(
82 self,
83 translation_granule: TranslationGranule<VA_BITS>,
84 level: isize,
85 ) -> Self {
86 Self(self.0 & (translation_granule.block_size_at_level(level) - 1))
Imre Kisd5b96fd2024-09-11 17:04:32 +020087 }
88
Imre Kis631127d2024-11-21 13:09:01 +010089 pub const fn get_level_index<const VA_BITS: usize>(
90 self,
91 translation_granule: TranslationGranule<VA_BITS>,
92 level: isize,
93 ) -> usize {
94 self.0 >> translation_granule.total_bits_at_level(level)
Imre Kisd5b96fd2024-09-11 17:04:32 +020095 }
96
97 pub const fn mask_bits(self, mask: usize) -> Self {
98 Self(self.0 & mask)
99 }
100
101 pub const fn diff(self, rhs: Self) -> Option<usize> {
102 self.0.checked_sub(rhs.0)
103 }
Imre Kisf0370e82024-11-18 16:24:55 +0100104
105 pub const fn align_up(self, alignment: usize) -> Self {
106 Self(self.0.next_multiple_of(alignment))
107 }
Imre Kisd5b96fd2024-09-11 17:04:32 +0200108}
109
110impl From<VirtualAddress> for usize {
111 fn from(value: VirtualAddress) -> Self {
112 value.0
113 }
114}
115
116impl From<VirtualAddress> for u64 {
117 fn from(value: VirtualAddress) -> Self {
118 value.0 as u64
119 }
120}
121
Imre Kis5f960442024-11-29 16:49:43 +0100122impl fmt::Debug for VirtualAddress {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
124 f.debug_tuple("VA")
125 .field(&format_args!("{:#x}", self.0))
126 .finish()
127 }
128}
129
Imre Kisd5b96fd2024-09-11 17:04:32 +0200130pub struct VirtualAddressRange {
131 pub(super) start: VirtualAddress,
132 pub(super) end: VirtualAddress,
133}
134
135impl VirtualAddressRange {
136 pub fn new(start: VirtualAddress, end: VirtualAddress) -> Self {
137 Self { start, end }
138 }
139
Imre Kis1278c9f2025-01-15 19:48:36 +0100140 /// Create a new VirtualAddressRange from the raw address values
141 ///
142 /// # Safety
143 /// The addresses have to be valid virtual addresses
Imre Kisd5b96fd2024-09-11 17:04:32 +0200144 pub unsafe fn from_range(value: Range<usize>) -> Self {
145 Self::new(
146 VirtualAddress::new(value.start),
147 VirtualAddress::new(value.end),
148 )
149 }
150
151 pub fn len(&self) -> Option<usize> {
152 self.end.diff(self.start)
153 }
154
155 pub fn step_by(self, step: usize) -> VirtualAddressIterator {
156 VirtualAddressIterator {
157 next: self.start,
158 end: self.end,
159 step,
160 }
161 }
162}
163
164pub struct VirtualAddressIterator {
165 next: VirtualAddress,
166 end: VirtualAddress,
167 step: usize,
168}
169
170impl Iterator for VirtualAddressIterator {
171 type Item = VirtualAddress;
172
173 fn next(&mut self) -> Option<Self::Item> {
174 if self.next < self.end {
175 let current = self.next;
176
177 self.next = if let Some(next) = self.next.add_offset(self.step) {
178 next
179 } else {
180 self.end
181 };
182
183 Some(current)
184 } else {
185 None
186 }
187 }
188}