Skip to content

Commit

Permalink
Merge pull request #1442 from hermit-os/memory_addresses
Browse files Browse the repository at this point in the history
Use `memory_address::{VirtAddr, PhysAddr}` in the kernel
  • Loading branch information
mkroening authored Nov 18, 2024
2 parents dd8a11b + f800de8 commit e838ab9
Show file tree
Hide file tree
Showing 45 changed files with 362 additions and 1,004 deletions.
19 changes: 17 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -135,19 +135,30 @@ multiboot = "0.8"
uart_16550 = "0.3"
x86 = { version = "0.52", default-features = false }
x86_64 = "0.15"
memory_addresses = { version = "0.2.2", default-features = false, features = [
"x86_64",
"conv-x86",
"conv-x86_64",
] }

[target.'cfg(target_arch = "aarch64")'.dependencies]
aarch64 = { version = "0.0.10", default-features = false }
aarch64 = { version = "0.0.13", default-features = false }
arm-gic = { version = "0.1" }
hermit-dtb = { version = "0.1" }
semihosting = { version = "0.1", optional = true }
memory_addresses = { version = "0.2.2", default-features = false, features = [
"aarch64",
] }

[target.'cfg(target_arch = "riscv64")'.dependencies]
riscv = "0.12"
sbi-rt = "0.0.3"
semihosting = { version = "0.1", optional = true }
tock-registers = { version = "0.9", optional = true }
trapframe = "0.10"
memory_addresses = { version = "0.2.2", default-features = false, features = [
"riscv64",
] }

[dev-dependencies]
float-cmp = "0.10"
Expand Down
7 changes: 4 additions & 3 deletions src/arch/aarch64/kernel/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ use arm_gic::gicv3::{GicV3, IntId, Trigger};
use hashbrown::HashMap;
use hermit_dtb::Dtb;
use hermit_sync::{InterruptSpinMutex, InterruptTicketMutex, OnceCell, SpinMutex};
use memory_addresses::arch::aarch64::PhysAddr;

