feat: add lower kernel identity-mapping

This commit is contained in:
Mark Poliakov 2021-10-08 22:33:10 +03:00
parent 455f6deec3
commit 70490c9aa8
9 changed files with 316 additions and 2 deletions

135
Cargo.lock generated
View File

@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -17,10 +23,38 @@ dependencies = [
"tock-registers",
]
[[package]]
name = "endian-type-rs"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6419a5c75e40011b9fe0174db3fe24006ab122fbe1b7e9cc5974b338a755c76"
[[package]]
name = "error"
version = "0.1.0"
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "fdt-rs"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99a40cabc11c8258822a593f5c51f2d9f4923e715ca9e2a0630cf77ae15f390b"
dependencies = [
"endian-type-rs",
"fallible-iterator",
"memoffset",
"num-derive",
"num-traits",
"rustc_version",
"static_assertions",
"unsafe_unwrap",
]
[[package]]
name = "kernel"
version = "0.1.0"
@ -28,15 +62,116 @@ dependencies = [
"cfg-if",
"cortex-a",
"error",
"fdt-rs",
"tock-registers",
]
[[package]]
name = "memoffset"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa"
dependencies = [
"autocfg",
]
[[package]]
name = "num-derive"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "osdev5"
version = "0.1.0"
[[package]]
name = "proc-macro2"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "tock-registers"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ee8fba06c1f4d0b396ef61a54530bb6b28f0dc61c38bc8bc5a5a48161e6282e"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "unsafe_unwrap"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1230ec65f13e0f9b28d789da20d2d419511893ea9dac2c1f4ef67b8b14e5da80"

View File

