Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 0 additions & 41 deletions src/arch/aarch64/entry.s
Original file line number Diff line number Diff line change
Expand Up @@ -79,44 +79,3 @@ el_1_entry:
.size _start, . - _start
.type _start, function
.global _start

.section .bss

.global l0_pgtable
.global l1_pgtable
.global l2_pgtable
.global l2k_pgtable
.global l3_pgtable
.global L0mib_pgtable

.align 12
l0_pgtable:
.space 512*8, 0
l1_pgtable:
.space 512*8, 0
l2_pgtable:
.space 512*8, 0
l2k_pgtable:
.space 512*8, 0
l3_pgtable:
.space 512*8, 0
L0mib_pgtable:
.space 512*8, 0
L2mib_pgtable:
.space 512*8, 0
L4mib_pgtable:
.space 512*8, 0
L6mib_pgtable:
.space 512*8, 0
L8mib_pgtable:
.space 512*8, 0
L10mib_pgtable:
.space 512*8, 0
L12mib_pgtable:
.space 512*8, 0
L14mib_pgtable:
.space 512*8, 0
L16mib_pgtable:
.space 512*8, 0
L18mib_pgtable:
.space 512*8, 0
78 changes: 8 additions & 70 deletions src/arch/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ mod console;
pub use self::console::Console;
pub mod drivers;
pub mod entry;
mod page_tables;
pub mod paging;

use core::arch::asm;
use core::ptr;

use aarch64_cpu::asm::barrier::{self, NSH, SY, dmb, dsb, isb};
use aarch64_cpu::registers::{ReadWriteable, SCTLR_EL1, TTBR0_EL1, TTBR1_EL1, Writeable};
use aarch64_cpu::asm::barrier::{NSH, SY, dmb, dsb, isb};
use align_address::Align;
use fdt::Fdt;
use goblin::elf::header::header64::{EI_DATA, ELFDATA2LSB, ELFMAG, Header, SELFMAG};
Expand All @@ -22,15 +22,6 @@ use crate::BootInfoExt;
use crate::arch::paging::*;
use crate::os::CONSOLE;

unsafe extern "C" {
static mut l0_pgtable: u64;
static mut l1_pgtable: u64;
static mut l2_pgtable: u64;
static mut l2k_pgtable: u64;
static mut l3_pgtable: u64;
static mut L0mib_pgtable: u64;
}

/// start address of the RAM at Qemu's virt emulation
const RAM_START: u64 = 0x40000000;
/// Default stack size of the kernel
Expand All @@ -40,13 +31,6 @@ const KERNEL_STACK_SIZE: usize = 32_768;
/// see <https://qemu.readthedocs.io/en/latest/system/arm/virt.html>
const DEVICE_TREE: u64 = RAM_START;

#[allow(dead_code)]
const PT_DEVICE: u64 = 0x707;
const PT_PT: u64 = 0x713;
const PT_MEM: u64 = 0x713;
const PT_MEM_CD: u64 = 0x70F;
const PT_SELF: u64 = 1 << 55;

pub unsafe fn get_memory(_memory_size: u64) -> u64 {
let loader_end = crate::os::executable_end().as_ptr();
(loader_end.expose_provenance() as u64).align_up(LargePageSize::SIZE as u64)
Expand Down Expand Up @@ -102,6 +86,7 @@ pub fn find_kernel() -> &'static [u8] {
}
}

#[allow(static_mut_refs)] // FIXME: disallow
pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! {
let LoadedKernel {
load_info,
Expand All @@ -118,62 +103,15 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! {
let uart_address: u32 = CONSOLE.lock().get().get_stdout();
info!("Detect UART at {uart_address:#x}");

let pgt_slice = unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(l0_pgtable), 512) };
for i in pgt_slice.iter_mut() {
*i = 0;
}
pgt_slice[0] = ptr::addr_of_mut!(l1_pgtable).expose_provenance() as u64 + PT_PT;
pgt_slice[511] = ptr::addr_of_mut!(l0_pgtable).expose_provenance() as u64 + PT_PT + PT_SELF;

let pgt_slice = unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(l1_pgtable), 512) };
for i in pgt_slice.iter_mut() {
*i = 0;
}
pgt_slice[0] = ptr::addr_of_mut!(l2_pgtable).expose_provenance() as u64 + PT_PT;
pgt_slice[1] = ptr::addr_of_mut!(l2k_pgtable).expose_provenance() as u64 + PT_PT;

