Skip to content

Commit 3847259

Browse files
authored
Merge pull request #370 from rust-osdev/addr
VirtAddr improvements
2 parents d4e330f + 872edf7 commit 3847259

File tree

3 files changed

+32
-32
lines changed

3 files changed

+32
-32
lines changed

src/addr.rs

+27-27
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const ADDRESS_SPACE_SIZE: u64 = 0x1_0000_0000_0000;
2222
/// between `u64` and `usize`.
2323
///
2424
/// On `x86_64`, only the 48 lower bits of a virtual address can be used. The top 16 bits need
25-
/// to be copies of bit 47, i.e. the most significant bit. Addresses that fulfil this criterium
25+
/// to be copies of bit 47, i.e. the most significant bit. Addresses that fulfil this criterion
2626
/// are called “canonical”. This type guarantees that it always represents a canonical address.
2727
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2828
#[repr(transparent)]
@@ -62,39 +62,43 @@ impl core::fmt::Debug for VirtAddrNotValid {
6262
impl VirtAddr {
6363
/// Creates a new canonical virtual address.
6464
///
65-
/// This function performs sign extension of bit 47 to make the address canonical.
65+
/// The provided address should already be canonical. If you want to check
66+
/// whether an address is canonical, use [`try_new`](Self::try_new).
6667
///
6768
/// ## Panics
6869
///
69-
/// This function panics if the bits in the range 48 to 64 contain data (i.e. are not null and no sign extension).
70-
#[inline]
71-
pub fn new(addr: u64) -> VirtAddr {
72-
Self::try_new(addr).expect(
73-
"address passed to VirtAddr::new must not contain any data \
74-
in bits 48 to 64",
75-
)
70+
/// This function panics if the bits in the range 48 to 64 are invalid
71+
/// (i.e. are not a proper sign extension of bit 47).
72+
#[inline]
73+
pub const fn new(addr: u64) -> VirtAddr {
74+
// TODO: Replace with .ok().expect(msg) when that works on stable.
75+
match Self::try_new(addr) {
76+
Ok(v) => v,
77+
Err(_) => panic!("virtual address must be sign extended in bits 48 to 64"),
78+
}
7679
}
7780

7881
/// Tries to create a new canonical virtual address.
7982
///
80-
/// This function tries to performs sign
81-
/// extension of bit 47 to make the address canonical. It succeeds if bits 48 to 64 are
82-
/// either a correct sign extension (i.e. copies of bit 47) or all null. Else, an error
83-
/// is returned.
84-
#[inline]
85-
pub fn try_new(addr: u64) -> Result<VirtAddr, VirtAddrNotValid> {
86-
match addr.get_bits(47..64) {
87-
0 | 0x1ffff => Ok(VirtAddr(addr)), // address is canonical
88-
1 => Ok(VirtAddr::new_truncate(addr)), // address needs sign extension
89-
_ => Err(VirtAddrNotValid(addr)),
83+
/// This function checks wether the given address is canonical
84+
/// and returns an error otherwise. An address is canonical
85+
/// if bits 48 to 64 are a correct sign
86+
/// extension (i.e. copies of bit 47).
87+
#[inline]
88+
pub const fn try_new(addr: u64) -> Result<VirtAddr, VirtAddrNotValid> {
89+
let v = Self::new_truncate(addr);
90+
if v.0 == addr {
91+
Ok(v)
92+
} else {
93+
Err(VirtAddrNotValid(addr))
9094
}
9195
}
9296

9397
/// Creates a new canonical virtual address, throwing out bits 48..64.
9498
///
95-
/// This function performs sign extension of bit 47 to make the address canonical, so
96-
/// bits 48 to 64 are overwritten. If you want to check that these bits contain no data,
97-
/// use `new` or `try_new`.
99+
/// This function performs sign extension of bit 47 to make the address
100+
/// canonical, overwriting bits 48 to 64. If you want to check whether an
101+
/// address is canonical, use [`new`](Self::new) or [`try_new`](Self::try_new).
98102
#[inline]
99103
pub const fn new_truncate(addr: u64) -> VirtAddr {
100104
// By doing the right shift as a signed operation (on a i64), it will
@@ -125,11 +129,7 @@ impl VirtAddr {
125129
}
126130

127131
/// Creates a virtual address from the given pointer
128-
// cfg(target_pointer_width = "32") is only here for backwards
129-
// compatibility: Earlier versions of this crate did not have any `cfg()`
130-
// on this function. At least for 32- and 64-bit we know the `as u64` cast
131-
// doesn't truncate.
132-
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
132+
#[cfg(target_pointer_width = "64")]
133133
#[inline]
134134
pub fn from_ptr<T>(ptr: *const T) -> Self {
135135
Self::new(ptr as u64)

src/instructions/interrupts.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,10 @@ where
109109
/// On some processors, the interrupt shadow of `sti` does not apply to
110110
/// non-maskable interrupts (NMIs). This means that an NMI can occur between
111111
/// the `sti` and `hlt` instruction, with the result that the CPU is put to
112-
/// sleep even though a new interrupt occured.
112+
/// sleep even though a new interrupt occurred.
113113
///
114114
/// To work around this, it is recommended to check in the NMI handler if
115-
/// the interrupt occured between `sti` and `hlt` instructions. If this is the
115+
/// the interrupt occurred between `sti` and `hlt` instructions. If this is the
116116
/// case, the handler should increase the instruction pointer stored in the
117117
/// interrupt stack frame so that the `hlt` instruction is skipped.
118118
///

src/structures/idt.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use super::gdt::SegmentSelector;
4242
/// first entry, the entry for the `divide_error` exception. Note that the index access is
4343
/// not possible for entries for which an error code is pushed.
4444
///
45-
/// The remaining entries are used for interrupts. They can be accesed through index
45+
/// The remaining entries are used for interrupts. They can be accessed through index
4646
/// operations on the idt, e.g. `idt[32]` returns the first interrupt entry, which is the 32nd IDT
4747
/// entry).
4848
///
@@ -1263,7 +1263,7 @@ macro_rules! set_general_handler {
12631263
#[macro_export]
12641264
#[doc(hidden)]
12651265
/// We can't loop in macros, but we can use recursion.
1266-
/// This macro recursivly adds one more bit to it's arguments until we have 8 bits so that we can call set_general_handler_entry.
1266+
/// This macro recursively adds one more bit to it's arguments until we have 8 bits so that we can call set_general_handler_entry.
12671267
macro_rules! set_general_handler_recursive_bits {
12681268
// if we have 8 all bits, construct the index from the bits, check if the entry is in range and invoke the macro that sets the handler
12691269
($idt:expr, $handler:ident, $range:expr, $bit7:tt, $bit6:tt, $bit5:tt, $bit4:tt, $bit3:tt, $bit2:tt, $bit1:tt, $bit0:tt) => {{
@@ -1274,7 +1274,7 @@ macro_rules! set_general_handler_recursive_bits {
12741274
$crate::set_general_handler_entry!($idt, $handler, IDX, $bit7, $bit6, $bit5, $bit4, $bit3, $bit2, $bit1, $bit0);
12751275
}
12761276
}};
1277-
// otherwise recursivly invoke the macro adding one more bit
1277+
// otherwise recursively invoke the macro adding one more bit
12781278
($idt:expr, $handler:ident, $range:expr $(, $bits:tt)*) => {
12791279
$crate::set_general_handler_recursive_bits!($idt, $handler, $range $(, $bits)*, 0);
12801280
$crate::set_general_handler_recursive_bits!($idt, $handler, $range $(, $bits)*, 1);

0 commit comments

Comments
 (0)