@@ -121,13 +121,23 @@ macro_rules! implement_address {
121
121
122
122
#[ cfg( target_arch = "x86_64" ) ]
123
123
mod canonical_address {
124
- use bit_field:: BitField ;
124
+ const CANONICAL_VIRT_ADDR_MASK : usize = 0x0000_7FFF_FFFF_FFFF ;
125
+ const CANONICAL_PHYS_ADDR_MASK : usize = 0x000F_FFFF_FFFF_FFFF ;
125
126
127
+ /// Returns whether the given virtual address value is canonical.
128
+ ///
129
+ /// On x86_64, virtual addresses must have their 16 most-significant bits
130
+ /// be sign-extended from bit 47.
126
131
#[ inline]
127
- pub fn is_canonical_virtual_address ( virt_addr : usize ) -> bool {
128
- matches ! ( virt_addr. get_bits( 47 ..64 ) , 0 | 0b1_1111_1111_1111_1111 )
132
+ pub const fn is_canonical_virtual_address ( virt_addr : usize ) -> bool {
133
+ let upper17 = virt_addr & !CANONICAL_VIRT_ADDR_MASK ;
134
+ upper17 == 0 || upper17 == !CANONICAL_VIRT_ADDR_MASK
129
135
}
130
136
137
+ /// Returns a canonicalized instance of the given virtual address value.
138
+ ///
139
+ /// On x86_64, virtual addresses must have their 16 most-significant bits
140
+ /// be sign-extended from bit 47.
131
141
#[ inline]
132
142
pub const fn canonicalize_virtual_address ( virt_addr : usize ) -> usize {
133
143
// match virt_addr.get_bit(47) {
@@ -139,57 +149,72 @@ mod canonical_address {
139
149
( ( virt_addr << 16 ) as isize >> 16 ) as usize
140
150
}
141
151
152
+ /// Returns whether the given phyiscal address value is canonical.
153
+ ///
154
+ /// On x86_64, physical addresses are 52 bits long,
155
+ /// so their 12 most-significant bits must be cleared.
142
156
#[ inline]
143
- pub fn is_canonical_physical_address ( phys_addr : usize ) -> bool {
144
- matches ! ( phys_addr. get_bits ( 52 .. 64 ) , 0 )
157
+ pub const fn is_canonical_physical_address ( phys_addr : usize ) -> bool {
158
+ phys_addr & ! CANONICAL_PHYS_ADDR_MASK == 0
145
159
}
146
160
161
+ /// Returns a canonicalized instance of the given phyiscal address value.
162
+ ///
163
+ /// On x86_64, physical addresses are 52 bits long,
164
+ /// so their 12 most-significant bits must be cleared.
147
165
#[ inline]
148
166
pub const fn canonicalize_physical_address ( phys_addr : usize ) -> usize {
149
- phys_addr & 0x000F_FFFF_FFFF_FFFF
167
+ phys_addr & CANONICAL_PHYS_ADDR_MASK
150
168
}
151
169
}
152
170
153
171
#[ cfg( target_arch = "aarch64" ) ]
154
172
mod canonical_address {
155
- use bit_field:: BitField ;
156
-
157
- /// On aarch64, VAs are composed of an ASID
158
- /// which is 8 or 16 bits long depending
159
- /// on MMU config. In Theseus, we use 8-bits
160
- /// and the next 8 bits are unused.
161
- /// Our ASID is zero, so a "canonical" VA has
162
- /// the 16 most significant bits cleared.
173
+ const CANONICAL_VIRT_ADDR_MASK : usize = 0x0000_FFFF_FFFF_FFFF ;
174
+ const CANONICAL_PHYS_ADDR_MASK : usize = 0x0000_FFFF_FFFF_FFFF ;
175
+
176
+ /// Returns whether the given virtual address value is canonical.
177
+ ///
178
+ /// On aarch64, virtual addresses contain an address space ID (ASID),
179
+ /// which is 8 or 16 bits long, depending on MMU config.
180
+ ///
181
+ /// In Theseus, we use 8-bit ASIDs, with the next 8 bits are unused.
182
+ /// Theseus's ASID is zero, so a canonical virtual address has its
183
+ /// 16 most-significant bits cleared (set to zero).
163
184
#[ inline]
164
- pub fn is_canonical_virtual_address ( virt_addr : usize ) -> bool {
165
- matches ! ( virt_addr. get_bits ( 48 .. 64 ) , 0 )
185
+ pub const fn is_canonical_virtual_address ( virt_addr : usize ) -> bool {
186
+ virt_addr & ! CANONICAL_VIRT_ADDR_MASK == 0
166
187
}
167
188
168
- /// On aarch64, VAs are composed of an ASID
169
- /// which is 8 or 16 bits long depending
170
- /// on MMU config. In Theseus, we use 8-bits
171
- /// and the next 8 bits are unused.
172
- /// Our ASID is zero, so a "canonical" VA has
173
- /// the 16 most significant bits cleared.
189
+ /// Returns a canonicalized instance of the given virtual address value.
190
+ ///
191
+ /// On aarch64, virtual addresses contain an address space ID (ASID),
192
+ /// which is 8 or 16 bits long, depending on MMU config.
193
+ ///
194
+ /// In Theseus, we use 8-bit ASIDs, with the next 8 bits are unused.
195
+ /// Theseus's ASID is zero, so a virtual address is canonicalized
196
+ /// by clearing (setting to zero) its 16 most-significant bits.
174
197
#[ inline]
175
198
pub const fn canonicalize_virtual_address ( virt_addr : usize ) -> usize {
176
- virt_addr & 0x0000_FFFF_FFFF_FFFF
199
+ virt_addr & CANONICAL_VIRT_ADDR_MASK
177
200
}
178
201
179
- /// On aarch64, we configure the MMU to use 48-bit
180
- /// physical addresses; "canonical" physical addresses
181
- /// have the 16 most significant bits cleared.
202
+ /// Returns whether the given physical address value is canonical.
203
+ ///
204
+ /// On aarch64, Theseus configures the MMU to use 48-bit physical addresses.
205
+ /// Thus, a canonical physical address has its 16 most-significant bits cleared.
182
206
#[ inline]
183
- pub fn is_canonical_physical_address ( phys_addr : usize ) -> bool {
184
- matches ! ( phys_addr. get_bits ( 48 .. 64 ) , 0 )
207
+ pub const fn is_canonical_physical_address ( phys_addr : usize ) -> bool {
208
+ phys_addr & ! CANONICAL_PHYS_ADDR_MASK == 0
185
209
}
186
210
187
- /// On aarch64, we configure the MMU to use 48-bit
188
- /// physical addresses; "canonical" physical addresses
189
- /// have the 16 most significant bits cleared.
211
+ /// Returns a canonicalized instance of the given physical address value.
212
+ ///
213
+ /// On aarch64, Theseus configures the MMU to use 48-bit physical addresses.
214
+ /// Thus, a physical address is canonicalized by clearing its 16 most-significant bits.
190
215
#[ inline]
191
216
pub const fn canonicalize_physical_address ( phys_addr : usize ) -> usize {
192
- phys_addr & 0x0000_FFFF_FFFF_FFFF
217
+ phys_addr & CANONICAL_PHYS_ADDR_MASK
193
218
}
194
219
}
195
220
@@ -355,13 +380,15 @@ macro_rules! implement_page_frame_range {
355
380
356
381
#[ doc = "A convenience method for creating a new `" $TypeName "` that spans \
357
382
all [`" $chunk "`]s from the given [`" $address "`] to an end bound based on the given size." ]
358
- pub fn [ <from_ $short _addr>] ( starting_addr: $address, size_in_bytes: usize ) -> $TypeName {
383
+ pub const fn [ <from_ $short _addr>] ( starting_addr: $address, size_in_bytes: usize ) -> $TypeName {
359
384
if size_in_bytes == 0 {
360
385
$TypeName:: empty( )
361
386
} else {
362
387
let start = $chunk:: containing_address( starting_addr) ;
363
388
// The end bound is inclusive, hence the -1. Parentheses are needed to avoid overflow.
364
- let end = $chunk:: containing_address( starting_addr + ( size_in_bytes - 1 ) ) ;
389
+ let end = $chunk:: containing_address(
390
+ $address:: new_canonical( starting_addr. value( ) + ( size_in_bytes - 1 ) )
391
+ ) ;
365
392
$TypeName:: new( start, end)
366
393
}
367
394
}
@@ -385,16 +412,18 @@ macro_rules! implement_page_frame_range {
385
412
}
386
413
387
414
#[ doc = "Returns `true` if this `" $TypeName "` contains the given [`" $address "`]." ]
388
- pub fn contains_address( & self , addr: $address) -> bool {
389
- self . 0 . contains( & $chunk:: containing_address( addr) )
415
+ pub const fn contains_address( & self , addr: $address) -> bool {
416
+ let c = $chunk:: containing_address( addr) ;
417
+ self . 0 . start( ) . number <= c. number
418
+ && c. number <= self . 0 . end( ) . number
390
419
}
391
420
392
421
#[ doc = "Returns the offset of the given [`" $address "`] within this `" $TypeName "`, \
393
422
i.e., `addr - self.start_address()`.\n \n \
394
423
If the given `addr` is not covered by this range of [`" $chunk "`]s, this returns `None`.\n \n \
395
424
# Examples\n \
396
425
If the range covers addresses `0x2000` to `0x4000`, then `offset_of_address(0x3500)` would return `Some(0x1500)`."]
397
- pub fn offset_of_address( & self , addr: $address) -> Option <usize > {
426
+ pub const fn offset_of_address( & self , addr: $address) -> Option <usize > {
398
427
if self . contains_address( addr) {
399
428
Some ( addr. value( ) - self . start_address( ) . value( ) )
400
429
} else {
@@ -403,13 +432,14 @@ macro_rules! implement_page_frame_range {
403
432
}
404
433
405
434
#[ doc = "Returns the [`" $address "`] at the given `offset` into this `" $TypeName "`within this `" $TypeName "`, \
406
- i.e., `addr - self.start_address()`.\n \n \
435
+ i.e., `self.start_address() + offset `.\n \n \
407
436
If the given `offset` is not within this range of [`" $chunk "`]s, this returns `None`.\n \n \
408
437
# Examples\n \
409
- If the range covers addresses `0x2000` to `0x4000`, then `address_at_offset(0x1500)` would return `Some(0x3500)`."]
410
- pub fn address_at_offset( & self , offset: usize ) -> Option <$address> {
411
- if offset <= self . size_in_bytes( ) {
412
- Some ( self . start_address( ) + offset)
438
+ If the range covers addresses `0x2000` through `0x3FFF`, then `address_at_offset(0x1500)` would return `Some(0x3500)`, \
439
+ and `address_at_offset(0x2000)` would return `None`."]
440
+ pub const fn address_at_offset( & self , offset: usize ) -> Option <$address> {
441
+ if offset < self . size_in_bytes( ) {
442
+ Some ( $address:: new_canonical( self . start_address( ) . value( ) + offset) )
413
443
}
414
444
else {
415
445
None
0 commit comments