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

Refactor the kernel's mm module #145

Merged
merged 7 commits into from
Dec 2, 2023
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
1 change: 1 addition & 0 deletions hal_aarch64/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ edition = "2021"
hal_core = { path = "../hal_core" }
tock-registers = "0.8"
cortex-a = "8.1"
log = "0.4"
17 changes: 9 additions & 8 deletions hal_aarch64/src/irq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use hal_core::{Error, TimerCallbackFn};
use crate::devices::gicv2::GicV2;

use crate::mm;
use hal_core::mm::{PageAllocFn, PageMap, Permissions, VAddr};
use hal_core::mm::{PageAlloc, PageMap, Permissions, VAddr};

use tock_registers::interfaces::Writeable;

Expand Down Expand Up @@ -64,19 +64,19 @@ impl IrqChip {

static mut IRQ_CHIP: IrqChip = IrqChip::NoChip;

pub fn init_irq_chip(_dt_node: (), alloc: PageAllocFn) -> Result<(), Error> {
pub fn init_irq_chip(_dt_node: (), allocator: &impl PageAlloc) -> Result<(), Error> {
let (gicd_base, gicc_base) = (0x800_0000, 0x801_0000);
mm::current().identity_map_range(
VAddr::new(gicd_base),
0x0001_0000 / mm::PAGE_SIZE,
Permissions::READ | Permissions::WRITE,
alloc,
allocator,
)?;
mm::current().identity_map_range(
VAddr::new(gicc_base),
0x0001_0000 / mm::PAGE_SIZE,
Permissions::READ | Permissions::WRITE,
alloc,
allocator,
)?;

unsafe {
Expand All @@ -103,11 +103,12 @@ extern "C" fn irq_current_el_sp0() {
// Clear the timer in order to EOI it.
cpu::clear_physical_timer();

let timer_ptr = TIMER_CALLBACK.load(Ordering::Relaxed);
if !timer_ptr.is_null() {
let timer_cb = TIMER_CALLBACK.load(Ordering::Relaxed);
if !timer_cb.is_null() {
unsafe {
let timer: fn() = core::mem::transmute::<_, fn()>(timer_ptr);
timer();
// Cannot simply dereference TIMER_CALLBACK here.
// We are using an AtomicPtr and TIMER_CALLBACK already holds the fn().
core::mem::transmute::<_, fn()>(timer_cb)();
}
}

Expand Down
2 changes: 2 additions & 0 deletions hal_aarch64/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ mod devices;
pub struct PanicInfo {
esr_el1: u64,
elr_el1: u64,
far_el1: u64,
}

pub fn panic_info() -> PanicInfo {
PanicInfo {
esr_el1: ESR_EL1.get(),
elr_el1: ELR_EL1.get(),
far_el1: FAR_EL1.get(),
}
}

Expand Down
41 changes: 26 additions & 15 deletions hal_aarch64/src/mm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use hal_core::{
mm::{self, PageAllocFn, PageMap},
mm::{self, PageAlloc, PageMap},
AddressRange, Error,
};

Expand All @@ -19,32 +19,39 @@ use core::cell::OnceCell;

static mut GPT: OnceCell<&'static mut PageTable> = OnceCell::new();

pub fn is_pagetable_installed() -> bool {
unsafe { GPT.get_mut().is_some() }
}

pub fn current() -> &'static mut PageTable {
unsafe { GPT.get_mut().unwrap() }
}

pub fn init_paging(
pub fn prefill_pagetable(
r: impl Iterator<Item = AddressRange>,
rw: impl Iterator<Item = AddressRange>,
rwx: impl Iterator<Item = AddressRange>,
pre_allocated: impl Iterator<Item = AddressRange>,
alloc: PageAllocFn,
allocator: &impl PageAlloc,
) -> Result<(), Error> {
hal_core::mm::init_paging::<PageTable>(r, rw, rwx, pre_allocated, alloc, |pt| {
// TODO: put into into the hal_core::Error
unsafe {
if GPT.set(pt).is_err() {
panic!("GPT is already set ?");
}
};
unsafe {
load_pagetable(current());
};
})?;
let pt = hal_core::mm::prefill_pagetable::<PageTable>(r, rw, rwx, pre_allocated, allocator)?;

// TODO: put into into the hal_core::Error
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the todo now or later?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oneday 🙏

unsafe {
if GPT.set(pt).is_err() {
panic!("GPT is already set ?");
}
};

Ok(())
}

pub fn enable_paging() {
unsafe {
load_pagetable(current());
};
}

unsafe fn load_pagetable(pt: &'static mut PageTable) {
MAIR_EL1.write(
// Attribute 0 - NonCacheable normal DRAM. FIXME: enable cache?
Expand Down Expand Up @@ -75,5 +82,9 @@ unsafe fn load_pagetable(pt: &'static mut PageTable) {
}

pub fn align_up(addr: usize) -> usize {
mm::align_up(addr, PageTable::PAGE_SIZE)
mm::align_up(addr, PAGE_SIZE)
}

pub fn align_down(addr: usize) -> usize {
mm::align_down(addr, PAGE_SIZE)
}
20 changes: 12 additions & 8 deletions hal_aarch64/src/mm/pgt48.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use hal_core::{
mm::{self, PageAllocFn, PageEntry, PageMap, Permissions},
mm::{self, PageAlloc, PageEntry, PageMap, Permissions},
Error,
};

Expand Down Expand Up @@ -224,9 +224,9 @@ impl PageMap for PageTable {
const PAGE_SIZE: usize = 4096;
type Entry = TableEntry;

fn new(alloc: PageAllocFn) -> Result<&'static mut Self, Error> {
let page = alloc(1);
let page_table = page.ptr_cast::<PageTable>();
fn new(allocator: &impl PageAlloc) -> Result<&'static mut Self, Error> {
let page = allocator.alloc(1)?;
let page_table = page as *mut PageTable;
// Safety: the PMM gave us the memory, it should be a valid pointer.
let page_table: &mut PageTable = unsafe { page_table.as_mut().unwrap() };

Expand All @@ -243,7 +243,7 @@ impl PageMap for PageTable {
va: mm::VAddr,
pa: mm::PAddr,
perms: Permissions,
alloc: PageAllocFn,
allocator: &impl PageAlloc,
) -> Result<&mut TableEntry, Error> {
let va = VAddr::from(va);
let pa = PAddr::from(pa);
Expand All @@ -266,7 +266,7 @@ impl PageMap for PageTable {

let descriptor = unsafe { &mut content.descriptor };
if descriptor.is_invalid() {
let new_page_table = PageTable::new(alloc)?;
let new_page_table = PageTable::new(allocator)?;
descriptor.set_next_level(new_page_table);
}

Expand All @@ -276,14 +276,18 @@ impl PageMap for PageTable {
unreachable!("We should have reached lvl 3 and returned by now...");
}

fn add_invalid_entry(&mut self, va: mm::VAddr, alloc: PageAllocFn) -> Result<(), Error> {
fn add_invalid_entry(
&mut self,
va: mm::VAddr,
allocator: &impl PageAlloc,
) -> Result<(), Error> {
let entry = self.map(
va,
mm::PAddr {
val: 0x0A0A_0A0A_0A0A_0A0A,
},
mm::Permissions::READ,
alloc,
allocator,
)?;

entry.set_invalid();
Expand Down
13 changes: 11 additions & 2 deletions hal_core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
#![no_std]
#![feature(return_position_impl_trait_in_trait)]

use core::convert::Into;
use core::ops::Range;

pub mod mm;

#[derive(Debug)]
pub enum Error {}
pub enum Error {
Alloc(mm::AllocatorError),
}

impl From<mm::AllocatorError> for Error {
fn from(e: mm::AllocatorError) -> Self {
Self::Alloc(e)
}
}

pub type TimerCallbackFn = fn();

Expand Down Expand Up @@ -43,7 +52,7 @@ impl AddressRange {
pub fn iter_pages(self, page_size: usize) -> impl Iterator<Item = usize> {
assert_eq!(self.end, mm::align_up(self.end, page_size));

(self.start..=self.end).step_by(page_size)
(self.start..self.end).step_by(page_size)
}

pub fn count_pages(&self, page_size: usize) -> usize {
Expand Down
Loading
Loading