aarch64/mmu: add io remap

master
equation314 6 years ago
parent a8b334123a
commit 264600f145

@ -98,6 +98,7 @@ pub struct MemoryAttr {
user: bool,
readonly: bool,
execute: bool,
mmio: bool,
hide: bool,
}
@ -114,6 +115,10 @@ impl MemoryAttr {
self.execute = true;
self
}
pub fn mmio(mut self) -> Self {
self.mmio = true;
self
}
pub fn hide(mut self) -> Self {
self.hide = true;
self
@ -122,8 +127,9 @@ impl MemoryAttr {
if self.user { entry.set_user(true); }
if self.readonly { entry.set_writable(false); }
if self.execute { entry.set_execute(true); }
if self.mmio { entry.set_mmio(false); }
if self.hide { entry.set_present(false); }
if self.user || self.readonly || self.execute || self.hide { entry.update(); }
if self.user || self.readonly || self.execute || self.mmio || self.hide { entry.update(); }
}
}

@ -57,4 +57,6 @@ pub trait Entry {
fn set_user(&mut self, value: bool);
fn execute(&self) -> bool;
fn set_execute(&mut self, value: bool);
fn mmio(&self) -> bool;
fn set_mmio(&mut self, value: bool);
}

@ -6,7 +6,8 @@ pub mod irq;
pub mod timer;
pub mod serial;
pub const IO_BASE: usize = bcm2837::IO_BASE;
pub const IO_REMAP_BASE: usize = bcm2837::IO_BASE;
pub const IO_REMAP_END: usize = 0x40001000;
pub fn init() {
assert_has_not_been_called!("board::init must be called only once");

@ -25,7 +25,7 @@ pub fn init_mmu_early() {
let frame_lvl4 = Frame::containing_address(PhysAddr::new(&PAGE_TABLE_LVL4 as *const _ as u64));
let frame_lvl3 = Frame::containing_address(PhysAddr::new(&PAGE_TABLE_LVL3 as *const _ as u64));
let frame_lvl2 = Frame::containing_address(PhysAddr::new(&PAGE_TABLE_LVL2 as *const _ as u64));
super::paging::setup_page_table(frame_lvl4, frame_lvl3, frame_lvl2);
super::paging::setup_temp_page_table(frame_lvl4, frame_lvl3, frame_lvl2);
// device.
MAIR_EL1.write(
@ -111,9 +111,8 @@ fn remap_the_kernel() {
ms.push(MemoryArea::new_identity(srodata as usize, erodata as usize, MemoryAttr::default().readonly(), "rodata"));
ms.push(MemoryArea::new_identity(sbss as usize, ebss as usize, MemoryAttr::default(), "bss"));
// ensure the level 2 page table exists
ms.push(MemoryArea::new_identity(0x40000000, 0x40200000, MemoryAttr::default(), "arm_control"));
super::paging::remap_device_2mib(&mut ms, 0x3F000000, 0x40200000);
use arch::board::{IO_REMAP_BASE, IO_REMAP_END};
ms.push(MemoryArea::new_identity(IO_REMAP_BASE, IO_REMAP_END, MemoryAttr::default().mmio(), "io_remap"));
unsafe { ms.activate(); }
use core::mem::forget;

@ -12,7 +12,7 @@ use aarch64::paging::{FrameAllocator, FrameDeallocator, Page, PhysFrame as Frame
use aarch64::paging::memory_attribute::*;
// need 3 page
pub fn setup_page_table(frame_lvl4: Frame, frame_lvl3: Frame, frame_lvl2: Frame) {
pub fn setup_temp_page_table(frame_lvl4: Frame, frame_lvl3: Frame, frame_lvl2: Frame) {
let p4 = unsafe { &mut *(frame_lvl4.start_address().as_u64() as *mut Aarch64PageTable) };
let p3 = unsafe { &mut *(frame_lvl3.start_address().as_u64() as *mut Aarch64PageTable) };
let p2 = unsafe { &mut *(frame_lvl2.start_address().as_u64() as *mut Aarch64PageTable) };
@ -25,8 +25,8 @@ pub fn setup_page_table(frame_lvl4: Frame, frame_lvl3: Frame, frame_lvl2: Frame)
for page in Page::<Size2MiB>::range_of(start_addr, end_addr) {
let paddr = PhysAddr::new(page.start_address().as_u64());
use arch::board::IO_BASE;
if paddr.as_u64() >= IO_BASE as u64 {
use arch::board::IO_REMAP_BASE;
if paddr.as_u64() >= IO_REMAP_BASE as u64 {
p2[page.p2_index()].set_block::<Size2MiB>(paddr, block_flags | EF::PXN, MairDevice::attr_value());
} else {
p2[page.p2_index()].set_block::<Size2MiB>(paddr, block_flags, MairNormal::attr_value());
@ -39,54 +39,10 @@ pub fn setup_page_table(frame_lvl4: Frame, frame_lvl3: Frame, frame_lvl2: Frame)
p4[0].set_frame(frame_lvl3, EF::default(), MairNormal::attr_value());
p4[RECURSIVE_INDEX].set_frame(frame_lvl4, EF::default(), MairNormal::attr_value());
// warn!("p2");
// for i in 0..512 {
// if p2[i].flags().bits() != 0 {
// info!("{:x?} {:x?} {:x?}",i, &p2[i] as *const _ as usize, p2[i]);
// }
// }
// warn!("p3");
// for i in 0..512 {
// if p3[i].flags().bits() != 0 {
// info!("{:x?} {:x?} {:x?}",i, &p3[i] as *const _ as usize, p3[i]);
// }
// }
// warn!("p4");
// for i in 0..512 {
// if p4[i].flags().bits() != 0 {
// info!("{:x?} {:x?} {:x?}",i, &p4[i] as *const _ as usize, p4[i]);
// }
// }
ttbr_el1_write(0, frame_lvl4);
tlb_invalidate_all();
}
/// map the range [start, end) as device memory, insert to the MemorySet
pub fn remap_device_2mib(ms: &mut MemorySet<InactivePageTable0>, start_addr: usize, end_addr: usize) {
ms.edit(|active_table| {
for page in Page::<Size2MiB>::range_of(start_addr, end_addr) {
let paddr = PhysAddr::new(page.start_address().as_u64());
let p2 = unsafe { &mut *active_table.0.p2_ptr(page) };
p2[page.p2_index()].set_block::<Size2MiB>(paddr, EF::default() - EF::TABLE_OR_PAGE, MairDevice::attr_value());
}
// let p2 = unsafe { &mut *(0o777_777_000_000_0000 as *mut Aarch64PageTable) };
// for i in 0..512 {
// if p2[i].flags().bits() != 0 {
// info!("{:x?} {:x?} {:x?}",i, &p2[i] as *const _ as usize, p2[i]);
// }
// }
// let p2 = unsafe { &mut *(0o777_777_000_001_0000 as *mut Aarch64PageTable) };
// for i in 0..512 {
// if p2[i].flags().bits() != 0 {
// info!("{:x?} {:x?} {:x?}",i, &p2[i] as *const _ as usize, p2[i]);
// }
// }
});
}
pub struct ActivePageTable(RecursivePageTable<'static>);
pub struct PageEntry(PageTableEntry);
@ -201,6 +157,8 @@ impl Entry for PageEntry {
false => self.as_flags().set(EF::PXN, !value),
}
}
fn mmio(&self) -> bool { self.0.attr().value == MairDevice::attr_value().value }
fn set_mmio(&mut self, value: bool) { self.0.modify_attr(MairDevice::attr_value()); }
}
impl PageEntry {

@ -126,6 +126,8 @@ impl Entry for PageEntry {
fn set_user(&mut self, value: bool) { self.as_flags().set(EF::USER, value); }
fn execute(&self) -> bool { self.0.flags().contains(EF::EXECUTABLE) }
fn set_execute(&mut self, value: bool) { self.as_flags().set(EF::EXECUTABLE, value); }
fn mmio(&self) -> bool { unimplemented!() }
fn set_mmio(&mut self, value: bool) { unimplemented!() }
}
impl PageEntry {

@ -138,6 +138,8 @@ impl Entry for PageEntry {
}
fn execute(&self) -> bool { !self.0.flags().contains(EF::NO_EXECUTE) }
fn set_execute(&mut self, value: bool) { self.as_flags().set(EF::NO_EXECUTE, !value); }
fn mmio(&self) -> bool { unimplemented!() }
fn set_mmio(&mut self, value: bool) { unimplemented!() }
}
impl PageEntry {
@ -261,4 +263,4 @@ impl FrameDeallocator<Size4KiB> for FrameAllocatorForX86 {
fn dealloc(&mut self, frame: Frame) {
dealloc_frame(frame.start_address().as_u64() as usize);
}
}
}

Loading…
Cancel
Save