use crate::arch::aarch64::kernel::core_local::increment_irq_counter;
use crate::arch::aarch64::kernel::scheduler::State;
use crate::arch::aarch64::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags};
use crate::arch::aarch64::mm::{virtualmem, PhysAddr};
use crate::arch::aarch64::mm::virtualmem;
#[cfg(not(feature = "pci"))]
use crate::drivers::mmio::get_interrupt_handlers;
#[cfg(feature = "pci")]
Expand Down Expand Up @@ -235,11 +236,11 @@ pub(crate) fn init() {

let reg = dtb.get_property("/intc", "reg").unwrap();
let (slice, residual_slice) = reg.split_at(core::mem::size_of::<u64>());
let gicd_start = PhysAddr(u64::from_be_bytes(slice.try_into().unwrap()));
let gicd_start = PhysAddr::new(u64::from_be_bytes(slice.try_into().unwrap()));
let (slice, residual_slice) = residual_slice.split_at(core::mem::size_of::<u64>());
let gicd_size = u64::from_be_bytes(slice.try_into().unwrap());
let (slice, residual_slice) = residual_slice.split_at(core::mem::size_of::<u64>());
let gicc_start = PhysAddr(u64::from_be_bytes(slice.try_into().unwrap()));
let gicc_start = PhysAddr::new(u64::from_be_bytes(slice.try_into().unwrap()));
let (slice, _residual_slice) = residual_slice.split_at(core::mem::size_of::<u64>());
let gicc_size = u64::from_be_bytes(slice.try_into().unwrap());

Expand Down
6 changes: 3 additions & 3 deletions src/arch/aarch64/kernel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ use core::str;
use core::sync::atomic::{AtomicU32, AtomicU64, Ordering};

use hermit_sync::SpinMutex;
use memory_addresses::arch::aarch64::{PhysAddr, VirtAddr};

use crate::arch::aarch64::kernel::core_local::*;
use crate::arch::aarch64::kernel::serial::SerialPort;
use crate::arch::aarch64::mm::{PhysAddr, VirtAddr};
use crate::env;

const SERIAL_PORT_BAUDRATE: u32 = 115200;
Expand All @@ -42,11 +42,11 @@ pub fn is_uhyve_with_pci() -> bool {
}

pub fn get_ram_address() -> PhysAddr {
PhysAddr(env::boot_info().hardware_info.phys_addr_range.start)
PhysAddr::new(env::boot_info().hardware_info.phys_addr_range.start)
}

pub fn get_base_address() -> VirtAddr {
VirtAddr(env::boot_info().load_info.kernel_image_addr_range.start)
VirtAddr::new(env::boot_info().load_info.kernel_image_addr_range.start)
}

pub fn get_image_size() -> usize {
Expand Down
5 changes: 3 additions & 2 deletions src/arch/aarch64/kernel/pci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ use core::str;
use arm_gic::gicv3::{IntId, Trigger};
use bit_field::BitField;
use hermit_dtb::Dtb;
use memory_addresses::arch::aarch64::{PhysAddr, VirtAddr};
use pci_types::{
Bar, CommandRegister, ConfigRegionAccess, InterruptLine, InterruptPin, PciAddress, PciHeader,
MAX_BARS,
};

use crate::arch::aarch64::kernel::interrupts::GIC;
use crate::arch::aarch64::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags};
use crate::arch::aarch64::mm::{virtualmem, PhysAddr, VirtAddr};
use crate::arch::aarch64::mm::virtualmem;
use crate::drivers::pci::{PciDevice, PCI_DEVICES};
use crate::env;

Expand Down Expand Up @@ -240,7 +241,7 @@ pub fn init() {
{
let reg = dtb.get_property(parts.first().unwrap(), "reg").unwrap();
let (slice, residual_slice) = reg.split_at(core::mem::size_of::<u64>());
let addr = PhysAddr(u64::from_be_bytes(slice.try_into().unwrap()));
let addr = PhysAddr::new(u64::from_be_bytes(slice.try_into().unwrap()));
let (slice, _residual_slice) = residual_slice.split_at(core::mem::size_of::<u64>());
let size = u64::from_be_bytes(slice.try_into().unwrap());

Expand Down
13 changes: 6 additions & 7 deletions src/arch/aarch64/kernel/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ use core::sync::atomic::Ordering;
use core::{mem, ptr, slice};

use align_address::Align;
use memory_addresses::arch::aarch64::{PhysAddr, VirtAddr};

use crate::arch::aarch64::kernel::core_local::core_scheduler;
use crate::arch::aarch64::kernel::CURRENT_STACK_ADDRESS;
use crate::arch::aarch64::mm::paging::{BasePageSize, PageSize, PageTableEntryFlags};
use crate::arch::aarch64::mm::{PhysAddr, VirtAddr};
use crate::scheduler::task::{Task, TaskFrame};
#[cfg(target_os = "none")]
use crate::scheduler::PerCoreSchedulerExt;
Expand Down Expand Up @@ -160,8 +160,7 @@ impl TaskStacks {
// clear user stack
unsafe {
ptr::write_bytes(
(virt_addr + DEFAULT_STACK_SIZE + 2 * BasePageSize::SIZE as usize)
.as_mut_ptr::<u8>(),
(virt_addr + DEFAULT_STACK_SIZE + 2 * BasePageSize::SIZE).as_mut_ptr::<u8>(),
0xAC,
user_stack_size,
);
Expand All @@ -175,7 +174,7 @@ impl TaskStacks {
}

pub fn from_boot_stacks() -> TaskStacks {
let stack = VirtAddr::from_u64(CURRENT_STACK_ADDRESS.load(Ordering::Relaxed));
let stack = VirtAddr::new(CURRENT_STACK_ADDRESS.load(Ordering::Relaxed));
debug!("Using boot stack {:p}", stack);

TaskStacks::Boot(BootStack { stack })
Expand All @@ -192,15 +191,15 @@ impl TaskStacks {
match self {
TaskStacks::Boot(_) => VirtAddr::zero(),
TaskStacks::Common(stacks) => {
stacks.virt_addr + DEFAULT_STACK_SIZE + 2 * BasePageSize::SIZE as usize
stacks.virt_addr + DEFAULT_STACK_SIZE + 2 * BasePageSize::SIZE
}
}
}

pub fn get_kernel_stack(&self) -> VirtAddr {
match self {
TaskStacks::Boot(stacks) => stacks.stack,
TaskStacks::Common(stacks) => stacks.virt_addr + BasePageSize::SIZE as usize,
TaskStacks::Common(stacks) => stacks.virt_addr + BasePageSize::SIZE,
}
}

Expand Down Expand Up @@ -358,7 +357,7 @@ impl TaskFrame for Task {
*stack.as_mut_ptr::<u64>() = 0xDEAD_BEEFu64;

// Put the State structure expected by the ASM switch() function on the stack.
stack = stack - mem::size_of::<State>();
stack -= mem::size_of::<State>();

let state = stack.as_mut_ptr::<State>();
ptr::write_bytes(stack.as_mut_ptr::<u8>(), 0, mem::size_of::<State>());
Expand Down
5 changes: 3 additions & 2 deletions src/arch/aarch64/kernel/systemtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ use core::str;

use hermit_dtb::Dtb;
use hermit_sync::OnceCell;
use memory_addresses::arch::aarch64::{PhysAddr, VirtAddr};
use time::OffsetDateTime;

use crate::arch::aarch64::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags};
use crate::arch::aarch64::mm::{virtualmem, PhysAddr, VirtAddr};
use crate::arch::aarch64::mm::virtualmem;
use crate::env;

static PL031_ADDRESS: OnceCell<VirtAddr> = OnceCell::new();
Expand Down Expand Up @@ -59,7 +60,7 @@ pub fn init() {
if str::from_utf8(compatible).unwrap().contains("pl031") {
let reg = dtb.get_property(parts.first().unwrap(), "reg").unwrap();
let (slice, residual_slice) = reg.split_at(core::mem::size_of::<u64>());
let addr = PhysAddr(u64::from_be_bytes(slice.try_into().unwrap()));
let addr = PhysAddr::new(u64::from_be_bytes(slice.try_into().unwrap()));
let (slice, _residual_slice) = residual_slice.split_at(core::mem::size_of::<u64>());
let size = u64::from_be_bytes(slice.try_into().unwrap());

Expand Down
2 changes: 0 additions & 2 deletions src/arch/aarch64/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ pub mod paging;
pub mod physicalmem;
pub mod virtualmem;

pub use aarch64::paging::{PhysAddr, VirtAddr};

pub use self::physicalmem::init_page_tables;

pub fn init() {
Expand Down
32 changes: 15 additions & 17 deletions src/arch/aarch64/mm/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ use core::marker::PhantomData;
use core::{fmt, mem, ptr};

use align_address::Align;
use memory_addresses::{PhysAddr, VirtAddr};

use crate::arch::aarch64::kernel::{get_base_address, get_image_size, get_ram_address, processor};
use crate::arch::aarch64::mm::{physicalmem, virtualmem, PhysAddr, VirtAddr};
use crate::arch::aarch64::mm::{physicalmem, virtualmem};
use crate::env::is_uhyve;
use crate::{mm, scheduler, KERNEL_STACK_SIZE};

/// Pointer to the root page table (called "Level 0" in ARM terminology).
/// Setting the upper bits to zero tells the MMU to use TTBR0 for the base address for the first table.
///
/// See entry.S and ARM Cortex-A Series Programmer's Guide for ARMv8-A, Version 1.0, PDF page 172
const L0TABLE_ADDRESS: VirtAddr = VirtAddr(0x0000_FFFF_FFFF_F000u64);
const L0TABLE_ADDRESS: VirtAddr = VirtAddr::new(0x0000_FFFF_FFFF_F000u64);

/// Number of Offset bits of a virtual address for a 4 KiB page, which are shifted away to get its Page Frame Number (PFN).
const PAGE_BITS: usize = 12;
Expand Down Expand Up @@ -121,16 +122,14 @@ impl PageTableEntryFlags {
#[derive(Clone, Copy, Debug)]
pub struct PageTableEntry {
/// Physical memory address this entry refers, combined with flags from PageTableEntryFlags.
physical_address_and_flags: PhysAddr,
physical_address_and_flags: u64,
}

impl PageTableEntry {
/// Return the stored physical address.
pub fn address(&self) -> PhysAddr {
PhysAddr(
self.physical_address_and_flags.as_u64()
& !(BasePageSize::SIZE - 1u64)
& !(u64::MAX << 48),
PhysAddr::new_truncate(
self.physical_address_and_flags & !(BasePageSize::SIZE - 1u64) & !(u64::MAX << 48),
)
}

Expand All @@ -147,17 +146,16 @@ impl PageTableEntry {
/// * `flags` - Flags from PageTableEntryFlags (note that the PRESENT, INNER_SHAREABLE, and ACCESSED flags are set automatically)
fn set(&mut self, physical_address: PhysAddr, flags: PageTableEntryFlags) {
// Verify that the offset bits for a 4 KiB page are zero.
assert_eq!(
physical_address % BasePageSize::SIZE,
0,
assert!(
physical_address.is_aligned_to(BasePageSize::SIZE),
"Physical address is not on a 4 KiB page boundary (physical_address = {physical_address:p})"
);

let mut flags_to_set = flags;
flags_to_set.insert(PageTableEntryFlags::PRESENT);
flags_to_set.insert(PageTableEntryFlags::INNER_SHAREABLE);
flags_to_set.insert(PageTableEntryFlags::ACCESSED);
self.physical_address_and_flags = PhysAddr(physical_address.as_u64() | flags_to_set.bits());
self.physical_address_and_flags = physical_address | flags_to_set.bits();
}
}

Expand Down Expand Up @@ -245,7 +243,7 @@ impl<S: PageSize> Page<S> {
/// The upper bits must always be 0 or 1 and indicate whether TBBR0 or TBBR1 contains the
/// base address. So always enforce 0 here.
fn is_valid_address(virtual_address: VirtAddr) -> bool {
virtual_address < VirtAddr(0x1_0000_0000_0000)
virtual_address < VirtAddr::new(0x1_0000_0000_0000)
}

/// Returns a Page including the given virtual address.
Expand All @@ -257,7 +255,7 @@ impl<S: PageSize> Page<S> {
);

Self {
virtual_address: VirtAddr(virtual_address.0.align_down(S::SIZE)),
virtual_address: virtual_address.align_down(S::SIZE),
size: PhantomData,
}
}
Expand Down Expand Up @@ -487,7 +485,7 @@ where
// Mark all entries as unused in the newly created table.
let subtable = self.subtable::<S>(page);
for entry in subtable.entries.iter_mut() {
entry.physical_address_and_flags = PhysAddr::zero();
entry.physical_address_and_flags = PhysAddr::zero().as_u64();
}
}

Expand Down Expand Up @@ -547,7 +545,7 @@ where
#[inline]
fn get_page_range<S: PageSize>(virtual_address: VirtAddr, count: usize) -> PageIter<S> {
let first_page = Page::<S>::including_address(virtual_address);
let last_page = Page::<S>::including_address(virtual_address + (count - 1) * S::SIZE as usize);
let last_page = Page::<S>::including_address(virtual_address + (count as u64 - 1) * S::SIZE);
Page::range(first_page, last_page)
}

Expand All @@ -566,7 +564,7 @@ pub fn get_physical_address<S: PageSize>(virtual_address: VirtAddr) -> Option<Ph
let root_pagetable = unsafe { &mut *(L0TABLE_ADDRESS.as_mut_ptr::<PageTable<L0Table>>()) };
let address = root_pagetable.get_page_table_entry(page)?.address();
let offset = virtual_address & (S::SIZE - 1);
Some(PhysAddr(address.as_u64() | offset.as_u64()))
Some(PhysAddr::new(address | offset))
}

/// Translate a virtual memory address to a physical one.
Expand Down Expand Up @@ -608,7 +606,7 @@ pub fn map_heap<S: PageSize>(virt_addr: VirtAddr, count: usize) -> Result<(), us
flags
};

let virt_addrs = (0..count).map(|n| virt_addr + n * S::SIZE as usize);
let virt_addrs = (0..count as u64).map(|n| virt_addr + n * S::SIZE);

for (map_counter, virt_addr) in virt_addrs.enumerate() {
let phys_addr = physicalmem::allocate_aligned(S::SIZE as usize, S::SIZE as usize)
Expand Down
8 changes: 4 additions & 4 deletions src/arch/aarch64/mm/physicalmem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use core::sync::atomic::{AtomicUsize, Ordering};

use free_list::{AllocError, FreeList, PageLayout, PageRange};
use hermit_sync::InterruptTicketMutex;
use memory_addresses::arch::aarch64::PhysAddr;

use crate::arch::aarch64::kernel::get_limit;
use crate::arch::aarch64::mm::paging::{BasePageSize, PageSize};
use crate::arch::aarch64::mm::PhysAddr;
use crate::mm;

static PHYSICAL_FREE_LIST: InterruptTicketMutex<FreeList<16>> =
Expand Down Expand Up @@ -52,7 +52,7 @@ pub fn allocate(size: usize) -> Result<PhysAddr, AllocError> {

let layout = PageLayout::from_size(size).unwrap();

Ok(PhysAddr(
Ok(PhysAddr::new(
PHYSICAL_FREE_LIST
.lock()
.allocate(layout)?
Expand Down Expand Up @@ -80,7 +80,7 @@ pub fn allocate_aligned(size: usize, align: usize) -> Result<PhysAddr, AllocErro

let layout = PageLayout::from_size_align(size, align).unwrap();

Ok(PhysAddr(
Ok(PhysAddr::new(
PHYSICAL_FREE_LIST
.lock()
.allocate(layout)?
Expand All @@ -94,7 +94,7 @@ pub fn allocate_aligned(size: usize, align: usize) -> Result<PhysAddr, AllocErro
/// Otherwise, it may fail due to an empty node pool (POOL.maintain() is called in virtualmem::deallocate)
pub fn deallocate(physical_address: PhysAddr, size: usize) {
assert!(
physical_address >= PhysAddr(mm::kernel_end_address().as_u64()),
physical_address >= PhysAddr::new(mm::kernel_end_address().as_u64()),
"Physical address {physical_address:p} is not >= KERNEL_END_ADDRESS"
);
assert!(size > 0);
Expand Down
Loading

0 comments on commit e838ab9

Please sign in to comment.