From 279f9837860afd82e2fc3f85754e3c114a2574b6 Mon Sep 17 00:00:00 2001 From: equation314 Date: Sat, 9 Mar 2019 19:50:11 +0800 Subject: [PATCH] aarch64: put the kernel in the top VA range --- bootloader/Cargo.lock | 2 +- bootloader/src/arch/aarch64/mod.rs | 9 +++--- crate/bcm2837/src/lib.rs | 2 +- crate/bcm2837/src/timer/generic_timer.rs | 2 +- kernel/Cargo.lock | 2 +- kernel/src/arch/aarch64/board/raspi3/fb.rs | 14 ++++----- kernel/src/arch/aarch64/board/raspi3/mod.rs | 2 +- kernel/src/arch/aarch64/boot/linker.ld | 2 +- kernel/src/arch/aarch64/consts.rs | 6 ++-- kernel/src/arch/aarch64/interrupt/context.rs | 4 +-- kernel/src/arch/aarch64/memory.rs | 25 +++++++++------- kernel/src/arch/aarch64/paging.rs | 31 ++++++++++++-------- kernel/src/process/structs.rs | 3 -- user | 2 +- 14 files changed, 57 insertions(+), 49 deletions(-) diff --git a/bootloader/Cargo.lock b/bootloader/Cargo.lock index 80bde96..1b96241 100644 --- a/bootloader/Cargo.lock +++ b/bootloader/Cargo.lock @@ -3,7 +3,7 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#ad81f8f0ebd6fed15b2b0696f5d1b566d36f1172" +source = "git+https://github.com/equation314/aarch64#14a08f4d285ae0ff515b03bff9f5e66eb68feaed" 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)", diff --git a/bootloader/src/arch/aarch64/mod.rs b/bootloader/src/arch/aarch64/mod.rs index e7cb408..61f9152 100644 --- a/bootloader/src/arch/aarch64/mod.rs +++ b/bootloader/src/arch/aarch64/mod.rs @@ -13,7 +13,7 @@ const IO_REMAP_BASE: u64 = 0x3F00_0000; const MEMORY_END: u64 = 0x4000_0000; const RECURSIVE_INDEX: usize = 0o777; -const KERNEL_OFFSET: u64 = 0x0000_0000_0000_0000; +const KERNEL_OFFSET: u64 = 0xFFFF_0000_0000_0000; global_asm!(include_str!("boot.S")); @@ -52,7 +52,8 @@ fn setup_temp_page_table(start_vaddr: VirtAddr, end_vaddr: VirtAddr, offset: u64 p4[0].set_frame(frame_lvl3, EF::default(), MairNormal::attr_value()); p4[RECURSIVE_INDEX].set_frame(frame_lvl4, EF::default(), MairNormal::attr_value()); - ttbr_el1_write(VirtAddr::new(KERNEL_OFFSET).va_range().unwrap() as u8, frame_lvl4); + ttbr_el1_write(0, frame_lvl4); + ttbr_el1_write(1, frame_lvl4); tlb_invalidate_all(); } @@ -112,9 +113,9 @@ pub fn map_kernel(kernel_start: usize, segments: &FixedVec) { unsafe { let src = (kernel_start as u64 + offset) as *const u8; - let dst = virt_addr as *mut u8; + let dst = virt_addr.wrapping_sub(KERNEL_OFFSET) as *mut u8; ptr::copy(src, dst, file_size as usize); - ptr::write_bytes((virt_addr + file_size) as *mut u8, 0, (mem_size - file_size) as usize); + ptr::write_bytes(dst.offset(file_size as isize), 0, (mem_size - file_size) as usize); } if virt_addr < start_vaddr.as_u64() { diff --git a/crate/bcm2837/src/lib.rs b/crate/bcm2837/src/lib.rs index d8af5ab..2755e55 100644 --- a/crate/bcm2837/src/lib.rs +++ b/crate/bcm2837/src/lib.rs @@ -9,4 +9,4 @@ pub mod mailbox; pub mod mini_uart; pub mod interrupt; -pub const IO_BASE: usize = 0x3F000000; +pub const IO_BASE: usize = 0xFFFF_0000_3F00_0000; diff --git a/crate/bcm2837/src/timer/generic_timer.rs b/crate/bcm2837/src/timer/generic_timer.rs index c4db806..bc54053 100644 --- a/crate/bcm2837/src/timer/generic_timer.rs +++ b/crate/bcm2837/src/timer/generic_timer.rs @@ -5,7 +5,7 @@ use aarch64::regs::*; use volatile::*; /// The base address for the ARM generic timer, IRQs, mailboxes -const GEN_TIMER_REG_BASE: usize = 0x40000000; +const GEN_TIMER_REG_BASE: usize = 0xFFFF_0000_4000_0000; /// Core interrupt sources (ref: QA7 4.10, page 16) #[repr(u8)] diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index eae162f..c14e2d1 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -3,7 +3,7 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#ad81f8f0ebd6fed15b2b0696f5d1b566d36f1172" +source = "git+https://github.com/equation314/aarch64#14a08f4d285ae0ff515b03bff9f5e66eb68feaed" 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)", diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/arch/aarch64/board/raspi3/fb.rs index 05fc6c0..02c647a 100644 --- a/kernel/src/arch/aarch64/board/raspi3/fb.rs +++ b/kernel/src/arch/aarch64/board/raspi3/fb.rs @@ -53,19 +53,19 @@ union ColorBuffer { } impl ColorBuffer { - fn new(color_depth: ColorDepth, bus_addr: u32, size: u32) -> ColorBuffer { + fn new(color_depth: ColorDepth, base_addr: usize, size: usize) -> ColorBuffer { unsafe { match color_depth { ColorDepth16 => ColorBuffer { buf16: core::slice::from_raw_parts_mut( - bus_addr as *mut u16, - (size / 2) as usize, + base_addr as *mut u16, + size / 2, ), }, ColorDepth32 => ColorBuffer { buf32: core::slice::from_raw_parts_mut( - bus_addr as *mut u32, - (size / 4) as usize, + base_addr as *mut u32, + size / 4, ), }, } @@ -144,7 +144,7 @@ impl Framebuffer { use crate::arch::memory; let paddr = info.bus_addr & !0xC0000000; - let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb") as u32; + let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb"); if vaddr == 0 { Err(format!( "cannot remap memory range [{:#x?}..{:#x?}]", @@ -153,7 +153,7 @@ impl Framebuffer { ))?; } Ok(Framebuffer { - buf: ColorBuffer::new(color_depth, vaddr, info.screen_size), + buf: ColorBuffer::new(color_depth, vaddr, info.screen_size as usize), color_depth, fb_info: info, }) diff --git a/kernel/src/arch/aarch64/board/raspi3/mod.rs b/kernel/src/arch/aarch64/board/raspi3/mod.rs index 6954e99..c001b34 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mod.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mod.rs @@ -9,7 +9,7 @@ pub mod serial; pub mod mailbox; pub const IO_REMAP_BASE: usize = bcm2837::IO_BASE; -pub const IO_REMAP_END: usize = 0x40001000; +pub const IO_REMAP_END: usize = 0xFFFF_0000_4000_1000; /// Initialize serial port before other initializations. pub fn init_serial_early() { diff --git a/kernel/src/arch/aarch64/boot/linker.ld b/kernel/src/arch/aarch64/boot/linker.ld index 0c102a0..e8a1046 100644 --- a/kernel/src/arch/aarch64/boot/linker.ld +++ b/kernel/src/arch/aarch64/boot/linker.ld @@ -1,7 +1,7 @@ ENTRY(_start) SECTIONS { - . = 0x100000; /* Load the kernel at this address. It's also kernel stack top address */ + . = 0xffff000000100000; /* Load the kernel at this address. It's also kernel stack top address */ bootstacktop = .; .text : { diff --git a/kernel/src/arch/aarch64/consts.rs b/kernel/src/arch/aarch64/consts.rs index af9f49c..ea71e7a 100644 --- a/kernel/src/arch/aarch64/consts.rs +++ b/kernel/src/arch/aarch64/consts.rs @@ -1,8 +1,8 @@ pub const RECURSIVE_INDEX: usize = 0o777; -pub const KERNEL_OFFSET: usize = 0; +pub const KERNEL_OFFSET: usize = 0xFFFF_0000_0000_0000; pub const KERNEL_PML4: usize = 0; pub const KERNEL_HEAP_SIZE: usize = 8 * 1024 * 1024; pub const MEMORY_OFFSET: usize = 0; -pub const USER_STACK_OFFSET: usize = 0xffff_8000_0000_0000; +pub const USER_STACK_OFFSET: usize = 0x0000_8000_0000_0000 - USER_STACK_SIZE; pub const USER_STACK_SIZE: usize = 1 * 1024 * 1024; -pub const USER32_STACK_OFFSET: usize = USER_STACK_OFFSET; \ No newline at end of file +pub const USER32_STACK_OFFSET: usize = USER_STACK_OFFSET; diff --git a/kernel/src/arch/aarch64/interrupt/context.rs b/kernel/src/arch/aarch64/interrupt/context.rs index ab24ecf..2f82217 100644 --- a/kernel/src/arch/aarch64/interrupt/context.rs +++ b/kernel/src/arch/aarch64/interrupt/context.rs @@ -127,11 +127,11 @@ impl Context { } pub unsafe fn switch(&mut self, target: &mut Self) { - self.ttbr = ttbr_el1_read(1); + self.ttbr = ttbr_el1_read(0); target.asid = ASID_ALLOCATOR.lock().alloc(target.asid); // with ASID we needn't flush TLB frequently - ttbr_el1_write_asid(1, target.asid.value, target.ttbr); + ttbr_el1_write_asid(0, target.asid.value, target.ttbr); barrier::dsb(barrier::ISH); Self::__switch(&mut self.stack_top, &mut target.stack_top); } diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index 416c7f8..1fd2162 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -1,6 +1,7 @@ //! Memory initialization for aarch64. use crate::memory::{init_heap, Linear, MemoryAttr, MemorySet, FRAME_ALLOCATOR}; +use crate::consts::{MEMORY_OFFSET, KERNEL_OFFSET}; use super::paging::MMIOType; use aarch64::regs::*; use atags::atags::Atags; @@ -16,7 +17,6 @@ pub fn init() { } fn init_frame_allocator() { - use crate::consts::MEMORY_OFFSET; use bit_allocator::BitAlloc; use core::ops::Range; @@ -45,15 +45,16 @@ static mut KERNEL_MEMORY_SET: Option = None; /// remap kernel page table after all initialization. fn remap_the_kernel() { + let offset = -(KERNEL_OFFSET as isize); let mut ms = MemorySet::new_bare(); - ms.push(0, bootstacktop as usize, Linear::new(0, MemoryAttr::default()), "kstack"); - ms.push(stext as usize, etext as usize, Linear::new(0, MemoryAttr::default().execute().readonly()), "text"); - ms.push(sdata as usize, edata as usize, Linear::new(0, MemoryAttr::default()), "data"); - ms.push(srodata as usize, erodata as usize, Linear::new(0, MemoryAttr::default().readonly()), "rodata"); - ms.push(sbss as usize, ebss as usize, Linear::new(0, MemoryAttr::default()), "bss"); + ms.push(KERNEL_OFFSET, bootstacktop as usize, Linear::new(offset, MemoryAttr::default()), "kstack"); + ms.push(stext as usize, etext as usize, Linear::new(offset, MemoryAttr::default().execute().readonly()), "text"); + ms.push(sdata as usize, edata as usize, Linear::new(offset, MemoryAttr::default()), "data"); + ms.push(srodata as usize, erodata as usize, Linear::new(offset, MemoryAttr::default().readonly()), "rodata"); + ms.push(sbss as usize, ebss as usize, Linear::new(offset, MemoryAttr::default()), "bss"); use super::board::{IO_REMAP_BASE, IO_REMAP_END}; - ms.push(IO_REMAP_BASE, IO_REMAP_END, Linear::new(0, MemoryAttr::default().mmio(MMIOType::Device as u8)), "io_remap"); + ms.push(IO_REMAP_BASE, IO_REMAP_END, Linear::new(offset, MemoryAttr::default().mmio(MMIOType::Device as u8)), "io_remap"); info!("{:#x?}", ms); unsafe { ms.get_page_table_mut().activate_as_kernel() } @@ -61,10 +62,12 @@ fn remap_the_kernel() { info!("kernel remap end"); } -pub fn ioremap(start: usize, len: usize, name: &'static str) -> usize { +pub fn ioremap(paddr: usize, len: usize, name: &'static str) -> usize { + let offset = -(KERNEL_OFFSET as isize); + let vaddr = paddr.wrapping_add(KERNEL_OFFSET); if let Some(ms) = unsafe { KERNEL_MEMORY_SET.as_mut() } { - ms.push(start, start + len, Linear::new(0, MemoryAttr::default().mmio(MMIOType::NormalNonCacheable as u8)), name); - return start; + ms.push(vaddr, vaddr + len, Linear::new(offset, MemoryAttr::default().mmio(MMIOType::NormalNonCacheable as u8)), name); + return vaddr; } 0 } @@ -74,7 +77,7 @@ pub fn ioremap(start: usize, len: usize, name: &'static str) -> usize { /// /// This function is expected to return `Some` under all normal cirumstances. fn memory_map() -> Option<(usize, usize)> { - let binary_end = _end as u32; + let binary_end = (_end as u64).wrapping_sub(KERNEL_OFFSET as u64); let mut atags: Atags = Atags::get(); while let Some(atag) = atags.next() { diff --git a/kernel/src/arch/aarch64/paging.rs b/kernel/src/arch/aarch64/paging.rs index 76995d8..51735c4 100644 --- a/kernel/src/arch/aarch64/paging.rs +++ b/kernel/src/arch/aarch64/paging.rs @@ -7,7 +7,7 @@ use aarch64::paging::{FrameAllocator, FrameDeallocator, Page, PhysFrame as Frame use aarch64::paging::memory_attribute::*; use log::*; // Depends on kernel -use crate::consts::{KERNEL_PML4, RECURSIVE_INDEX}; +use crate::consts::{KERNEL_OFFSET, KERNEL_PML4, RECURSIVE_INDEX}; use crate::memory::{active_table, alloc_frame, dealloc_frame}; pub struct ActivePageTable(RecursivePageTable<'static>); @@ -36,10 +36,16 @@ impl PageTable for ActivePageTable { } } -impl PageTableExt for ActivePageTable {} +impl PageTableExt for ActivePageTable { + const TEMP_PAGE_ADDR: usize = KERNEL_OFFSET | 0xcafeb000; +} const ROOT_PAGE_TABLE: *mut Aarch64PageTable = - ((RECURSIVE_INDEX << 39) | (RECURSIVE_INDEX << 30) | (RECURSIVE_INDEX << 21) | (RECURSIVE_INDEX << 12)) as *mut Aarch64PageTable; + (KERNEL_OFFSET | + (RECURSIVE_INDEX << 39) | + (RECURSIVE_INDEX << 30) | + (RECURSIVE_INDEX << 21) | + (RECURSIVE_INDEX << 12)) as *mut Aarch64PageTable; impl ActivePageTable { pub unsafe fn new() -> Self { @@ -183,11 +189,11 @@ impl InactivePageTable for InactivePageTable0 { } unsafe fn set_token(token: usize) { - ttbr_el1_write(1, Frame::containing_address(PhysAddr::new(token as u64))); + ttbr_el1_write(0, Frame::containing_address(PhysAddr::new(token as u64))); } fn active_token() -> usize { - ttbr_el1_read(1).start_address().as_u64() as usize + ttbr_el1_read(0).start_address().as_u64() as usize } fn flush_tlb() { @@ -195,14 +201,14 @@ impl InactivePageTable for InactivePageTable0 { } fn edit(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T { - let target = ttbr_el1_read(0).start_address().as_u64() as usize; + let target = ttbr_el1_read(1).start_address().as_u64() as usize; active_table().with_temporary_map(target, |active_table, p4_table: &mut Aarch64PageTable| { let backup = p4_table[RECURSIVE_INDEX].clone(); - let old_frame = ttbr_el1_read(1); + let old_frame = ttbr_el1_read(0); // overwrite recursive mapping p4_table[RECURSIVE_INDEX].set_frame(self.p4_frame.clone(), EF::default(), MairNormal::attr_value()); - ttbr_el1_write(1, self.p4_frame.clone()); + ttbr_el1_write(0, self.p4_frame.clone()); tlb_invalidate_all(); // execute f in the new context @@ -210,7 +216,7 @@ impl InactivePageTable for InactivePageTable0 { // restore recursive mapping to original p4 table p4_table[RECURSIVE_INDEX] = backup; - ttbr_el1_write(1, old_frame); + ttbr_el1_write(0, old_frame); tlb_invalidate_all(); ret }) @@ -221,11 +227,12 @@ impl InactivePageTable0 { /// Activate as kernel page table (TTBR0). /// Used in `arch::memory::remap_the_kernel()`. pub unsafe fn activate_as_kernel(&self) { - let old_frame = ttbr_el1_read(0); + let old_frame = ttbr_el1_read(1); let new_frame = self.p4_frame.clone(); - debug!("switch TTBR0 {:?} -> {:?}", old_frame, new_frame); + debug!("switch TTBR1 {:?} -> {:?}", old_frame, new_frame); if old_frame != new_frame { - ttbr_el1_write(0, new_frame); + ttbr_el1_write(0, Frame::of_addr(0)); + ttbr_el1_write(1, new_frame); tlb_invalidate_all(); } } diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 6218338..b6dafa1 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -238,9 +238,6 @@ fn memory_set_from(elf: &ElfFile<'_>) -> (MemorySet, usize) { let file_size = ph.file_size() as usize; let mem_size = ph.mem_size() as usize; - #[cfg(target_arch = "aarch64")] - assert_eq!((virt_addr >> 48), 0xffff, "Segment Fault"); - // Get target slice #[cfg(feature = "no_mmu")] let target = &mut target[virt_addr - va_begin..virt_addr - va_begin + mem_size]; diff --git a/user b/user index 64dac11..bbf127b 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 64dac11ac304eece980ba4cffb2eac2040aa08b3 +Subproject commit bbf127b24e3ec46b03dcedab4e4364d6494a26d9