Merge branch 'virt_is_canonical' into 'master'
Add Arch::virt_is_valid See merge request redox-os/rmm!4
This commit is contained in:
@@ -84,6 +84,11 @@ impl Arch for AArch64Arch {
|
||||
//TODO: Does this need to be called?
|
||||
Self::invalidate_all();
|
||||
}
|
||||
|
||||
fn virt_is_valid(address: VirtualAddress) -> bool {
|
||||
// FIXME
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -101,6 +101,10 @@ impl Arch for EmulateArch {
|
||||
unsafe fn set_table(address: PhysicalAddress) {
|
||||
MACHINE.as_mut().unwrap().set_table(address);
|
||||
}
|
||||
fn virt_is_valid(_address: VirtualAddress) -> bool {
|
||||
// TODO: Don't see why an emulated arch would have any problems with canonicalness...
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
const MEMORY_SIZE: usize = 64 * MEGABYTE;
|
||||
|
||||
@@ -3,6 +3,7 @@ use core::ptr;
|
||||
use crate::{
|
||||
MemoryArea,
|
||||
PhysicalAddress,
|
||||
TableKind,
|
||||
VirtualAddress,
|
||||
};
|
||||
|
||||
@@ -84,4 +85,6 @@ pub trait Arch: Clone + Copy {
|
||||
unsafe fn phys_to_virt(phys: PhysicalAddress) -> VirtualAddress {
|
||||
VirtualAddress::new(phys.data() + Self::PHYS_OFFSET)
|
||||
}
|
||||
|
||||
fn virt_is_valid(address: VirtualAddress) -> bool;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::{
|
||||
Arch,
|
||||
MemoryArea,
|
||||
PhysicalAddress,
|
||||
TableKind,
|
||||
VirtualAddress,
|
||||
};
|
||||
|
||||
@@ -58,6 +59,13 @@ impl Arch for RiscV64Sv39Arch {
|
||||
(address.data() >> Self::PAGE_SHIFT); // Convert to PPN (TODO: ensure alignment)
|
||||
asm!("csrw satp, {0}", in(reg) satp);
|
||||
}
|
||||
|
||||
fn virt_is_valid(address: VirtualAddress) -> bool {
|
||||
const MASK: usize = 0xFFFF_FFC0_0000_0000;
|
||||
let masked = address.data() & MASK;
|
||||
|
||||
masked == MASK || masked == 0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -83,4 +91,29 @@ mod tests {
|
||||
|
||||
assert_eq!(RiscV64Sv39Arch::PHYS_OFFSET, 0xFFFF_FE00_0000_0000);
|
||||
}
|
||||
#[test]
|
||||
fn is_canonical() {
|
||||
use super::VirtualAddress;
|
||||
|
||||
#[track_caller]
|
||||
fn yes(addr: usize) {
|
||||
assert!(RiscV64Sv39Arch::virt_is_valid(VirtualAddress::new(addr)));
|
||||
}
|
||||
#[track_caller]
|
||||
fn no(addr: usize) {
|
||||
assert!(!RiscV64Sv39Arch::virt_is_valid(VirtualAddress::new(addr)));
|
||||
}
|
||||
|
||||
yes(0xFFFF_FFFF_FFFF_FFFF);
|
||||
yes(0xFFFF_FFF0_1337_1337);
|
||||
no(0x0000_0F00_0000_0000);
|
||||
no(0x1337_0000_0000_0000);
|
||||
no(1 << 38);
|
||||
yes(1 << 37);
|
||||
|
||||
// Check for off-by-one errors.
|
||||
yes(0xFFFF_FFC0_0000_0000 | (1 << 37));
|
||||
yes(0xFFFF_FFE0_0000_0000 | (1 << 37));
|
||||
no(0xFFFF_FF80_0000_0000 | (1 << 37));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::{
|
||||
Arch,
|
||||
MemoryArea,
|
||||
PhysicalAddress,
|
||||
TableKind,
|
||||
VirtualAddress,
|
||||
};
|
||||
|
||||
@@ -58,6 +59,14 @@ impl Arch for RiscV64Sv48Arch {
|
||||
(address.data() >> Self::PAGE_SHIFT); // Convert to PPN (TODO: ensure alignment)
|
||||
asm!("csrw satp, {0}", in(reg) satp);
|
||||
}
|
||||
fn virt_is_valid(address: VirtualAddress) -> bool {
|
||||
// RISC-V SV48 uses 48-bit sign-extended addresses, identical to 4-level paging on x86_64.
|
||||
let mask = 0xFFFF_8000_0000_0000;
|
||||
let masked = address.data() & mask;
|
||||
|
||||
masked == mask
|
||||
|| masked == 0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -83,4 +92,24 @@ mod tests {
|
||||
|
||||
assert_eq!(RiscV64Sv48Arch::PHYS_OFFSET, 0xFFFF_FE00_0000_0000);
|
||||
}
|
||||
#[test]
|
||||
fn is_canonical() {
|
||||
use super::VirtualAddress;
|
||||
|
||||
// Close to identical when compared to x86_64 test.
|
||||
fn yes(address: usize) {
|
||||
assert!(RiscV64Sv48Arch::virt_is_valid(VirtualAddress::new(address)));
|
||||
}
|
||||
fn no(address: usize) {
|
||||
assert!(!RiscV64Sv48Arch::virt_is_valid(VirtualAddress::new(address)));
|
||||
}
|
||||
|
||||
yes(0xFFFF_8000_1337_1337);
|
||||
yes(0xFFFF_FFFF_FFFF_FFFF);
|
||||
yes(0x0000_0000_0000_0042);
|
||||
yes(0x0000_7FFF_FFFF_FFFF);
|
||||
no(0x1337_0000_0000_0000);
|
||||
no(0x1337_8000_0000_0000);
|
||||
no(0x0000_8000_0000_0000);
|
||||
}
|
||||
}
|
||||
|
||||
+36
-1
@@ -47,12 +47,30 @@ impl Arch for X8664Arch {
|
||||
unsafe fn set_table(address: PhysicalAddress) {
|
||||
asm!("mov cr3, {0}", in(reg) address.data());
|
||||
}
|
||||
|
||||
fn virt_is_valid(address: VirtualAddress) -> bool {
|
||||
// On x86_64, an address is valid if and only if it is canonical. It may still point to
|
||||
// unmapped memory, but will always be valid once translated via the page table has
|
||||
// suceeded.
|
||||
address.is_canonical()
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualAddress {
|
||||
#[cfg(any(doc, target_arch = "x86_64"))]
|
||||
#[doc(cfg(target_arch = "x86_64"))]
|
||||
pub fn is_canonical(self) -> bool {
|
||||
let masked = self.data() & 0xFFFF_8000_0000_0000;
|
||||
// TODO: 5-level paging
|
||||
masked == 0xFFFF_8000_0000_0000
|
||||
|| masked == 0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::Arch;
|
||||
use super::X8664Arch;
|
||||
use super::{VirtualAddress, X8664Arch};
|
||||
|
||||
#[test]
|
||||
fn constants() {
|
||||
@@ -72,4 +90,21 @@ mod tests {
|
||||
|
||||
assert_eq!(X8664Arch::PHYS_OFFSET, 0xFFFF_8000_0000_0000);
|
||||
}
|
||||
#[test]
|
||||
fn is_canonical() {
|
||||
fn yes(address: usize) {
|
||||
assert!(VirtualAddress::new(address).is_canonical());
|
||||
}
|
||||
fn no(address: usize) {
|
||||
assert!(!VirtualAddress::new(address).is_canonical());
|
||||
}
|
||||
|
||||
yes(0xFFFF_8000_1337_1337);
|
||||
yes(0xFFFF_FFFF_FFFF_FFFF);
|
||||
yes(0x0000_0000_0000_0042);
|
||||
yes(0x0000_7FFF_FFFF_FFFF);
|
||||
no(0x1337_0000_0000_0000);
|
||||
no(0x1337_8000_0000_0000);
|
||||
no(0x0000_8000_0000_0000);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![feature(asm)]
|
||||
#![feature(asm, doc_cfg)]
|
||||
|
||||
pub use crate::{
|
||||
allocator::*,
|
||||
|
||||
Reference in New Issue
Block a user