aarch64/mmu: mmu enabled

master
equation314 6 years ago
parent 576ae1d911
commit 9e8124abbb

@ -1,68 +0,0 @@
[[package]]
name = "aarch64"
version = "0.1.0"
dependencies = [
"bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cortex-a 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ux 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bit_field"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cortex-a"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "os_bootinfo"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "register"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"tock-registers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tock-registers"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "usize_conversions"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ux"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum cortex-a 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b187d0d728b4a99ba1d79f9671b976bcdd71a8a2c719585218fd2dc14a4d08c"
"checksum os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66481dbeb5e773e7bd85b63cd6042c30786f834338288c5ec4f3742673db360a"
"checksum register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e10f31b6d2299e5620986ad9fcdd66463e125ad72af4f403f9aedf7592d5ccdb"
"checksum tock-registers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a385d94f3f62e60445a0adb9ff8d9621faa272234530d4c0f848ec98f88e316"
"checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5"
"checksum ux 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53d8df5dd8d07fedccd202de1887d94481fadaea3db70479f459e8163a1fab41"

@ -5,11 +5,12 @@ use regs::*;
#[inline(always)] #[inline(always)]
pub fn tlb_invalidate() { pub fn tlb_invalidate() {
unsafe { unsafe {
asm!("dsb ishst asm!(
"dsb ishst
tlbi vmalle1is tlbi vmalle1is
dsb ish dsb ish
tlbi vmalle1is isb"
isb"); );
} }
} }
@ -63,6 +64,15 @@ pub unsafe fn get_ttbr1() -> usize {
ttbr0 ttbr0
} }
#[inline(always)]
pub fn address_translate(vaddr: usize) -> usize {
let paddr: usize;
unsafe {
asm!("at S1E1R, $1; mrs $0, par_el1" : "=r"(paddr) : "r"(vaddr));
}
paddr
}
/// Returns the SPSel value. /// Returns the SPSel value.
#[inline(always)] #[inline(always)]
pub fn sp_sel() -> u8 { pub fn sp_sel() -> u8 {
@ -94,7 +104,6 @@ pub fn wfi() {
} }
} }
/// The classic no-op /// The classic no-op
#[inline] #[inline]
pub fn nop() { pub fn nop() {
@ -150,7 +159,7 @@ bitflags! {
pub fn ttbr0_el1_read() -> (PhysFrame, ttbr0_el1_Flags) { pub fn ttbr0_el1_read() -> (PhysFrame, ttbr0_el1_Flags) {
let value = TTBR0_EL1.get(); let value = TTBR0_EL1.get();
let flags = ttbr0_el1_Flags::from_bits_truncate(value); let flags = ttbr0_el1_Flags::from_bits_truncate(value);
let addr = PhysAddr::new(value & 0x_000f_ffff_ffff_f000); let addr = PhysAddr::new(value & 0x_0000_ffff_ffff_f000);
let frame = PhysFrame::containing_address(addr); let frame = PhysFrame::containing_address(addr);
(frame, flags) (frame, flags)
} }

@ -34,16 +34,6 @@ pub trait NotGiantPageSize: PageSize {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Size4KiB {} pub enum Size4KiB {}
/// A “huge” 2MiB page.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Size2MiB {}
/// A “giant” 1GiB page.
///
/// (Only available on newer x86_64 CPUs.)
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Size1GiB {}
impl PageSize for Size4KiB { impl PageSize for Size4KiB {
const SIZE: u64 = 4096; const SIZE: u64 = 4096;
const SIZE_AS_DEBUG_STR: &'static str = "4KiB"; const SIZE_AS_DEBUG_STR: &'static str = "4KiB";
@ -51,18 +41,6 @@ impl PageSize for Size4KiB {
impl NotGiantPageSize for Size4KiB {} impl NotGiantPageSize for Size4KiB {}
impl PageSize for Size2MiB {
const SIZE: u64 = Size4KiB::SIZE * 512;
const SIZE_AS_DEBUG_STR: &'static str = "2MiB";
}
impl NotGiantPageSize for Size2MiB {}
impl PageSize for Size1GiB {
const SIZE: u64 = Size2MiB::SIZE * 512;
const SIZE_AS_DEBUG_STR: &'static str = "1GiB";
}
/// A virtual memory page. /// A virtual memory page.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C)] #[repr(C)]
@ -128,31 +106,6 @@ impl<S: NotGiantPageSize> Page<S> {
} }
} }
impl Page<Size1GiB> {
/// Returns the 1GiB memory page with the specified page table indices.
pub fn from_page_table_indices_1gib(p4_index: u9, p3_index: u9) -> Self {
use bit_field::BitField;
let mut addr = 0;
addr.set_bits(39..48, u64::from(p4_index));
addr.set_bits(30..39, u64::from(p3_index));
Page::containing_address(VirtAddr::new(addr))
}
}
impl Page<Size2MiB> {
/// Returns the 2MiB memory page with the specified page table indices.
pub fn from_page_table_indices_2mib(p4_index: u9, p3_index: u9, p2_index: u9) -> Self {
use bit_field::BitField;
let mut addr = 0;
addr.set_bits(39..48, u64::from(p4_index));
addr.set_bits(30..39, u64::from(p3_index));
addr.set_bits(21..30, u64::from(p2_index));
Page::containing_address(VirtAddr::new(addr))
}
}
impl Page<Size4KiB> { impl Page<Size4KiB> {
/// Returns the 4KiB memory page with the specified page table indices. /// Returns the 4KiB memory page with the specified page table indices.
pub fn from_page_table_indices(p4_index: u9, p3_index: u9, p2_index: u9, p1_index: u9) -> Self { pub fn from_page_table_indices(p4_index: u9, p3_index: u9, p2_index: u9, p1_index: u9) -> Self {
@ -246,16 +199,6 @@ impl<S: PageSize> Iterator for PageRange<S> {
} }
} }
impl PageRange<Size2MiB> {
/// Converts the range of 2MiB pages to a range of 4KiB pages.
pub fn as_4kib_page_range(self) -> PageRange<Size4KiB> {
PageRange {
start: Page::containing_address(self.start.start_address()),
end: Page::containing_address(self.end.start_address()),
}
}
}
impl<S: PageSize> fmt::Debug for PageRange<S> { impl<S: PageSize> fmt::Debug for PageRange<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("PageRange") f.debug_struct("PageRange")

@ -21,7 +21,7 @@ pub enum FrameError {
#[derive(Clone)] #[derive(Clone)]
#[repr(transparent)] #[repr(transparent)]
pub struct PageTableEntry { pub struct PageTableEntry {
entry: u64, pub entry: u64,
} }
impl PageTableEntry { impl PageTableEntry {
@ -42,7 +42,7 @@ impl PageTableEntry {
/// Returns the physical address mapped by this entry, might be zero. /// Returns the physical address mapped by this entry, might be zero.
pub fn addr(&self) -> PhysAddr { pub fn addr(&self) -> PhysAddr {
PhysAddr::new(self.entry & 0x000fffff_fffff000) PhysAddr::new(self.entry & 0x0000_ffff_ffff_f000)
} }
/// Returns the physical frame mapped by this entry. /// Returns the physical frame mapped by this entry.
@ -83,6 +83,7 @@ impl PageTableEntry {
impl fmt::Debug for PageTableEntry { impl fmt::Debug for PageTableEntry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut f = f.debug_struct("PageTableEntry"); let mut f = f.debug_struct("PageTableEntry");
f.field("value", &self.entry);
f.field("addr", &self.addr()); f.field("addr", &self.addr());
f.field("flags", &self.flags()); f.field("flags", &self.flags());
f.finish() f.finish()
@ -94,9 +95,11 @@ bitflags! {
pub struct PageTableFlags: u64 { pub struct PageTableFlags: u64 {
const ALL = 0xffffffff_ffffffff; const ALL = 0xffffffff_ffffffff;
const TYPE_MASK = 3 << 0; const TYPE_MASK = 3 << 0;
const TYPE_FAULT = 0 << 0; // const TYPE_FAULT = 0 << 0;
const TYPE_PAGE = 3 << 0; const TYPE_PAGE = 3 << 0;
const TABLE_BIT = 1 << 1; const TABLE_BIT = 1 << 1;
// const BLOCK_BIT = 0 << 1;
const PAGE_BIT = 1 << 1;
const PRESENT = 1 << 0; const PRESENT = 1 << 0;
const USER_ACCESSIBLE = 1 << 6; /* AP[1] */ const USER_ACCESSIBLE = 1 << 6; /* AP[1] */

@ -4,7 +4,7 @@ use asm::tlb_invalidate;
use paging::{ use paging::{
frame_alloc::FrameAllocator, frame_alloc::FrameAllocator,
page_table::{FrameError, PageTable, PageTableEntry, PageTableFlags}, page_table::{FrameError, PageTable, PageTableEntry, PageTableFlags},
NotGiantPageSize, Page, PageSize, PhysFrame, Size1GiB, Size2MiB, Size4KiB, NotGiantPageSize, Page, PageSize, PhysFrame, Size4KiB,
}; };
use paging::page_table::PageTableFlags as Flags; use paging::page_table::PageTableFlags as Flags;
use asm::ttbr0_el1_read; use asm::ttbr0_el1_read;
@ -217,7 +217,7 @@ impl<'a> RecursivePageTable<'a> {
if entry.is_unused() { if entry.is_unused() {
if let Some(frame) = allocator.alloc() { if let Some(frame) = allocator.alloc() {
entry.set_frame(frame, Flags::PRESENT | Flags::WRITE); entry.set_frame(frame, Flags::PRESENT | Flags::WRITE | Flags::ACCESSED | Flags::PAGE_BIT);
created = true; created = true;
} else { } else {
return Err(MapToError::FrameAllocationFailed); return Err(MapToError::FrameAllocationFailed);
@ -241,214 +241,6 @@ impl<'a> RecursivePageTable<'a> {
} }
} }
impl<'a> Mapper<Size1GiB> for RecursivePageTable<'a> {
fn map_to<A>(
&mut self,
page: Page<Size1GiB>,
frame: PhysFrame<Size1GiB>,
flags: PageTableFlags,
allocator: &mut A,
) -> Result<MapperFlush<Size1GiB>, MapToError>
where
A: FrameAllocator<Size4KiB>,
{
let p4 = &mut self.p4;
let p3_page = p3_page(page, self.recursive_index);
let p3 = unsafe { Self::create_next_table(&mut p4[page.p4_index()], p3_page, allocator)? };
if !p3[page.p3_index()].is_unused() {
return Err(MapToError::PageAlreadyMapped);
}
p3[page.p3_index()].set_addr(frame.start_address(), flags | Flags::HUGE_PAGE);
Ok(MapperFlush::new(page))
}
fn unmap(
&mut self,
page: Page<Size1GiB>,
) -> Result<(PhysFrame<Size1GiB>, MapperFlush<Size1GiB>), UnmapError> {
let p4 = &mut self.p4;
let p4_entry = &p4[page.p4_index()];
p4_entry.frame().map_err(|err| match err {
FrameError::FrameNotPresent => UnmapError::PageNotMapped,
FrameError::HugeFrame => UnmapError::ParentEntryHugePage,
})?;
let p3 = unsafe { &mut *(p3_ptr(page, self.recursive_index)) };
let p3_entry = &mut p3[page.p3_index()];
let flags = p3_entry.flags();
if !flags.contains(PageTableFlags::PRESENT) {
return Err(UnmapError::PageNotMapped);
}
if !flags.contains(PageTableFlags::HUGE_PAGE) {
return Err(UnmapError::ParentEntryHugePage);
}
let frame = PhysFrame::from_start_address(p3_entry.addr())
.map_err(|()| UnmapError::InvalidFrameAddress(p3_entry.addr()))?;
p3_entry.set_unused();
Ok((frame, MapperFlush::new(page)))
}
fn update_flags(
&mut self,
page: Page<Size1GiB>,
flags: PageTableFlags,
) -> Result<MapperFlush<Size1GiB>, FlagUpdateError> {
let p4 = &mut self.p4;
if p4[page.p4_index()].is_unused() {
return Err(FlagUpdateError::PageNotMapped);
}
let p3 = unsafe { &mut *(p3_ptr(page, self.recursive_index)) };
if p3[page.p3_index()].is_unused() {
return Err(FlagUpdateError::PageNotMapped);
}
p3[page.p3_index()].set_flags(flags | Flags::HUGE_PAGE);
Ok(MapperFlush::new(page))
}
fn translate_page(&self, page: Page<Size1GiB>) -> Option<PhysFrame<Size1GiB>> {
let p4 = &self.p4;
if p4[page.p4_index()].is_unused() {
return None;
}
let p3 = unsafe { &*(p3_ptr(page, self.recursive_index)) };
let p3_entry = &p3[page.p3_index()];
if p3_entry.is_unused() {
return None;
}
PhysFrame::from_start_address(p3_entry.addr()).ok()
}
}
impl<'a> Mapper<Size2MiB> for RecursivePageTable<'a> {
fn map_to<A>(
&mut self,
page: Page<Size2MiB>,
frame: PhysFrame<Size2MiB>,
flags: PageTableFlags,
allocator: &mut A,
) -> Result<MapperFlush<Size2MiB>, MapToError>
where
A: FrameAllocator<Size4KiB>,
{
let p4 = &mut self.p4;
let p3_page = p3_page(page, self.recursive_index);
let p3 = unsafe { Self::create_next_table(&mut p4[page.p4_index()], p3_page, allocator)? };
let p2_page = p2_page(page, self.recursive_index);
let p2 = unsafe { Self::create_next_table(&mut p3[page.p3_index()], p2_page, allocator)? };
if !p2[page.p2_index()].is_unused() {
return Err(MapToError::PageAlreadyMapped);
}
p2[page.p2_index()].set_addr(frame.start_address(), flags | Flags::HUGE_PAGE);
Ok(MapperFlush::new(page))
}
fn unmap(
&mut self,
page: Page<Size2MiB>,
) -> Result<(PhysFrame<Size2MiB>, MapperFlush<Size2MiB>), UnmapError> {
let p4 = &mut self.p4;
let p4_entry = &p4[page.p4_index()];
p4_entry.frame().map_err(|err| match err {
FrameError::FrameNotPresent => UnmapError::PageNotMapped,
FrameError::HugeFrame => UnmapError::ParentEntryHugePage,
})?;
let p3 = unsafe { &mut *(p3_ptr(page, self.recursive_index)) };
let p3_entry = &p3[page.p3_index()];
p3_entry.frame().map_err(|err| match err {
FrameError::FrameNotPresent => UnmapError::PageNotMapped,
FrameError::HugeFrame => UnmapError::ParentEntryHugePage,
})?;
let p2 = unsafe { &mut *(p2_ptr(page, self.recursive_index)) };
let p2_entry = &mut p2[page.p2_index()];
let flags = p2_entry.flags();
if !flags.contains(PageTableFlags::PRESENT) {
return Err(UnmapError::PageNotMapped);
}
if !flags.contains(PageTableFlags::HUGE_PAGE) {
return Err(UnmapError::ParentEntryHugePage);
}
let frame = PhysFrame::from_start_address(p2_entry.addr())
.map_err(|()| UnmapError::InvalidFrameAddress(p2_entry.addr()))?;
p2_entry.set_unused();
Ok((frame, MapperFlush::new(page)))
}
fn update_flags(
&mut self,
page: Page<Size2MiB>,
flags: PageTableFlags,
) -> Result<MapperFlush<Size2MiB>, FlagUpdateError> {
let p4 = &mut self.p4;
if p4[page.p4_index()].is_unused() {
return Err(FlagUpdateError::PageNotMapped);
}
let p3 = unsafe { &mut *(p3_ptr(page, self.recursive_index)) };
if p3[page.p3_index()].is_unused() {
return Err(FlagUpdateError::PageNotMapped);
}
let p2 = unsafe { &mut *(p2_ptr(page, self.recursive_index)) };
if p2[page.p2_index()].is_unused() {
return Err(FlagUpdateError::PageNotMapped);
}
p2[page.p2_index()].set_flags(flags | Flags::HUGE_PAGE);
Ok(MapperFlush::new(page))
}
fn translate_page(&self, page: Page<Size2MiB>) -> Option<PhysFrame<Size2MiB>> {
let p4 = &self.p4;
if p4[page.p4_index()].is_unused() {
return None;
}
let p3 = unsafe { &*(p3_ptr(page, self.recursive_index)) };
let p3_entry = &p3[page.p3_index()];
if p3_entry.is_unused() {
return None;
}
let p2 = unsafe { &*(p2_ptr(page, self.recursive_index)) };
let p2_entry = &p2[page.p2_index()];
if p2_entry.is_unused() {
return None;
}
PhysFrame::from_start_address(p2_entry.addr()).ok()
}
}
impl<'a> Mapper<Size4KiB> for RecursivePageTable<'a> { impl<'a> Mapper<Size4KiB> for RecursivePageTable<'a> {
fn map_to<A>( fn map_to<A>(

17
kernel/Cargo.lock generated

@ -5,6 +5,7 @@ dependencies = [
"bare-metal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "bare-metal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -176,6 +177,14 @@ name = "redox_syscall"
version = "0.1.40" version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "register"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "register" name = "register"
version = "0.2.1" version = "0.2.1"
@ -238,6 +247,11 @@ dependencies = [
"remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "tock-registers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "tock-registers" name = "tock-registers"
version = "0.2.0" version = "0.2.0"
@ -271,6 +285,7 @@ dependencies = [
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"riscv 0.3.0", "riscv 0.3.0",
"simple-filesystem 0.0.1 (git+https://github.com/wangrunji0408/SimpleFileSystem-Rust)", "simple-filesystem 0.0.1 (git+https://github.com/wangrunji0408/SimpleFileSystem-Rust)",
"spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -384,6 +399,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07"
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
"checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479"
"checksum register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e10f31b6d2299e5620986ad9fcdd66463e125ad72af4f403f9aedf7592d5ccdb" "checksum register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e10f31b6d2299e5620986ad9fcdd66463e125ad72af4f403f9aedf7592d5ccdb"
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
"checksum simple-filesystem 0.0.1 (git+https://github.com/wangrunji0408/SimpleFileSystem-Rust)" = "<none>" "checksum simple-filesystem 0.0.1 (git+https://github.com/wangrunji0408/SimpleFileSystem-Rust)" = "<none>"
@ -391,6 +407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "37b5646825922b96b5d7d676b5bb3458a54498e96ed7b0ce09dc43a07038fea4" "checksum spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "37b5646825922b96b5d7d676b5bb3458a54498e96ed7b0ce09dc43a07038fea4"
"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5"
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
"checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9"
"checksum tock-registers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a385d94f3f62e60445a0adb9ff8d9621faa272234530d4c0f848ec98f88e316" "checksum tock-registers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a385d94f3f62e60445a0adb9ff8d9621faa272234530d4c0f848ec98f88e316"
"checksum uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "269f953d8de3226f7c065c589c7b4a3e83d10a419c7c3b5e2e0f197e6acc966e" "checksum uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "269f953d8de3226f7c065c589c7b4a3e83d10a419c7c3b5e2e0f197e6acc966e"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"

@ -32,6 +32,7 @@ bit-allocator = { path = "../crate/bit-allocator" }
ucore-memory = { path = "../crate/memory" } ucore-memory = { path = "../crate/memory" }
ucore-process = { path = "../crate/process" } ucore-process = { path = "../crate/process" }
simple-filesystem = { git = "https://github.com/wangrunji0408/SimpleFileSystem-Rust" } simple-filesystem = { git = "https://github.com/wangrunji0408/SimpleFileSystem-Rust" }
register="0.1.0"
[target.'cfg(target_arch = "x86_64")'.dependencies] [target.'cfg(target_arch = "x86_64")'.dependencies]
bootloader = "0.3" bootloader = "0.3"

@ -17,6 +17,8 @@ halt:
setup: setup:
# store the desired EL1 stack pointer in x1 # store the desired EL1 stack pointer in x1
adr x1, _start adr x1, _start
# FIXME
lsl x1, x1, #2
# use SP_ELx for Exception level ELx # use SP_ELx for Exception level ELx
msr SPsel, #1 msr SPsel, #1

@ -38,10 +38,11 @@ pub struct Info {
/// the trap frame for the exception. /// the trap frame for the exception.
#[no_mangle] #[no_mangle]
pub extern "C" fn rust_trap(info: Info, esr: u32, tf: &mut TrapFrame) { pub extern "C" fn rust_trap(info: Info, esr: u32, tf: &mut TrapFrame) {
let syndrome = Syndrome::from(esr); trace!("Interrupt: {:?}, ELR: {:#x?}", info, tf.elr);
trace!("Interrupt: {:?} from: {:?}", syndrome, info);
match info.kind { match info.kind {
Kind::Synchronous => { Kind::Synchronous => {
let syndrome = Syndrome::from(esr);
trace!("ESR: {:#x?}, Syndrome: {:?}", esr, syndrome);
// syndrome is only valid with sync // syndrome is only valid with sync
match syndrome { match syndrome {
Syndrome::Brk(brk) => handle_break(brk, tf), Syndrome::Brk(brk) => handle_break(brk, tf),

@ -11,64 +11,55 @@ use core::ops::Range;
/// Memory initialization. /// Memory initialization.
pub fn init() { pub fn init() {
/*let (start, end) = memory_map().expect("failed to find memory map");
unsafe {
HEAP_ALLOCATOR.lock().init(start, end - start);
}*/
#[repr(align(4096))] #[repr(align(4096))]
struct PageData([u8; PAGE_SIZE]); struct PageData([u8; PAGE_SIZE]);
static PAGE_TABLE_ROOT: PageData = PageData([0; PAGE_SIZE]); static PAGE_TABLE_LVL4: PageData = PageData([0; PAGE_SIZE]);
static PAGE_TABLE_LVL3: PageData = PageData([0; PAGE_SIZE]);
static PAGE_TABLE_LVL2: PageData = PageData([0; PAGE_SIZE]);
let frame = Frame::containing_address(PhysAddr::new(&PAGE_TABLE_ROOT as *const _ as u64)); let frame_lvl4 = Frame::containing_address(PhysAddr::new(&PAGE_TABLE_LVL4 as *const _ as u64));
super::paging::setup_page_table(frame); 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);
init_mmu(); init_mmu();
init_frame_allocator(); init_frame_allocator();
init_heap(); init_heap();
let (start, end) = memory_map().expect("failed to find memory map"); info!("memory: init end");
let mut v = vec![];
for i in 0..(20 + (start & 0xf)) {
v.push(i);
println!("{:x?} {:x?}", &v[i] as * const _ as usize, v);
}
} }
extern "C" { extern "C" {
static _end: u8; static _end: u8;
} }
fn init_frame_allocator() { fn init_frame_allocator() {
use bit_allocator::BitAlloc;
use core::ops::Range;
use consts::{MEMORY_OFFSET}; use consts::{MEMORY_OFFSET};
let (start, end) = memory_map().expect("failed to find memory map");
info!("{:x?} {:x?}", start, end);
let (start, end) = memory_map().expect("failed to find memory map");
let mut ba = FRAME_ALLOCATOR.lock(); let mut ba = FRAME_ALLOCATOR.lock();
use core::mem::size_of;
use ::memory::FrameAlloc;
info!("{:x?} {:x?}", &FRAME_ALLOCATOR as *const _ as usize, size_of::<FrameAlloc>());
use consts::{KERNEL_HEAP_OFFSET, KERNEL_HEAP_SIZE};
info!("{:x?} {:x?}", KERNEL_HEAP_OFFSET + KERNEL_HEAP_SIZE, end);
ba.insert(to_range(start, end)); ba.insert(to_range(start, end));
info!("FrameAllocator init end"); info!("FrameAllocator init end");
/*
* @param:
* start: start address
* end: end address
* @brief:
* transform the memory address to the page number
* @retval:
* the page number range from start address to end address
*/
fn to_range(start: usize, end: usize) -> Range<usize> { fn to_range(start: usize, end: usize) -> Range<usize> {
let page_start = (start - MEMORY_OFFSET) / PAGE_SIZE; let page_start = (start - MEMORY_OFFSET) / PAGE_SIZE;
let page_end = (end - MEMORY_OFFSET - 1) / PAGE_SIZE + 1; let page_end = (end - MEMORY_OFFSET - 1) / PAGE_SIZE + 1;
// info!("{:x?} {:x?}", page_start, page_end);
page_start..page_end page_start..page_end
} }
} }
fn init_mmu() { fn init_mmu() {
info!("init_mmu");
// device. // device.
MAIR_EL1.write( MAIR_EL1.write(
// Attribute 1 // Attribute 1
@ -80,7 +71,6 @@ fn init_mmu() {
); );
// Configure various settings of stage 1 of the EL1 translation regime. // Configure various settings of stage 1 of the EL1 translation regime.
let ips = ID_AA64MMFR0_EL1.read(ID_AA64MMFR0_EL1::PARange); let ips = ID_AA64MMFR0_EL1.read(ID_AA64MMFR0_EL1::PARange);
info!("{:x?}", ips);
TCR_EL1.write( TCR_EL1.write(
TCR_EL1::TBI0::Ignored TCR_EL1::TBI0::Ignored
+ TCR_EL1::IPS.val(ips) + TCR_EL1::IPS.val(ips)
@ -97,21 +87,20 @@ fn init_mmu() {
// First, force all previous changes to be seen before the MMU is enabled. // First, force all previous changes to be seen before the MMU is enabled.
unsafe { barrier::isb(barrier::SY); } unsafe { barrier::isb(barrier::SY); }
info!("{:x?}", TCR_EL1.get());
// Enable the MMU and turn on data and instruction caching. // Enable the MMU and turn on data and instruction caching.
SCTLR_EL1.modify(SCTLR_EL1::M::Enable + SCTLR_EL1::C::Cacheable + SCTLR_EL1::I::Cacheable); SCTLR_EL1.modify(SCTLR_EL1::M::Enable + SCTLR_EL1::C::Cacheable + SCTLR_EL1::I::Cacheable);
// Force MMU init to complete before next instruction // Force MMU init to complete before next instruction
unsafe { barrier::isb(barrier::SY); } unsafe { barrier::isb(barrier::SY); }
info!("mmu enabled!"); info!("mmu enabled");
} }
/// Returns the (start address, end address) of the available memory on this /// Returns the (start address, end address) of the available memory on this
/// system if it can be determined. If it cannot, `None` is returned. /// system if it can be determined. If it cannot, `None` is returned.
/// ///
/// This function is expected to return `Some` under all normal cirumstances. /// This function is expected to return `Some` under all normal cirumstances.
pub fn memory_map() -> Option<(usize, usize)> { fn memory_map() -> Option<(usize, usize)> {
let binary_end = unsafe { (&_end as *const u8) as u32 }; let binary_end = unsafe { (&_end as *const u8) as u32 };
let mut atags: Atags = Atags::get(); let mut atags: Atags = Atags::get();

@ -1,6 +1,6 @@
//! Page table implementations for aarch64. //! Page table implementations for aarch64.
use bit_allocator::{BitAlloc};
// Depends on kernel // Depends on kernel
use consts::{KERNEL_PML4, RECURSIVE_INDEX};
use memory::{active_table, alloc_frame, alloc_stack, dealloc_frame}; use memory::{active_table, alloc_frame, alloc_stack, dealloc_frame};
use ucore_memory::memory_set::*; use ucore_memory::memory_set::*;
use ucore_memory::PAGE_SIZE; use ucore_memory::PAGE_SIZE;
@ -11,29 +11,121 @@ use aarch64::paging::{Mapper, PageTable as Aarch64PageTable, PageTableEntry, Pag
use aarch64::paging::{FrameAllocator, FrameDeallocator, Page, PageRange, PhysFrame as Frame, Size4KiB}; use aarch64::paging::{FrameAllocator, FrameDeallocator, Page, PageRange, PhysFrame as Frame, Size4KiB};
use aarch64::{regs::*}; use aarch64::{regs::*};
// need 1 page register_bitfields! {u64,
pub fn setup_page_table(frame: Frame) { // AArch64 Reference Manual page 2150
let p4 = unsafe { &mut *(frame.start_address().as_u64() as *mut Aarch64PageTable) }; STAGE1_DESCRIPTOR [
/// Execute-never
XN OFFSET(54) NUMBITS(1) [
False = 0,
True = 1
],
/// Various address fields, depending on use case
LVL4_OUTPUT_ADDR_4KiB OFFSET(39) NUMBITS(9) [], // [47:39]
LVL3_OUTPUT_ADDR_4KiB OFFSET(30) NUMBITS(18) [], // [47:30]
LVL2_OUTPUT_ADDR_4KiB OFFSET(21) NUMBITS(27) [], // [47:21]
NEXT_LVL_TABLE_ADDR_4KiB OFFSET(12) NUMBITS(36) [], // [47:12]
/// Access flag
AF OFFSET(10) NUMBITS(1) [
False = 0,
True = 1
],
/// Shareability field
SH OFFSET(8) NUMBITS(2) [
OuterShareable = 0b10,
InnerShareable = 0b11
],
/// Access Permissions
AP OFFSET(6) NUMBITS(2) [
RW_EL1 = 0b00,
RW_EL1_EL0 = 0b01,
RO_EL1 = 0b10,
RO_EL1_EL0 = 0b11
],
/// Memory attributes index into the MAIR_EL1 register
AttrIndx OFFSET(2) NUMBITS(3) [],
TYPE OFFSET(1) NUMBITS(1) [
Block = 0,
Table = 1
],
VALID OFFSET(0) NUMBITS(1) [
False = 0,
True = 1
]
]
}
// need 3 page
pub fn setup_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) };
p4.zero(); p4.zero();
p3.zero();
p2.zero();
// p4.set_recursive(RECURSIVE_PAGE_PML4, frame.clone());
mod mair {
// Set kernel identity map pub const NORMAL: u64 = 0;
// 0x10000000 ~ 1K area pub const DEVICE: u64 = 1;
p4.map_identity(0o777, EF::PRESENT | EF::PXN | EF::UXN); }
// 0x80000000 ~ 8K area // Fill the rest of the LVL2 (2MiB) entries as block
p4.map_identity(0, EF::PRESENT); // descriptors. Differentiate between normal and device mem.
// p2.map_identity(KERNEL_PML4, EF::PRESENT | EF::READABLE | EF::WRITABLE); const MMIO_BASE: u64 = 0x3F000000;
// p2.map_identity(KERNEL_PML4 + 1, EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE); let mmio_base: u64 = MMIO_BASE >> 21;
let mut common = STAGE1_DESCRIPTOR::VALID::True
// use super::riscv::register::satp; + STAGE1_DESCRIPTOR::TYPE::Block
// unsafe { satp::set(satp::Mode::Sv32, 0, frame); } + STAGE1_DESCRIPTOR::AP::RW_EL1
// sfence_vma_all(); + STAGE1_DESCRIPTOR::AF::True;
// + STAGE1_DESCRIPTOR::XN::True;
ttbr0_el1_write(frame);
for i in 0..512 {
let j: u64 = i as u64;
let mem_attr = if j >= mmio_base {
STAGE1_DESCRIPTOR::SH::OuterShareable + STAGE1_DESCRIPTOR::AttrIndx.val(mair::DEVICE)
} else {
STAGE1_DESCRIPTOR::SH::InnerShareable + STAGE1_DESCRIPTOR::AttrIndx.val(mair::NORMAL)
};
p2[i].entry = (common + mem_attr + STAGE1_DESCRIPTOR::LVL2_OUTPUT_ADDR_4KiB.val(j)).value;
}
common = common + STAGE1_DESCRIPTOR::SH::InnerShareable + STAGE1_DESCRIPTOR::AttrIndx.val(mair::NORMAL);
p3[0].entry = (common + STAGE1_DESCRIPTOR::TYPE::Table + STAGE1_DESCRIPTOR::NEXT_LVL_TABLE_ADDR_4KiB.val(frame_lvl2.start_address().as_u64() >> 12)).value;
p3[1].entry = (common + STAGE1_DESCRIPTOR::LVL3_OUTPUT_ADDR_4KiB.val(1)).value;
p4[0].entry = (common + STAGE1_DESCRIPTOR::TYPE::Table + STAGE1_DESCRIPTOR::NEXT_LVL_TABLE_ADDR_4KiB.val(frame_lvl3.start_address().as_u64() >> 12)).value;
p4[RECURSIVE_INDEX].entry = (common + STAGE1_DESCRIPTOR::TYPE::Table + STAGE1_DESCRIPTOR::NEXT_LVL_TABLE_ADDR_4KiB.val(frame_lvl4.start_address().as_u64() >> 12)).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]);
// }
// }
ttbr0_el1_write(frame_lvl4);
tlb_invalidate(); tlb_invalidate();
info!("setup init page table end"); info!("setup init page table end");
} }
@ -69,7 +161,7 @@ impl PageTable for ActivePageTable {
type Entry = PageEntry; type Entry = PageEntry;
fn map(&mut self, addr: usize, target: usize) -> &mut PageEntry { fn map(&mut self, addr: usize, target: usize) -> &mut PageEntry {
let flags = EF::PRESENT | EF::WRITE | EF::UXN; let flags = EF::PRESENT | EF::WRITE | EF::ACCESSED | EF::UXN | EF::PAGE_BIT;
self.0.map_to(Page::of_addr(addr), Frame::of_addr(target), flags, &mut FrameAllocatorForAarch64) self.0.map_to(Page::of_addr(addr), Frame::of_addr(target), flags, &mut FrameAllocatorForAarch64)
.unwrap().flush(); .unwrap().flush();
self.get_entry(addr) self.get_entry(addr)
@ -81,7 +173,7 @@ impl PageTable for ActivePageTable {
} }
fn get_entry(&mut self, addr: usize) -> &mut PageEntry { fn get_entry(&mut self, addr: usize) -> &mut PageEntry {
let entry_addr = ((addr >> 9) & 0o777_777_777_7770) | 0xffffff80_00000000; let entry_addr = ((addr >> 9) & 0o777_777_777_7770) | (RECURSIVE_INDEX << 39);
unsafe { &mut *(entry_addr as *mut PageEntry) } unsafe { &mut *(entry_addr as *mut PageEntry) }
} }
@ -99,9 +191,12 @@ impl PageTable for ActivePageTable {
} }
} }
const ROOT_PAGE_TABLE: *mut Aarch64PageTable =
((RECURSIVE_INDEX << 39) | (RECURSIVE_INDEX << 30) | (RECURSIVE_INDEX << 21) | (RECURSIVE_INDEX << 12)) as *mut Aarch64PageTable;
impl ActivePageTable { impl ActivePageTable {
pub unsafe fn new() -> Self { pub unsafe fn new() -> Self {
ActivePageTable(RecursivePageTable::new(&mut *(0xffff_ffff_ffff_f000 as *mut _)).unwrap()) ActivePageTable(RecursivePageTable::new(&mut *(ROOT_PAGE_TABLE as *mut _)).unwrap())
} }
fn with_temporary_map(&mut self, frame: &Frame, f: impl FnOnce(&mut ActivePageTable, &mut Aarch64PageTable)) { fn with_temporary_map(&mut self, frame: &Frame, f: impl FnOnce(&mut ActivePageTable, &mut Aarch64PageTable)) {
// Create a temporary page // Create a temporary page
@ -161,7 +256,7 @@ impl Entry for PageEntry {
let mut addr = self as *const _ as usize; let mut addr = self as *const _ as usize;
for _ in 0..3 { for _ in 0..3 {
// Upper level entry // Upper level entry
addr = ((addr >> 9) & 0o777_777_777_7770) | 0xffffff80_00000000; addr = ((addr >> 9) & 0o777_777_777_7770) | (RECURSIVE_INDEX << 39);
// set USER_ACCESSIBLE // set USER_ACCESSIBLE
unsafe { (*(addr as *mut EF)).insert(EF::USER_ACCESSIBLE) }; unsafe { (*(addr as *mut EF)).insert(EF::USER_ACCESSIBLE) };
} }
@ -200,24 +295,24 @@ impl InactivePageTable for InactivePageTable0 {
active_table().with_temporary_map(&frame, |_, table: &mut Aarch64PageTable| { active_table().with_temporary_map(&frame, |_, table: &mut Aarch64PageTable| {
table.zero(); table.zero();
// set up recursive mapping for the table // set up recursive mapping for the table
table[511].set_frame(frame.clone(), EF::PRESENT | EF::WRITE); table[RECURSIVE_INDEX].set_frame(frame.clone(), EF::PRESENT | EF::WRITE | EF::ACCESSED | EF::PAGE_BIT);
}); });
InactivePageTable0 { p4_frame: frame } InactivePageTable0 { p4_frame: frame }
} }
fn edit(&mut self, f: impl FnOnce(&mut Self::Active)) { fn edit(&mut self, f: impl FnOnce(&mut Self::Active)) {
active_table().with_temporary_map(&ttbr0_el1_read().0, |active_table, p4_table: &mut Aarch64PageTable| { active_table().with_temporary_map(&ttbr0_el1_read().0, |active_table, p4_table: &mut Aarch64PageTable| {
let backup = p4_table[0o777].clone(); let backup = p4_table[RECURSIVE_INDEX].clone();
// overwrite recursive mapping // overwrite recursive mapping
p4_table[0o777].set_frame(self.p4_frame.clone(), EF::PRESENT | EF::WRITE); p4_table[RECURSIVE_INDEX].set_frame(self.p4_frame.clone(), EF::PRESENT | EF::WRITE | EF::ACCESSED | EF::PAGE_BIT);
tlb_invalidate(); tlb_invalidate();
// execute f in the new context // execute f in the new context
f(active_table); f(active_table);
// restore recursive mapping to original p4 table // restore recursive mapping to original p4 table
p4_table[0o777] = backup; p4_table[RECURSIVE_INDEX] = backup;
tlb_invalidate(); tlb_invalidate();
}); });
} }
@ -228,6 +323,7 @@ impl InactivePageTable for InactivePageTable0 {
debug!("switch table {:?} -> {:?}", old_frame, new_frame); debug!("switch table {:?} -> {:?}", old_frame, new_frame);
if old_frame != new_frame { if old_frame != new_frame {
ttbr0_el1_write(new_frame); ttbr0_el1_write(new_frame);
tlb_invalidate();
} }
} }
@ -237,11 +333,13 @@ impl InactivePageTable for InactivePageTable0 {
debug!("switch table {:?} -> {:?}", old_frame, new_frame); debug!("switch table {:?} -> {:?}", old_frame, new_frame);
if old_frame != new_frame { if old_frame != new_frame {
ttbr0_el1_write(new_frame); ttbr0_el1_write(new_frame);
tlb_invalidate();
} }
f(); f();
debug!("switch table {:?} -> {:?}", new_frame, old_frame); debug!("switch table {:?} -> {:?}", new_frame, old_frame);
if old_frame != new_frame { if old_frame != new_frame {
ttbr0_el1_write(old_frame); ttbr0_el1_write(old_frame);
tlb_invalidate();
} }
} }
@ -264,13 +362,12 @@ impl InactivePageTable for InactivePageTable0 {
impl InactivePageTable0 { impl InactivePageTable0 {
fn map_kernel(&mut self) { fn map_kernel(&mut self) {
let mut table = unsafe { &mut *(0xffff_ffff_ffff_f000 as *mut Aarch64PageTable) }; let table = unsafe { &mut *ROOT_PAGE_TABLE };
// Kernel at 0xffff_ff00_0000_0000 let e0 = table[KERNEL_PML4].clone();
// Kernel stack at 0x0000_57ac_0000_0000 (defined in bootloader crate) assert!(!e0.is_unused());
let e0 = table[0].clone();
self.edit(|_| { self.edit(|_| {
table[0].set_addr(e0.addr(), e0.flags() & EF::GLOBAL); table[KERNEL_PML4].set_addr(e0.addr(), e0.flags() & EF::GLOBAL);
//table[175].set_addr(estack.addr(), estack.flags() & EF::GLOBAL);
}); });
} }
} }

@ -131,15 +131,12 @@ mod x86_64 {
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
mod aarch64 { mod aarch64 {
//! TODO: replace unmiplemented consts with real value pub const RECURSIVE_INDEX: usize = 0o777;
const UNIMPLEMENTED: usize = 0; pub const KERNEL_OFFSET: usize = 0;
pub const KERNEL_OFFSET: usize = UNIMPLEMENTED; pub const KERNEL_PML4: usize = 0;
pub const KERNEL_PML4: usize = UNIMPLEMENTED;
pub const KERNEL_HEAP_OFFSET: usize = UNIMPLEMENTED;
pub const KERNEL_HEAP_SIZE: usize = 8 * 1024 * 1024; pub const KERNEL_HEAP_SIZE: usize = 8 * 1024 * 1024;
pub const MEMORY_OFFSET: usize = UNIMPLEMENTED; pub const MEMORY_OFFSET: usize = 0;
pub const MEMORY_END: usize = UNIMPLEMENTED; pub const USER_STACK_OFFSET: usize = 0x3000_0000;
pub const USER_STACK_OFFSET: usize = UNIMPLEMENTED; pub const USER_STACK_SIZE: usize = 1 * 1024 * 1024;
pub const USER_STACK_SIZE: usize = UNIMPLEMENTED; pub const USER32_STACK_OFFSET: usize = USER_STACK_OFFSET;
pub const USER32_STACK_OFFSET: usize = UNIMPLEMENTED;
} }

@ -38,6 +38,10 @@ extern crate aarch64;
use linked_list_allocator::LockedHeap; use linked_list_allocator::LockedHeap;
#[macro_use]
extern crate register;
#[macro_use] // print! #[macro_use] // print!
pub mod logging; pub mod logging;
mod memory; mod memory;

@ -1,5 +1,5 @@
pub use arch::paging::*; pub use arch::paging::*;
use bit_allocator::{BitAlloc, BitAlloc4K, BitAlloc64K}; use bit_allocator::{BitAlloc, BitAlloc4K, BitAlloc64K, BitAlloc1M};
use consts::MEMORY_OFFSET; use consts::MEMORY_OFFSET;
use spin::{Mutex, MutexGuard}; use spin::{Mutex, MutexGuard};
use super::HEAP_ALLOCATOR; use super::HEAP_ALLOCATOR;
@ -19,7 +19,7 @@ pub type FrameAlloc = BitAlloc4K;
// Raspberry Pi 3 has 1G memory // Raspberry Pi 3 has 1G memory
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
pub type FrameAlloc = BitAlloc64K; pub type FrameAlloc = BitAlloc1M;
lazy_static! { lazy_static! {
pub static ref FRAME_ALLOCATOR: Mutex<FrameAlloc> = Mutex::new(FrameAlloc::default()); pub static ref FRAME_ALLOCATOR: Mutex<FrameAlloc> = Mutex::new(FrameAlloc::default());

Loading…
Cancel
Save