Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move PhysAddr and PhysRange to port #34

Merged
merged 1 commit into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions aarch64/src/kalloc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::vm::{Page4K, PAGE_SIZE_4K};
use crate::vm::Page4K;
use core::ptr;
use port::mcslock::{Lock, LockNode};
use port::{
mcslock::{Lock, LockNode},
mem::PAGE_SIZE_4K,
};

static FREE_LIST: Lock<FreeList> = Lock::new("kmem", FreeList { next: None });

Expand Down
155 changes: 10 additions & 145 deletions aarch64/src/kmem.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
use port::fdt::RegBlock;
use port::mem::PhysAddr;

use crate::{param::KZERO, vm::Page4K};
use core::{
fmt,
iter::{Step, StepBy},
mem,
ops::{self, Range},
slice,
};
use core::{mem, slice};

// These map to definitions in kernel.ld
extern "C" {
Expand Down Expand Up @@ -42,119 +36,20 @@ pub fn eearly_pagetables_addr() -> usize {
unsafe { eearly_pagetables.as_ptr().addr() }
}

#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
#[repr(transparent)]
pub struct PhysAddr(u64);

impl PhysAddr {
pub const fn new(value: u64) -> Self {
PhysAddr(value)
}

pub const fn addr(&self) -> u64 {
self.0
}

pub const fn as_virt(&self) -> usize {
(self.0 as usize).wrapping_add(KZERO)
}

pub fn from_virt(a: usize) -> Self {
Self((a - KZERO) as u64)
}

pub fn from_ptr<T>(a: *const T) -> Self {
Self::from_virt(a.addr())
}

pub const fn as_ptr_mut<T>(&self) -> *mut T {
self.as_virt() as *mut T
}

pub const fn round_up(&self, step: u64) -> PhysAddr {
PhysAddr((self.0 + step - 1) & !(step - 1))
}

pub const fn round_down(&self, step: u64) -> PhysAddr {
PhysAddr(self.0 & !(step - 1))
}
pub const fn physaddr_as_virt(pa: PhysAddr) -> usize {
(pa.addr() as usize).wrapping_add(KZERO)
}

impl ops::Add<u64> for PhysAddr {
type Output = PhysAddr;

fn add(self, offset: u64) -> PhysAddr {
PhysAddr(self.0 + offset)
}
pub const fn physaddr_as_ptr_mut<T>(pa: PhysAddr) -> *mut T {
physaddr_as_virt(pa) as *mut T
}

/// Note that this implementation will round down the startpa and round up the endpa
impl Step for PhysAddr {
fn steps_between(&startpa: &Self, &endpa: &Self) -> Option<usize> {
if startpa.0 <= endpa.0 {
match endpa.0.checked_sub(startpa.0) {
Some(result) => usize::try_from(result).ok(),
None => None,
}
} else {
None
}
}

fn forward_checked(startpa: Self, count: usize) -> Option<Self> {
startpa.0.checked_add(count as u64).map(PhysAddr)
}

fn backward_checked(startpa: Self, count: usize) -> Option<Self> {
startpa.0.checked_sub(count as u64).map(PhysAddr)
}
pub const fn from_virt_to_physaddr(va: usize) -> PhysAddr {
PhysAddr::new((va - KZERO) as u64)
}

impl fmt::Debug for PhysAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "PhysAddr({:#016x})", self.0)?;
Ok(())
}
}

pub struct PhysRange(pub Range<PhysAddr>);

impl PhysRange {
pub fn with_len(start: u64, len: usize) -> Self {
Self(PhysAddr(start)..PhysAddr(start + len as u64))
}

#[allow(dead_code)]
pub fn offset_addr(&self, offset: u64) -> Option<PhysAddr> {
let addr = self.0.start + offset;
if self.0.contains(&addr) {
Some(addr)
} else {
None
}
}

pub fn start(&self) -> PhysAddr {
self.0.start
}

pub fn end(&self) -> PhysAddr {
self.0.end
}

pub fn step_by_rounded(&self, step_size: usize) -> StepBy<Range<PhysAddr>> {
let startpa = self.start().round_down(step_size as u64);
let endpa = self.end().round_up(step_size as u64);
(startpa..endpa).step_by(step_size)
}
}

impl From<&RegBlock> for PhysRange {
fn from(r: &RegBlock) -> Self {
let start = PhysAddr(r.addr);
let end = start + r.len.unwrap_or(0);
PhysRange(start..end)
}
pub fn from_ptr_to_physaddr<T>(a: *const T) -> PhysAddr {
from_virt_to_physaddr(a.addr())
}

unsafe fn page_slice_mut<'a>(pstart: *mut Page4K, pend: *mut Page4K) -> &'a mut [Page4K] {
Expand All @@ -174,33 +69,3 @@ pub fn early_pages() -> &'static mut [Page4K] {
let early_end = eearly_pagetables_addr() as *mut Page4K;
unsafe { page_slice_mut(early_start, early_end) }
}

#[cfg(test)]
mod tests {
use super::*;
use crate::vm;

#[test]
fn physaddr_step() {
let range = PhysRange(PhysAddr::new(4096)..PhysAddr::new(4096 * 3));
let pas = range.step_by_rounded(vm::PAGE_SIZE_4K).collect::<Vec<PhysAddr>>();
assert_eq!(pas, [PhysAddr::new(4096), PhysAddr::new(4096 * 2)]);
}

#[test]
fn physaddr_step_rounds_up_and_down() {
// Start should round down to 8192
// End should round up to 16384
let range = PhysRange(PhysAddr::new(9000)..PhysAddr::new(5000 * 3));
let pas = range.step_by_rounded(vm::PAGE_SIZE_4K).collect::<Vec<PhysAddr>>();
assert_eq!(pas, [PhysAddr::new(4096 * 2), PhysAddr::new(4096 * 3)]);
}

#[test]
fn physaddr_step_2m() {
let range =
PhysRange(PhysAddr::new(0x3f000000)..PhysAddr::new(0x3f000000 + 4 * 1024 * 1024));
let pas = range.step_by_rounded(vm::PAGE_SIZE_2M).collect::<Vec<PhysAddr>>();
assert_eq!(pas, [PhysAddr::new(0x3f000000), PhysAddr::new(0x3f000000 + 2 * 1024 * 1024)]);
}
}
6 changes: 3 additions & 3 deletions aarch64/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#![feature(asm_const)]
#![feature(core_intrinsics)]
#![feature(stdsimd)]
#![feature(step_trait)]
#![feature(strict_provenance)]
#![forbid(unsafe_op_in_unsafe_fn)]

Expand All @@ -22,11 +21,12 @@ mod uartmini;
mod uartpl011;
mod vm;

use crate::kmem::{PhysAddr, PhysRange};
use crate::kmem::from_virt_to_physaddr;
use crate::vm::kernel_root;
use core::ffi::c_void;
use core::ptr;
use port::fdt::DeviceTree;
use port::mem::PhysRange;
use port::println;
use vm::PageTable;

Expand Down Expand Up @@ -123,7 +123,7 @@ pub extern "C" fn main9(dtb_va: usize) {
unsafe {
kalloc::free_pages(kmem::early_pages());

let dtb_range = PhysRange::with_len(PhysAddr::from_virt(dtb_va).addr(), dt.size());
let dtb_range = PhysRange::with_len(from_virt_to_physaddr(dtb_va).addr(), dt.size());
vm::init(&dt, &mut *ptr::addr_of_mut!(KPGTBL), dtb_range);
vm::switch(&*ptr::addr_of!(KPGTBL));
}
Expand Down
2 changes: 1 addition & 1 deletion aarch64/src/registers.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#![allow(non_upper_case_globals)]

use crate::{kmem::PhysRange, vm::PAGE_SIZE_2M};
use bitstruct::bitstruct;
use core::fmt;
use num_enum::TryFromPrimitive;
use port::mem::{PhysRange, PAGE_SIZE_2M};

// GPIO registers
pub const GPFSEL1: usize = 0x04; // GPIO function select register 1
Expand Down
3 changes: 2 additions & 1 deletion aarch64/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

extern crate alloc;

use crate::kmem::physaddr_as_virt;
use crate::registers::rpi_mmio;
use crate::uartmini::MiniUart;
use alloc::alloc::{GlobalAlloc, Layout};
Expand All @@ -16,7 +17,7 @@ use port::mem::VirtRange;
// - Add support for raspi4
#[panic_handler]
pub fn panic(info: &PanicInfo) -> ! {
let mmio = rpi_mmio().expect("mmio base detect failed").start().as_virt();
let mmio = physaddr_as_virt(rpi_mmio().expect("mmio base detect failed").start());

let gpio_range = VirtRange::with_len(mmio + 0x200000, 0xb4);
let aux_range = VirtRange::with_len(mmio + 0x215000, 0x8);
Expand Down
34 changes: 18 additions & 16 deletions aarch64/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,24 @@

use crate::{
kalloc,
kmem::{ebss_addr, erodata_addr, etext_addr, text_addr, PhysAddr, PhysRange},
kmem::{
ebss_addr, erodata_addr, etext_addr, from_ptr_to_physaddr, from_virt_to_physaddr,
physaddr_as_ptr_mut, physaddr_as_virt, text_addr,
},
registers::rpi_mmio,
};
use bitstruct::bitstruct;
use core::fmt;
use core::ptr::write_volatile;
use num_enum::{FromPrimitive, IntoPrimitive};
use port::fdt::DeviceTree;
use port::{
fdt::DeviceTree,
mem::{PhysAddr, PhysRange, PAGE_SIZE_1G, PAGE_SIZE_2M, PAGE_SIZE_4K},
};

#[cfg(not(test))]
use port::println;

pub const PAGE_SIZE_4K: usize = 4 << 10;
pub const PAGE_SIZE_2M: usize = 2 << 20;
pub const PAGE_SIZE_1G: usize = 1 << 30;

#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PageSize {
Expand Down Expand Up @@ -162,7 +164,7 @@ impl Entry {
}

fn virt_page_addr(self) -> usize {
self.phys_page_addr().as_virt()
physaddr_as_virt(self.phys_page_addr())
}

fn table(self, level: Level) -> bool {
Expand Down Expand Up @@ -312,7 +314,7 @@ impl Table {
// Create a new page table and write the entry into the parent table
let table = Self::alloc_pagetable()?;
entry = Entry::rw_kernel_data()
.with_phys_addr(PhysAddr::from_ptr(table))
.with_phys_addr(from_ptr_to_physaddr(table))
.with_page_or_table(true);
unsafe {
write_volatile(&mut self.entries[index], entry);
Expand Down Expand Up @@ -358,7 +360,7 @@ impl PageTable {
// TODO Only do this if self != kernel_root()
let old_recursive_entry = kernel_root().entries[511];
let temp_recursive_entry = Entry::rw_kernel_data()
.with_phys_addr(PhysAddr::from_ptr(self))
.with_phys_addr(from_ptr_to_physaddr(self))
.with_page_or_table(true);

unsafe {
Expand Down Expand Up @@ -413,7 +415,7 @@ impl PageTable {
let mut startva = None;
let mut endva = 0;
for pa in range.step_by_rounded(page_size.size()) {
let va = pa.as_virt();
let va = physaddr_as_virt(pa);
self.map_to(entry.with_phys_addr(pa), va, page_size)?;
startva.get_or_insert(va);
endva = va + page_size.size();
Expand Down Expand Up @@ -479,7 +481,7 @@ pub unsafe fn init(_dt: &DeviceTree, kpage_table: &mut PageTable, dtb_range: Phy
// Write the recursive entry
unsafe {
let entry = Entry::rw_kernel_data()
.with_phys_addr(PhysAddr::from_ptr(kpage_table))
.with_phys_addr(from_ptr_to_physaddr(kpage_table))
.with_page_or_table(true);
write_volatile(&mut kpage_table.entries[511], entry);
}
Expand All @@ -490,13 +492,13 @@ pub unsafe fn init(_dt: &DeviceTree, kpage_table: &mut PageTable, dtb_range: Phy
// in depth!
let custom_map = {
let text_range =
PhysRange(PhysAddr::from_virt(text_addr())..PhysAddr::from_virt(etext_addr()));
PhysRange(from_virt_to_physaddr(text_addr())..from_virt_to_physaddr(etext_addr()));
let data_range = PhysRange::with_len(
PhysAddr::from_virt(etext_addr()).addr(),
from_virt_to_physaddr(etext_addr()).addr(),
erodata_addr() - etext_addr(),
);
let bss_range = PhysRange::with_len(
PhysAddr::from_virt(erodata_addr()).addr(),
from_virt_to_physaddr(erodata_addr()).addr(),
ebss_addr() - erodata_addr(),
);

Expand Down Expand Up @@ -549,7 +551,7 @@ fn ttbr1_el1() -> u64 {
pub unsafe fn switch(kpage_table: &PageTable) {
#[cfg(not(test))]
unsafe {
let pt_phys = PhysAddr::from_ptr(kpage_table).addr();
let pt_phys = from_ptr_to_physaddr(kpage_table).addr();
// https://forum.osdev.org/viewtopic.php?t=36412&p=303237
core::arch::asm!(
"msr ttbr1_el1, {pt_phys}",
Expand Down Expand Up @@ -577,7 +579,7 @@ pub unsafe fn invalidate_all_tlb_entries() {

/// Return the root kernel page table
pub fn kernel_root() -> &'static mut PageTable {
unsafe { &mut *PhysAddr::new(ttbr1_el1()).as_ptr_mut::<PageTable>() }
unsafe { &mut *physaddr_as_ptr_mut::<PageTable>(PhysAddr::new(ttbr1_el1())) }
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions port/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![allow(clippy::upper_case_acronyms)]
#![cfg_attr(not(any(test)), no_std)]
#![feature(maybe_uninit_slice)]
#![feature(step_trait)]
#![forbid(unsafe_op_in_unsafe_fn)]

pub mod dat;
Expand Down
Loading
Loading