blob: 320a0d2eb4c047a4d7a9deea4236c0919a3e5585 [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 {
12 pub const unsafe fn new(address: usize) -> Self {
13 Self(address)
14 }
15
16 pub const fn add_offset(self, offset: usize) -> Option<Self> {
17 if let Some(address) = self.0.checked_add(offset) {
18 Some(Self(address))
19 } else {
20 None
21 }
22 }
23
24 pub const fn identity_va(self) -> VirtualAddress {
25 VirtualAddress(self.0)
26 }
27
28 pub const fn diff(self, rhs: Self) -> Option<usize> {
29 self.0.checked_sub(rhs.0)
30 }
31}
32
33impl From<PhysicalAddress> for usize {
34 fn from(value: PhysicalAddress) -> Self {
35 value.0
36 }
37}
38
39impl From<PhysicalAddress> for u64 {
40 fn from(value: PhysicalAddress) -> Self {
41 value.0 as u64
42 }
43}
44
Imre Kis5f960442024-11-29 16:49:43 +010045impl fmt::Debug for PhysicalAddress {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
47 f.debug_tuple("PA")
48 .field(&format_args!("{:#x}", self.0))
49 .finish()
50 }
51}
52
53#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
Imre Kisd5b96fd2024-09-11 17:04:32 +020054pub struct VirtualAddress(pub(super) usize);
55
56impl VirtualAddress {
57 pub const unsafe fn new(address: usize) -> Self {
58 Self(address)
59 }
60
61 pub const fn add_offset(self, offset: usize) -> Option<Self> {
62 if let Some(address) = self.0.checked_add(offset) {
63 Some(Self(address))
64 } else {
65 None
66 }
67 }
68
69 pub const fn identity_pa(self) -> PhysicalAddress {
70 PhysicalAddress(self.0)
71 }
72
Imre Kis631127d2024-11-21 13:09:01 +010073 pub const fn mask_for_level<const VA_BITS: usize>(
74 self,
75 translation_granule: TranslationGranule<VA_BITS>,
76 level: isize,
77 ) -> Self {
78 Self(self.0 & (translation_granule.block_size_at_level(level) - 1))
Imre Kisd5b96fd2024-09-11 17:04:32 +020079 }
80
Imre Kis631127d2024-11-21 13:09:01 +010081 pub const fn get_level_index<const VA_BITS: usize>(
82 self,
83 translation_granule: TranslationGranule<VA_BITS>,
84 level: isize,
85 ) -> usize {
86 self.0 >> translation_granule.total_bits_at_level(level)
Imre Kisd5b96fd2024-09-11 17:04:32 +020087 }
88
89 pub const fn mask_bits(self, mask: usize) -> Self {
90 Self(self.0 & mask)
91 }
92
93 pub const fn diff(self, rhs: Self) -> Option<usize> {
94 self.0.checked_sub(rhs.0)
95 }
Imre Kisf0370e82024-11-18 16:24:55 +010096
97 pub const fn align_up(self, alignment: usize) -> Self {
98 Self(self.0.next_multiple_of(alignment))
99 }
Imre Kisd5b96fd2024-09-11 17:04:32 +0200100}
101
102impl From<VirtualAddress> for usize {
103 fn from(value: VirtualAddress) -> Self {
104 value.0
105 }
106}
107
108impl From<VirtualAddress> for u64 {
109 fn from(value: VirtualAddress) -> Self {
110 value.0 as u64
111 }
112}
113
Imre Kis5f960442024-11-29 16:49:43 +0100114impl fmt::Debug for VirtualAddress {
115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
116 f.debug_tuple("VA")
117 .field(&format_args!("{:#x}", self.0))
118 .finish()
119 }
120}
121
Imre Kisd5b96fd2024-09-11 17:04:32 +0200122pub struct VirtualAddressRange {
123 pub(super) start: VirtualAddress,
124 pub(super) end: VirtualAddress,
125}
126
127impl VirtualAddressRange {
128 pub fn new(start: VirtualAddress, end: VirtualAddress) -> Self {
129 Self { start, end }
130 }
131
132 pub unsafe fn from_range(value: Range<usize>) -> Self {
133 Self::new(
134 VirtualAddress::new(value.start),
135 VirtualAddress::new(value.end),
136 )
137 }
138
139 pub fn len(&self) -> Option<usize> {
140 self.end.diff(self.start)
141 }
142
143 pub fn step_by(self, step: usize) -> VirtualAddressIterator {
144 VirtualAddressIterator {
145 next: self.start,
146 end: self.end,
147 step,
148 }
149 }
150}
151
152pub struct VirtualAddressIterator {
153 next: VirtualAddress,
154 end: VirtualAddress,
155 step: usize,
156}
157
158impl Iterator for VirtualAddressIterator {
159 type Item = VirtualAddress;
160
161 fn next(&mut self) -> Option<Self::Item> {
162 if self.next < self.end {
163 let current = self.next;
164
165 self.next = if let Some(next) = self.next.add_offset(self.step) {
166 next
167 } else {
168 self.end
169 };
170
171 Some(current)
172 } else {
173 None
174 }
175 }
176}