From 9e8124abbbf4dace6e2eef451db74793c536fdc2 Mon Sep 17 00:00:00 2001 From: equation314 Date: Tue, 20 Nov 2018 16:46:16 +0800 Subject: [PATCH] aarch64/mmu: mmu enabled --- crate/aarch64/Cargo.lock | 68 ------ crate/aarch64/src/asm.rs | 27 ++- crate/aarch64/src/paging/mod.rs | 57 ----- crate/aarch64/src/paging/page_table.rs | 9 +- crate/aarch64/src/paging/recursive.rs | 212 +------------------ kernel/Cargo.lock | 17 ++ kernel/Cargo.toml | 1 + kernel/src/arch/aarch64/boot/boot.S | 2 + kernel/src/arch/aarch64/interrupt/handler.rs | 5 +- kernel/src/arch/aarch64/memory.rs | 55 ++--- kernel/src/arch/aarch64/paging.rs | 163 +++++++++++--- kernel/src/consts.rs | 17 +- kernel/src/lib.rs | 4 + kernel/src/memory.rs | 6 +- 14 files changed, 215 insertions(+), 428 deletions(-) delete mode 100644 crate/aarch64/Cargo.lock diff --git a/crate/aarch64/Cargo.lock b/crate/aarch64/Cargo.lock deleted file mode 100644 index 2d0a329..0000000 --- a/crate/aarch64/Cargo.lock +++ /dev/null @@ -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" diff --git a/crate/aarch64/src/asm.rs b/crate/aarch64/src/asm.rs index d97fa78..17e6c29 100644 --- a/crate/aarch64/src/asm.rs +++ b/crate/aarch64/src/asm.rs @@ -4,12 +4,13 @@ use regs::*; #[inline(always)] pub fn tlb_invalidate() { - unsafe{ - asm!("dsb ishst - tlbi vmalle1is - dsb ish - tlbi vmalle1is - isb"); + unsafe { + asm!( + "dsb ishst + tlbi vmalle1is + dsb ish + isb" + ); } } @@ -63,6 +64,15 @@ pub unsafe fn get_ttbr1() -> usize { 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. #[inline(always)] pub fn sp_sel() -> u8 { @@ -94,7 +104,6 @@ pub fn wfi() { } } - /// The classic no-op #[inline] pub fn nop() { @@ -142,7 +151,7 @@ pub fn eret() -> ! { bitflags! { /// Controls cache settings for the level 4 page table. pub struct ttbr0_el1_Flags: u64 { - + const COMMON_NOT_PRIVATE = 1 << 0; } } @@ -150,7 +159,7 @@ bitflags! { pub fn ttbr0_el1_read() -> (PhysFrame, ttbr0_el1_Flags) { let value = TTBR0_EL1.get(); 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); (frame, flags) } diff --git a/crate/aarch64/src/paging/mod.rs b/crate/aarch64/src/paging/mod.rs index 56073b2..ebc00dc 100644 --- a/crate/aarch64/src/paging/mod.rs +++ b/crate/aarch64/src/paging/mod.rs @@ -34,16 +34,6 @@ pub trait NotGiantPageSize: PageSize {} #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] 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 { const SIZE: u64 = 4096; const SIZE_AS_DEBUG_STR: &'static str = "4KiB"; @@ -51,18 +41,6 @@ impl PageSize 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. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[repr(C)] @@ -128,31 +106,6 @@ impl Page { } } -impl Page { - /// 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 { - /// 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 { /// 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 { @@ -246,16 +199,6 @@ impl Iterator for PageRange { } } -impl PageRange { - /// Converts the range of 2MiB pages to a range of 4KiB pages. - pub fn as_4kib_page_range(self) -> PageRange { - PageRange { - start: Page::containing_address(self.start.start_address()), - end: Page::containing_address(self.end.start_address()), - } - } -} - impl fmt::Debug for PageRange { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("PageRange") diff --git a/crate/aarch64/src/paging/page_table.rs b/crate/aarch64/src/paging/page_table.rs index 1525b17..c06123e 100644 --- a/crate/aarch64/src/paging/page_table.rs +++ b/crate/aarch64/src/paging/page_table.rs @@ -21,7 +21,7 @@ pub enum FrameError { #[derive(Clone)] #[repr(transparent)] pub struct PageTableEntry { - entry: u64, + pub entry: u64, } impl PageTableEntry { @@ -42,7 +42,7 @@ impl PageTableEntry { /// Returns the physical address mapped by this entry, might be zero. 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. @@ -83,6 +83,7 @@ impl PageTableEntry { impl fmt::Debug for PageTableEntry { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut f = f.debug_struct("PageTableEntry"); + f.field("value", &self.entry); f.field("addr", &self.addr()); f.field("flags", &self.flags()); f.finish() @@ -94,9 +95,11 @@ bitflags! { pub struct PageTableFlags: u64 { const ALL = 0xffffffff_ffffffff; const TYPE_MASK = 3 << 0; - const TYPE_FAULT = 0 << 0; + // const TYPE_FAULT = 0 << 0; const TYPE_PAGE = 3 << 0; const TABLE_BIT = 1 << 1; + // const BLOCK_BIT = 0 << 1; + const PAGE_BIT = 1 << 1; const PRESENT = 1 << 0; const USER_ACCESSIBLE = 1 << 6; /* AP[1] */ diff --git a/crate/aarch64/src/paging/recursive.rs b/crate/aarch64/src/paging/recursive.rs index 0cbc6d0..d735216 100644 --- a/crate/aarch64/src/paging/recursive.rs +++ b/crate/aarch64/src/paging/recursive.rs @@ -4,7 +4,7 @@ use asm::tlb_invalidate; use paging::{ frame_alloc::FrameAllocator, 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 asm::ttbr0_el1_read; @@ -217,7 +217,7 @@ impl<'a> RecursivePageTable<'a> { if entry.is_unused() { 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; } else { return Err(MapToError::FrameAllocationFailed); @@ -241,214 +241,6 @@ impl<'a> RecursivePageTable<'a> { } } -impl<'a> Mapper for RecursivePageTable<'a> { - fn map_to( - &mut self, - page: Page, - frame: PhysFrame, - flags: PageTableFlags, - allocator: &mut A, - ) -> Result, MapToError> - where - A: FrameAllocator, - { - 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, - ) -> Result<(PhysFrame, MapperFlush), 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, - flags: PageTableFlags, - ) -> Result, 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) -> Option> { - 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 for RecursivePageTable<'a> { - fn map_to( - &mut self, - page: Page, - frame: PhysFrame, - flags: PageTableFlags, - allocator: &mut A, - ) -> Result, MapToError> - where - A: FrameAllocator, - { - 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, - ) -> Result<(PhysFrame, MapperFlush), 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, - flags: PageTableFlags, - ) -> Result, 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) -> Option> { - 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 for RecursivePageTable<'a> { fn map_to( diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 05f0710..7795f1f 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -5,6 +5,7 @@ dependencies = [ "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)", "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)", "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)", @@ -176,6 +177,14 @@ name = "redox_syscall" version = "0.1.40" 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]] name = "register" version = "0.2.1" @@ -238,6 +247,11 @@ dependencies = [ "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]] name = "tock-registers" version = "0.2.0" @@ -271,6 +285,7 @@ dependencies = [ "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)", "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", "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)", @@ -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 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 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 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)" = "" @@ -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 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 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 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" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index c80b6ef..06ea088 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -32,6 +32,7 @@ bit-allocator = { path = "../crate/bit-allocator" } ucore-memory = { path = "../crate/memory" } ucore-process = { path = "../crate/process" } simple-filesystem = { git = "https://github.com/wangrunji0408/SimpleFileSystem-Rust" } +register="0.1.0" [target.'cfg(target_arch = "x86_64")'.dependencies] bootloader = "0.3" diff --git a/kernel/src/arch/aarch64/boot/boot.S b/kernel/src/arch/aarch64/boot/boot.S index b8a142e..57a4239 100644 --- a/kernel/src/arch/aarch64/boot/boot.S +++ b/kernel/src/arch/aarch64/boot/boot.S @@ -17,6 +17,8 @@ halt: setup: # store the desired EL1 stack pointer in x1 adr x1, _start + # FIXME + lsl x1, x1, #2 # use SP_ELx for Exception level ELx msr SPsel, #1 diff --git a/kernel/src/arch/aarch64/interrupt/handler.rs b/kernel/src/arch/aarch64/interrupt/handler.rs index 85d1faf..787cbf5 100644 --- a/kernel/src/arch/aarch64/interrupt/handler.rs +++ b/kernel/src/arch/aarch64/interrupt/handler.rs @@ -38,10 +38,11 @@ pub struct Info { /// the trap frame for the exception. #[no_mangle] pub extern "C" fn rust_trap(info: Info, esr: u32, tf: &mut TrapFrame) { - let syndrome = Syndrome::from(esr); - trace!("Interrupt: {:?} from: {:?}", syndrome, info); + trace!("Interrupt: {:?}, ELR: {:#x?}", info, tf.elr); match info.kind { Kind::Synchronous => { + let syndrome = Syndrome::from(esr); + trace!("ESR: {:#x?}, Syndrome: {:?}", esr, syndrome); // syndrome is only valid with sync match syndrome { Syndrome::Brk(brk) => handle_break(brk, tf), diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index 126cf57..3e7f6d8 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -11,64 +11,55 @@ use core::ops::Range; /// Memory initialization. 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))] 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)); - super::paging::setup_page_table(frame); + 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); init_mmu(); - init_frame_allocator(); init_heap(); - let (start, end) = memory_map().expect("failed to find memory map"); - let mut v = vec![]; - for i in 0..(20 + (start & 0xf)) { - v.push(i); - println!("{:x?} {:x?}", &v[i] as * const _ as usize, v); - } - + info!("memory: init end"); } extern "C" { static _end: u8; } - fn init_frame_allocator() { + use bit_allocator::BitAlloc; + use core::ops::Range; 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(); - use core::mem::size_of; - use ::memory::FrameAlloc; - info!("{:x?} {:x?}", &FRAME_ALLOCATOR as *const _ as usize, size_of::()); - use consts::{KERNEL_HEAP_OFFSET, KERNEL_HEAP_SIZE}; - info!("{:x?} {:x?}", KERNEL_HEAP_OFFSET + KERNEL_HEAP_SIZE, end); ba.insert(to_range(start, 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 { let page_start = (start - MEMORY_OFFSET) / PAGE_SIZE; let page_end = (end - MEMORY_OFFSET - 1) / PAGE_SIZE + 1; - // info!("{:x?} {:x?}", page_start, page_end); page_start..page_end } } fn init_mmu() { - info!("init_mmu"); - // device. MAIR_EL1.write( // Attribute 1 @@ -80,7 +71,6 @@ fn init_mmu() { ); // Configure various settings of stage 1 of the EL1 translation regime. let ips = ID_AA64MMFR0_EL1.read(ID_AA64MMFR0_EL1::PARange); - info!("{:x?}", ips); TCR_EL1.write( TCR_EL1::TBI0::Ignored + 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. unsafe { barrier::isb(barrier::SY); } - info!("{:x?}", TCR_EL1.get()); // 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); // Force MMU init to complete before next instruction unsafe { barrier::isb(barrier::SY); } - info!("mmu enabled!"); + info!("mmu enabled"); } /// Returns the (start address, end address) of the available memory on this /// system if it can be determined. If it cannot, `None` is returned. /// /// 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 mut atags: Atags = Atags::get(); diff --git a/kernel/src/arch/aarch64/paging.rs b/kernel/src/arch/aarch64/paging.rs index 603346d..9696db9 100644 --- a/kernel/src/arch/aarch64/paging.rs +++ b/kernel/src/arch/aarch64/paging.rs @@ -1,6 +1,6 @@ //! Page table implementations for aarch64. -use bit_allocator::{BitAlloc}; // Depends on kernel +use consts::{KERNEL_PML4, RECURSIVE_INDEX}; use memory::{active_table, alloc_frame, alloc_stack, dealloc_frame}; use ucore_memory::memory_set::*; 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::{regs::*}; -// need 1 page -pub fn setup_page_table(frame: Frame) { - let p4 = unsafe { &mut *(frame.start_address().as_u64() as *mut Aarch64PageTable) }; - p4.zero(); - - - // p4.set_recursive(RECURSIVE_PAGE_PML4, frame.clone()); +register_bitfields! {u64, + // AArch64 Reference Manual page 2150 + 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 + ] + ] +} - // Set kernel identity map - // 0x10000000 ~ 1K area - p4.map_identity(0o777, EF::PRESENT | EF::PXN | EF::UXN); +// 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(); + p3.zero(); + p2.zero(); - // 0x80000000 ~ 8K area - p4.map_identity(0, EF::PRESENT); - // p2.map_identity(KERNEL_PML4, EF::PRESENT | EF::READABLE | EF::WRITABLE); - // p2.map_identity(KERNEL_PML4 + 1, EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE); + mod mair { + pub const NORMAL: u64 = 0; + pub const DEVICE: u64 = 1; + } - // use super::riscv::register::satp; - // unsafe { satp::set(satp::Mode::Sv32, 0, frame); } - // sfence_vma_all(); + // Fill the rest of the LVL2 (2MiB) entries as block + // descriptors. Differentiate between normal and device mem. + const MMIO_BASE: u64 = 0x3F000000; + let mmio_base: u64 = MMIO_BASE >> 21; + let mut common = STAGE1_DESCRIPTOR::VALID::True + + STAGE1_DESCRIPTOR::TYPE::Block + + STAGE1_DESCRIPTOR::AP::RW_EL1 + + STAGE1_DESCRIPTOR::AF::True; + // + STAGE1_DESCRIPTOR::XN::True; + + 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; + } - ttbr0_el1_write(frame); + 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(); + info!("setup init page table end"); } @@ -69,7 +161,7 @@ impl PageTable for ActivePageTable { type Entry = 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) .unwrap().flush(); self.get_entry(addr) @@ -81,7 +173,7 @@ impl PageTable for ActivePageTable { } 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) } } @@ -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 { 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)) { // Create a temporary page @@ -161,7 +256,7 @@ impl Entry for PageEntry { let mut addr = self as *const _ as usize; for _ in 0..3 { // 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 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| { table.zero(); // 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 } } 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| { - let backup = p4_table[0o777].clone(); + let backup = p4_table[RECURSIVE_INDEX].clone(); // 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(); // execute f in the new context f(active_table); // restore recursive mapping to original p4 table - p4_table[0o777] = backup; + p4_table[RECURSIVE_INDEX] = backup; tlb_invalidate(); }); } @@ -228,6 +323,7 @@ impl InactivePageTable for InactivePageTable0 { debug!("switch table {:?} -> {:?}", old_frame, new_frame); if old_frame != new_frame { ttbr0_el1_write(new_frame); + tlb_invalidate(); } } @@ -237,11 +333,13 @@ impl InactivePageTable for InactivePageTable0 { debug!("switch table {:?} -> {:?}", old_frame, new_frame); if old_frame != new_frame { ttbr0_el1_write(new_frame); + tlb_invalidate(); } f(); debug!("switch table {:?} -> {:?}", new_frame, old_frame); if old_frame != new_frame { ttbr0_el1_write(old_frame); + tlb_invalidate(); } } @@ -264,13 +362,12 @@ impl InactivePageTable for InactivePageTable0 { impl InactivePageTable0 { fn map_kernel(&mut self) { - let mut table = unsafe { &mut *(0xffff_ffff_ffff_f000 as *mut Aarch64PageTable) }; - // Kernel at 0xffff_ff00_0000_0000 - // Kernel stack at 0x0000_57ac_0000_0000 (defined in bootloader crate) - let e0 = table[0].clone(); + let table = unsafe { &mut *ROOT_PAGE_TABLE }; + let e0 = table[KERNEL_PML4].clone(); + assert!(!e0.is_unused()); + self.edit(|_| { - table[0].set_addr(e0.addr(), e0.flags() & EF::GLOBAL); - //table[175].set_addr(estack.addr(), estack.flags() & EF::GLOBAL); + table[KERNEL_PML4].set_addr(e0.addr(), e0.flags() & EF::GLOBAL); }); } } diff --git a/kernel/src/consts.rs b/kernel/src/consts.rs index b2cdefe..e879173 100644 --- a/kernel/src/consts.rs +++ b/kernel/src/consts.rs @@ -131,15 +131,12 @@ mod x86_64 { #[cfg(target_arch = "aarch64")] mod aarch64 { - //! TODO: replace unmiplemented consts with real value - const UNIMPLEMENTED: usize = 0; - pub const KERNEL_OFFSET: usize = UNIMPLEMENTED; - pub const KERNEL_PML4: usize = UNIMPLEMENTED; - pub const KERNEL_HEAP_OFFSET: usize = UNIMPLEMENTED; + pub const RECURSIVE_INDEX: usize = 0o777; + pub const KERNEL_OFFSET: usize = 0; + pub const KERNEL_PML4: usize = 0; pub const KERNEL_HEAP_SIZE: usize = 8 * 1024 * 1024; - pub const MEMORY_OFFSET: usize = UNIMPLEMENTED; - pub const MEMORY_END: usize = UNIMPLEMENTED; - pub const USER_STACK_OFFSET: usize = UNIMPLEMENTED; - pub const USER_STACK_SIZE: usize = UNIMPLEMENTED; - pub const USER32_STACK_OFFSET: usize = UNIMPLEMENTED; + pub const MEMORY_OFFSET: usize = 0; + pub const USER_STACK_OFFSET: usize = 0x3000_0000; + pub const USER_STACK_SIZE: usize = 1 * 1024 * 1024; + pub const USER32_STACK_OFFSET: usize = USER_STACK_OFFSET; } diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 063b1d0..05cc181 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -38,6 +38,10 @@ extern crate aarch64; use linked_list_allocator::LockedHeap; + +#[macro_use] +extern crate register; + #[macro_use] // print! pub mod logging; mod memory; diff --git a/kernel/src/memory.rs b/kernel/src/memory.rs index bbe78db..100925e 100644 --- a/kernel/src/memory.rs +++ b/kernel/src/memory.rs @@ -1,5 +1,5 @@ pub use arch::paging::*; -use bit_allocator::{BitAlloc, BitAlloc4K, BitAlloc64K}; +use bit_allocator::{BitAlloc, BitAlloc4K, BitAlloc64K, BitAlloc1M}; use consts::MEMORY_OFFSET; use spin::{Mutex, MutexGuard}; use super::HEAP_ALLOCATOR; @@ -19,7 +19,7 @@ pub type FrameAlloc = BitAlloc4K; // Raspberry Pi 3 has 1G memory #[cfg(target_arch = "aarch64")] -pub type FrameAlloc = BitAlloc64K; +pub type FrameAlloc = BitAlloc1M; lazy_static! { pub static ref FRAME_ALLOCATOR: Mutex = Mutex::new(FrameAlloc::default()); @@ -76,4 +76,4 @@ pub fn init_heap() { // use ucore_memory::cow::test::test_with; // test_with(&mut active_table()); // } -//} \ No newline at end of file +//}