aarch64: put the kernel in the top VA range

toolchain_update
equation314 6 years ago
parent 0e38439fb8
commit 279f983786

@ -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)",

@ -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<ProgramHeader64>) {
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() {

@ -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;

@ -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)]

2
kernel/Cargo.lock generated

@ -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)",

@ -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,
})

@ -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() {

@ -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 : {

@ -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;

@ -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);
}

@ -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<MemorySet> = 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() {

@ -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<T>(&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();
}
}

@ -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];

@ -1 +1 @@
Subproject commit 64dac11ac304eece980ba4cffb2eac2040aa08b3
Subproject commit bbf127b24e3ec46b03dcedab4e4364d6494a26d9
Loading…
Cancel
Save