@ -22,6 +22,11 @@ SECTIONS {
*(.data*)
}
. = ALIGN(4K);
.tables : AT(. - KERNEL_OFFSET) {
*(.tables)
}
. = ALIGN(4K);
.bss : AT(. - KERNEL_OFFSET) {
PROVIDE(__bss_start = .);

View File

@ -13,6 +13,7 @@ test = false
cfg-if = "1.x.x"
error = { path = "../error" }
tock-registers = "0.7.x"
fdt-rs = { version = "0.x.x", default-features = false }
[target.'cfg(target_arch = "aarch64")'.dependencies]
cortex-a = { version = "6.x.x" }

View File

@ -8,6 +8,9 @@
.section .text._entry
.global _entry
_entry:
// Preserve FDT base address
mov x8, x0
mrs x1, mpidr_el1
and x1, x1, #3
beq 2f
@ -30,6 +33,7 @@ _entry:
ADR_REL x0, bsp_stack_top
mov sp, x0
mov x0, x8
b __aa64_bsp_main
.section .bss

View File

@ -1,13 +1,14 @@
//! aarch64 common boot logic
use crate::arch::{aarch64::asm::CPACR_EL1, machine};
use crate::dev::Device;
use crate::dev::{Device, fdt::DeviceTree};
use crate::mem::virt;
use cortex_a::asm::barrier::{self, dsb, isb};
use cortex_a::registers::{DAIF, SCTLR_EL1, VBAR_EL1};
use tock_registers::interfaces::{ReadWriteable, Writeable};
#[no_mangle]
fn __aa64_bsp_main() {
fn __aa64_bsp_main(fdt_base: usize) {
// Disable FP instruction trapping
CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNone);
@ -28,7 +29,14 @@ fn __aa64_bsp_main() {
isb(barrier::SY);
}
// Enable MMU
virt::enable().expect("Failed to initialize virtual memory");
machine::init_board().unwrap();
let fdt = DeviceTree::from_phys(fdt_base).expect("Failed to obtain a device tree");
fdt.dump();
unsafe {
machine::local_timer().enable().unwrap();
}

88
kernel/src/dev/fdt.rs Normal file
View File

@ -0,0 +1,88 @@
use error::Errno;
use fdt_rs::prelude::*;
use fdt_rs::{
base::DevTree,
index::{DevTreeIndex, DevTreeIndexNode},
};
#[repr(align(16))]
struct Wrap {
data: [u8; 16384],
}
static mut INDEX_BUFFER: Wrap = Wrap { data: [0; 16384] };
type INode<'a> = DevTreeIndexNode<'a, 'a, 'a>;
pub struct DeviceTree {
tree: DevTree<'static>,
index: DevTreeIndex<'static, 'static>,
}
fn tab(depth: usize) {
for _ in 0..depth {
debug!("\t");
}
}
fn dump_node(node: &INode, depth: usize) {
if node.name().unwrap().starts_with("virtio_mmio@") {
return;
}
tab(depth);
debugln!("{:?} {{", node.name().unwrap());
for prop in node.props() {
tab(depth + 1);
let name = prop.name().unwrap();
debug!("{:?} = ", name);
match name {
"compatible" => debug!("{:?}", prop.str().unwrap()),
"#address-cells" | "#size-cells" => debug!("{}", prop.u32(0).unwrap()),
"reg" => {
debug!("<");
let len = prop.length() / 4;
for i in 0..len {
debug!("{:#010x}", prop.u32(i).unwrap());
if i < len - 1 {
debug!(", ");
}
}
debug!(">");
},
_ => debug!("..."),
}
debugln!(";");
}
if node.children().next().is_some() {
debugln!("");
}
for child in node.children() {
dump_node(&child, depth + 1);
}
tab(depth);
debugln!("}}");
}
impl DeviceTree {
pub fn dump(&self) {
dump_node(&self.index.root(), 0);
}
pub fn from_phys(base: usize) -> Result<DeviceTree, Errno> {
// TODO virtualize address
let tree = unsafe { DevTree::from_raw_pointer(base as *const _) }.unwrap();
let layout = DevTreeIndex::get_layout(&tree).unwrap();
let index = DevTreeIndex::new(tree, unsafe {
&mut INDEX_BUFFER.data[0..layout.size() + layout.align()]
})
.unwrap();
Ok(DeviceTree { tree, index })
}
}

View File

@ -3,6 +3,8 @@
use error::Errno;
// Device classes
#[allow(missing_docs)]
pub mod fdt;
pub mod gpio;
pub mod irq;
pub mod pci;

View File

@ -1,5 +1,7 @@
//! Memory management and functions module
pub mod virt;
/// See memcpy(3p).
///
/// # Safety

View File

@ -0,0 +1,69 @@
#![allow(missing_docs)]
use cortex_a::asm::barrier::{self, dsb, isb};
use cortex_a::registers::{ID_AA64MMFR0_EL1, MAIR_EL1, SCTLR_EL1, TCR_EL1, TTBR0_EL1, TTBR1_EL1};
use error::Errno;
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
const PTE_BLOCK_AF: u64 = 1 << 10;
const PTE_BLOCK_ISH: u64 = 3 << 8;
const PTE_BLOCK_OSH: u64 = 2 << 8;
const PTE_PRESENT: u64 = 1 << 0;
#[no_mangle]
static mut KERNEL_TTBR0: [u64; 512] = {
let mut table = [0; 512];
// TODO fine-grained mapping
table[0] = (0 << 30) | PTE_BLOCK_AF | PTE_BLOCK_ISH | PTE_PRESENT;
table[1] = (1 << 30) | PTE_BLOCK_AF | PTE_BLOCK_ISH | PTE_PRESENT;
table
};
pub struct DeviceMemory {
base: usize,
count: usize,
}
impl DeviceMemory {
pub fn map(phys: usize, count: usize) -> Result<Self, Errno> {
todo!()
}
}
impl Drop for DeviceMemory {
fn drop(&mut self) {
todo!()
}
}
pub fn enable() -> Result<(), Errno> {
MAIR_EL1.write(
MAIR_EL1::Attr0_Normal_Outer::NonCacheable + MAIR_EL1::Attr0_Normal_Inner::NonCacheable,
);
TTBR0_EL1.set(unsafe { &mut KERNEL_TTBR0 as *mut _ as u64 });
if ID_AA64MMFR0_EL1.matches_all(ID_AA64MMFR0_EL1::TGran4::NotSupported) {
return Err(Errno::InvalidArgument);
}
let parange = ID_AA64MMFR0_EL1.read(ID_AA64MMFR0_EL1::PARange);
unsafe {
dsb(barrier::ISH);
isb(barrier::SY);
}
TCR_EL1.write(
TCR_EL1::IPS.val(parange)
+ TCR_EL1::T0SZ.val(25)
+ TCR_EL1::TG0::KiB_4
+ TCR_EL1::SH0::Outer
+ TCR_EL1::IRGN0::NonCacheable
+ TCR_EL1::ORGN0::NonCacheable
+ TCR_EL1::EPD1::SET
);
SCTLR_EL1.modify(SCTLR_EL1::M::SET);
Ok(())
}