let pgt_slice = unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(l2_pgtable), 512) };
for i in pgt_slice.iter_mut() {
*i = 0;
}
pgt_slice[0] = ptr::addr_of_mut!(l3_pgtable).expose_provenance() as u64 + PT_PT;

let pgt_slice = unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(l3_pgtable), 512) };
for i in pgt_slice.iter_mut() {
*i = 0;
}
pgt_slice[1] = uart_address as u64 + PT_MEM_CD;

// map kernel to __executable_start and stack below the kernel
let pgt_slice = unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(l2k_pgtable), 512) };
for i in pgt_slice.iter_mut() {
*i = 0;
}
for (i, pgt_slice) in pgt_slice.iter_mut().enumerate().take(10) {
*pgt_slice = ptr::addr_of_mut!(L0mib_pgtable).expose_provenance() as u64
+ (i * BasePageSize::SIZE) as u64
+ PT_PT;
}

let pgt_slice =
unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(L0mib_pgtable), 10 * 512) };
for (i, entry) in pgt_slice.iter_mut().enumerate() {
*entry = RAM_START + (i * BasePageSize::SIZE) as u64 + PT_MEM;
unsafe {
page_tables::init(uart_address);
}

CONSOLE.lock().get().set_stdout(0x1000);

// Load TTBRx
TTBR1_EL1.set(0);
TTBR0_EL1.set(&raw mut l0_pgtable as u64);
barrier::dsb(barrier::SY);
barrier::isb(barrier::SY);

// Enable paging
SCTLR_EL1.modify(SCTLR_EL1::M::Enable);
barrier::isb(barrier::SY);

info!("Successfully set up paging.");
unsafe {
page_tables::enable();
}

let fdt = unsafe {
Fdt::from_ptr(ptr::with_exposed_provenance(DEVICE_TREE as usize))
Expand Down
149 changes: 149 additions & 0 deletions src/arch/aarch64/page_tables.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
use core::ptr;

use aarch64_cpu::asm::barrier::{SY, dsb, isb};
use aarch64_cpu::registers::{ReadWriteable, SCTLR_EL1, TTBR0_EL1, TTBR1_EL1, Writeable};
use log::info;

use super::RAM_START;
use super::paging::{BasePageSize, PageSize};

static mut LEVEL_0_TABLE: PageTable = {
let mut table = [ptr::null_mut(); _];

table[0] = (&raw mut LEVEL_1_TABLE)
.wrapping_byte_add(descr::NORMAL)
.cast();
table[511] = (&raw mut LEVEL_0_TABLE)
.wrapping_byte_add(descr::NORMAL)
.wrapping_byte_add(descr::SELF)
.cast();

PageTable(table)
};

static mut LEVEL_1_TABLE: PageTable = {
let mut table = [ptr::null_mut(); _];

table[0] = (&raw mut LEVEL_2_TABLE_SERIAL)
.wrapping_byte_add(descr::NORMAL)
.cast();
table[1] = (&raw mut LEVEL_2_TABLE_RAM)
.wrapping_byte_add(descr::NORMAL)
.cast();

PageTable(table)
};

static mut LEVEL_2_TABLE_SERIAL: PageTable = {
let mut table = [ptr::null_mut(); _];

table[0] = (&raw mut LEVEL_3_TABLE_SERIAL)
.wrapping_byte_add(descr::NORMAL)
.cast();

PageTable(table)
};

static mut LEVEL_2_TABLE_RAM: PageTable = {
let mut table = [ptr::null_mut(); _];

let mut entry_i = 0;
while entry_i < 10usize {
let entry = &mut table[entry_i];

let level_3_table = unsafe { &raw mut LEVEL_3_TABLES_RAM[entry_i] };
*entry = level_3_table.wrapping_byte_add(descr::NORMAL).cast();

entry_i += 1;
}

PageTable(table)
};

static mut LEVEL_3_TABLE_SERIAL: PageTable = PageTable([ptr::null_mut(); _]);

static mut LEVEL_3_TABLES_RAM: [PageTable; 10] = {
let mut tables = [PageTable([ptr::null_mut(); _]); _];

let mut table_i = 0;
while table_i < tables.len() {
let table = &mut tables[table_i].0;

let mut entry_i = 0;
while entry_i < table.len() {
let entry = &mut table[entry_i];

let addr = (table_i * 512 + entry_i) * BasePageSize::SIZE;
*entry = ptr::with_exposed_provenance_mut::<()>(RAM_START as usize)
.wrapping_byte_add(addr)
.wrapping_byte_add(descr::NORMAL);

entry_i += 1;
}

table_i += 1;
}

tables
};

pub unsafe fn init(uart_address: u32) {
unsafe {
LEVEL_3_TABLE_SERIAL.0[1] = ptr::with_exposed_provenance_mut::<()>(uart_address as usize)
.wrapping_byte_add(descr::NON_CACHEABLE);
}
}

pub unsafe fn enable() {
// Set Translation Table Base Registers (TTBR)
TTBR1_EL1.set(0);
TTBR0_EL1.set((&raw mut LEVEL_0_TABLE).expose_provenance() as u64);
dsb(SY);
isb(SY);

// Set MMU enable in System Control Register (SCTLR)
SCTLR_EL1.modify(SCTLR_EL1::M::Enable);
isb(SY);

info!("Successfully set up paging.");
}

#[derive(Clone, Copy, Debug)]
#[repr(C, align(0x1000))]
struct PageTable([*mut (); 512]);

/// Descriptor values
///
/// For reference, see <https://developer.arm.com/documentation/ddi0487/mb/-Part-D-The-AArch64-System-Level-Architecture/-Chapter-D8-The-AArch64-Virtual-Memory-System-Architecture/-D8-3-Translation-table-descriptor-formats/-D8-3-1-VMSAv8-64-descriptor-formats>.
mod descr {
pub const NORMAL: usize = AF | SH_INNER | attr_indx(4) | TABLE | VALID;
pub const NON_CACHEABLE: usize = AF | SH_INNER | attr_indx(3) | TABLE | VALID;

/// Valid descriptor
const VALID: usize = 1;

/// Table descriptor
const TABLE: usize = 1 << 1;

/// Attribute index
///
/// Selects the corresponding `MAIR` memory region attributes.
const fn attr_indx(indx: u8) -> usize {
assert!(indx < 1 << 5);
(indx as usize) << 2
}

/// Shareability
///
/// Inner Shareable
const SH_INNER: usize = 1 << 8 | 1 << 9;

/// Access flag
const AF: usize = 1 << 10;

/// A software-defined marker for marking a self-referential entry.
///
/// This can be used for recursive page tables by the kernel, but is currently not needed.
// FIXME: remove once the kernel set's up it's own page tables.
pub const SELF: usize = 1 << 55;
}
3 changes: 1 addition & 2 deletions src/arch/riscv64/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ pub fn get_fdt() -> Fdt<'static> {
}

pub fn get_stack_ptr() -> *mut u8 {
// SAFETY: We only create a pointer here
let stack_top = ptr::addr_of_mut!(STACK);
let stack_top = &raw mut STACK;
// SAFETY: Pointing directly past the object is allowed
let stack_bottom = unsafe { stack_top.add(1) };
stack_bottom.cast::<u8>()
Expand Down