Skip to content

Commit 75dbb1e

Browse files
committed
feat(mm): offset device memory when being careful
1 parent ea83f22 commit 75dbb1e

File tree

4 files changed

+45
-7
lines changed

4 files changed

+45
-7
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ vsock = ["pci"]
7373

7474
[lints.rust]
7575
rust_2018_idioms = "warn"
76+
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(careful)'] }
7677
unsafe_op_in_unsafe_fn = "warn"
7778

7879
[lints.clippy]

src/mm/device_alloc.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use core::alloc::{AllocError, Allocator, Layout};
22
use core::ptr::{self, NonNull};
33

44
use align_address::Align;
5-
use memory_addresses::PhysAddr;
5+
use memory_addresses::{PhysAddr, VirtAddr};
66

77
use crate::arch::mm::paging::{BasePageSize, PageSize};
8+
use crate::mm::virtualmem;
89

910
/// An [`Allocator`] for memory that is used to communicate with devices.
1011
///
@@ -18,7 +19,7 @@ unsafe impl Allocator for DeviceAlloc {
1819

1920
let phys_addr = super::physicalmem::allocate(size).unwrap();
2021

21-
let ptr = self.ptr(phys_addr.as_usize());
22+
let ptr = self.ptr(phys_addr);
2223
let slice = ptr::slice_from_raw_parts_mut(ptr, size);
2324
Ok(NonNull::new(slice).unwrap())
2425
}
@@ -35,15 +36,27 @@ unsafe impl Allocator for DeviceAlloc {
3536

3637
impl DeviceAlloc {
3738
/// Returns a pointer corresponding to `phys_addr`.
38-
pub fn ptr<T>(&self, phys_addr: usize) -> *mut T {
39-
ptr::with_exposed_provenance_mut(phys_addr)
39+
pub fn ptr<T>(&self, phys_addr: PhysAddr) -> *mut T {
40+
let addr = phys_addr.as_usize() + self.phys_offset().as_usize();
41+
ptr::with_exposed_provenance_mut(addr)
4042
}
4143

4244
/// Returns the physical address of `ptr`.
4345
///
4446
/// The address is only correct if `ptr` has been allocated by this allocator.
4547
pub fn phys_addr<T: ?Sized>(&self, ptr: *mut T) -> PhysAddr {
46-
let addr = u64::try_from(ptr.expose_provenance()).unwrap();
48+
let addr = u64::try_from(ptr.expose_provenance()).unwrap() - self.phys_offset().as_u64();
4749
PhysAddr::new(addr)
4850
}
51+
52+
/// Returns the physical address offset.
53+
///
54+
/// This device allocator expects the complete physical memory to be mapped device-readable at this offset.
55+
pub fn phys_offset(&self) -> VirtAddr {
56+
if cfg!(careful) {
57+
virtualmem::kernel_heap_end().as_u64().div_ceil(4).into()
58+
} else {
59+
0u64.into()
60+
}
61+
}
4962
}

src/mm/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
pub(crate) mod allocator;
2-
#[cfg(any(feature = "tcp", feature = "udp", feature = "fuse", feature = "vsock"))]
32
pub(crate) mod device_alloc;
43
pub(crate) mod physicalmem;
54
pub(crate) mod virtualmem;

src/mm/physicalmem.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ use free_list::{AllocError, FreeList, PageLayout, PageRange};
55
use hermit_sync::InterruptTicketMutex;
66
use memory_addresses::{PhysAddr, VirtAddr};
77

8-
use crate::arch::mm::paging::{self, BasePageSize, PageSize};
8+
#[cfg(target_arch = "x86_64")]
9+
use crate::arch::mm::paging::PageTableEntryFlagsExt;
10+
use crate::arch::mm::paging::{self, BasePageSize, HugePageSize, PageSize, PageTableEntryFlags};
911
use crate::env;
12+
use crate::mm::device_alloc::DeviceAlloc;
1013

1114
pub static PHYSICAL_FREE_LIST: InterruptTicketMutex<FreeList<16>> =
1215
InterruptTicketMutex::new(FreeList::new());
@@ -43,6 +46,21 @@ pub unsafe fn init_frame_range(frame_range: PageRange) {
4346
.map(|addr| PhysAddr::new(addr.try_into().unwrap()))
4447
.for_each(paging::identity_map::<IdentityPageSize>);
4548

49+
if DeviceAlloc.phys_offset() != VirtAddr::zero() {
50+
let flags = {
51+
let mut flags = PageTableEntryFlags::empty();
52+
flags.normal().writable().execute_disable();
53+
flags
54+
};
55+
(start..end)
56+
.step_by(IdentityPageSize::SIZE.try_into().unwrap())
57+
.for_each(|addr| {
58+
let phys_addr = PhysAddr::new(addr.try_into().unwrap());
59+
let virt_addr = VirtAddr::from_ptr(DeviceAlloc.ptr::<()>(phys_addr));
60+
paging::map::<IdentityPageSize>(virt_addr, phys_addr, 1, flags);
61+
});
62+
}
63+
4664
TOTAL_MEMORY.fetch_add(frame_range.len().get(), Ordering::Relaxed);
4765
}
4866

@@ -118,6 +136,13 @@ fn detect_from_limits() -> Result<(), ()> {
118136
}
119137

120138
pub fn init() {
139+
if env::is_uefi() && DeviceAlloc.phys_offset() != VirtAddr::zero() {
140+
let start = DeviceAlloc.phys_offset();
141+
let count = DeviceAlloc.phys_offset().as_u64() / HugePageSize::SIZE;
142+
let count = usize::try_from(count).unwrap();
143+
paging::unmap::<HugePageSize>(start, count);
144+
}
145+
121146
if let Err(_err) = detect_from_fdt() {
122147
cfg_if::cfg_if! {
123148
if #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] {

0 commit comments

Comments
 (0)