Add documentation
This commit is contained in:
parent
4898ad3139
commit
408857fcb6
|
@ -4,14 +4,15 @@
|
||||||
* Based on ideas from Jorge Aparicio, Andre Richter, Phil Oppenheimer.
|
* Based on ideas from Jorge Aparicio, Andre Richter, Phil Oppenheimer.
|
||||||
* Copyright (c) 2019 Berkus Decker <berkus+vesper@metta.systems>
|
* Copyright (c) 2019 Berkus Decker <berkus+vesper@metta.systems>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//! Low-level boot of the Raspberry's processor
|
||||||
|
//! http://infocenter.arm.com/help/topic/com.arm.doc.dai0527a/DAI0527A_baremetal_boot_code_for_ARMv8_A_processors.pdf
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::endless_sleep,
|
crate::endless_sleep,
|
||||||
cortex_a::{asm, regs::*},
|
cortex_a::{asm, regs::*},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Low-level boot of the Raspberry's processor
|
|
||||||
/// http://infocenter.arm.com/help/topic/com.arm.doc.dai0527a/DAI0527A_baremetal_boot_code_for_ARMv8_A_processors.pdf
|
|
||||||
|
|
||||||
/// Type check the user-supplied entry function.
|
/// Type check the user-supplied entry function.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! entry {
|
macro_rules! entry {
|
||||||
|
|
|
@ -354,6 +354,7 @@ fn into_mmu_attributes(
|
||||||
* 48-bit virtual address space; different mappings in VBAR0 (EL0) and VBAR1 (EL1+).
|
* 48-bit virtual address space; different mappings in VBAR0 (EL0) and VBAR1 (EL1+).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// Number of entries in a 4KiB mmu table.
|
||||||
pub const NUM_ENTRIES_4KIB: u64 = 512;
|
pub const NUM_ENTRIES_4KIB: u64 = 512;
|
||||||
|
|
||||||
/// Trait for abstracting over the possible page sizes, 4KiB, 16KiB, 2MiB, 1GiB.
|
/// Trait for abstracting over the possible page sizes, 4KiB, 16KiB, 2MiB, 1GiB.
|
||||||
|
@ -412,9 +413,14 @@ pub enum PageDirectory {}
|
||||||
/// L3 tables -- only pointers to 4/16KiB pages
|
/// L3 tables -- only pointers to 4/16KiB pages
|
||||||
pub enum PageTable {}
|
pub enum PageTable {}
|
||||||
|
|
||||||
|
/// Shared trait for specific table levels.
|
||||||
pub trait TableLevel {}
|
pub trait TableLevel {}
|
||||||
|
|
||||||
|
/// Shared trait for hierarchical table levels.
|
||||||
|
///
|
||||||
|
/// Specifies what is the next level of page table hierarchy.
|
||||||
pub trait HierarchicalLevel: TableLevel {
|
pub trait HierarchicalLevel: TableLevel {
|
||||||
|
/// Level of the next translation table below this one.
|
||||||
type NextLevel: TableLevel;
|
type NextLevel: TableLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,7 +440,8 @@ impl HierarchicalLevel for PageDirectory {
|
||||||
}
|
}
|
||||||
// PageTables do not have next level, therefore they are not HierarchicalLevel
|
// PageTables do not have next level, therefore they are not HierarchicalLevel
|
||||||
|
|
||||||
// Contains just u64 internally, provides enum interface on top
|
/// MMU address translation table.
|
||||||
|
/// Contains just u64 internally, provides enum interface on top
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[repr(align(4096))]
|
#[repr(align(4096))]
|
||||||
pub struct Table<L: TableLevel> {
|
pub struct Table<L: TableLevel> {
|
||||||
|
@ -447,6 +454,7 @@ impl<L> Table<L>
|
||||||
where
|
where
|
||||||
L: TableLevel,
|
L: TableLevel,
|
||||||
{
|
{
|
||||||
|
/// Zero out entire table.
|
||||||
pub fn zero(&mut self) {
|
pub fn zero(&mut self) {
|
||||||
for entry in self.entries.iter_mut() {
|
for entry in self.entries.iter_mut() {
|
||||||
*entry = 0;
|
*entry = 0;
|
||||||
|
@ -613,6 +621,11 @@ impl BaseAddr for [u64; 512] {
|
||||||
|
|
||||||
/// Set up identity mapped page tables for the first 1 gigabyte of address space.
|
/// Set up identity mapped page tables for the first 1 gigabyte of address space.
|
||||||
/// default: 880 MB ARM ram, 128MB VC
|
/// default: 880 MB ARM ram, 128MB VC
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Completely unsafe, we're in the hardware land! Incorrectly initialised tables will just
|
||||||
|
/// restart the CPU.
|
||||||
pub unsafe fn init() -> Result<(), &'static str> {
|
pub unsafe fn init() -> Result<(), &'static str> {
|
||||||
// Prepare the memory attribute indirection register.
|
// Prepare the memory attribute indirection register.
|
||||||
mair::set_up();
|
mair::set_up();
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: BlueOak-1.0.0
|
* SPDX-License-Identifier: BlueOak-1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//! Memory management functions for aarch64.
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::println,
|
crate::println,
|
||||||
core::{fmt, ops::RangeInclusive},
|
core::{fmt, ops::RangeInclusive},
|
||||||
|
@ -23,58 +26,85 @@ pub const PAGE_SIZE: usize = 4096;
|
||||||
/// @todo we need to infer the memory map from the provided DTB.
|
/// @todo we need to infer the memory map from the provided DTB.
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub mod map {
|
pub mod map {
|
||||||
|
/// Beginning of memory.
|
||||||
pub const START: usize = 0x0000_0000;
|
pub const START: usize = 0x0000_0000;
|
||||||
|
/// End of memory.
|
||||||
pub const END: usize = 0x3FFF_FFFF;
|
pub const END: usize = 0x3FFF_FFFF;
|
||||||
|
|
||||||
|
/// Physical RAM addresses.
|
||||||
pub mod phys {
|
pub mod phys {
|
||||||
|
/// Base address of video (VC) memory.
|
||||||
pub const VIDEOMEM_BASE: usize = 0x3e00_0000;
|
pub const VIDEOMEM_BASE: usize = 0x3e00_0000;
|
||||||
|
/// Base address of MMIO register range.
|
||||||
pub const MMIO_BASE: usize = 0x3F00_0000;
|
pub const MMIO_BASE: usize = 0x3F00_0000;
|
||||||
|
/// Base address of ARM<->VC mailbox area.
|
||||||
pub const VIDEOCORE_MBOX_BASE: usize = MMIO_BASE + 0x0000_B880;
|
pub const VIDEOCORE_MBOX_BASE: usize = MMIO_BASE + 0x0000_B880;
|
||||||
|
/// Base address of GPIO registers.
|
||||||
pub const GPIO_BASE: usize = MMIO_BASE + 0x0020_0000;
|
pub const GPIO_BASE: usize = MMIO_BASE + 0x0020_0000;
|
||||||
|
/// Base address of regular UART.
|
||||||
pub const PL011_UART_BASE: usize = MMIO_BASE + 0x0020_1000;
|
pub const PL011_UART_BASE: usize = MMIO_BASE + 0x0020_1000;
|
||||||
|
/// Base address of MiniUART.
|
||||||
pub const MINI_UART_BASE: usize = MMIO_BASE + 0x0021_5000;
|
pub const MINI_UART_BASE: usize = MMIO_BASE + 0x0021_5000;
|
||||||
|
/// End of MMIO memory.
|
||||||
pub const MMIO_END: usize = super::END;
|
pub const MMIO_END: usize = super::END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Virtual (mapped) addresses.
|
||||||
pub mod virt {
|
pub mod virt {
|
||||||
|
/// Start (top) of kernel stack.
|
||||||
pub const KERN_STACK_START: usize = super::START;
|
pub const KERN_STACK_START: usize = super::START;
|
||||||
|
/// End (bottom) of kernel stack. SP starts at KERN_STACK_END + 1.
|
||||||
pub const KERN_STACK_END: usize = 0x0007_FFFF;
|
pub const KERN_STACK_END: usize = 0x0007_FFFF;
|
||||||
|
|
||||||
// The second 2 MiB block.
|
/// Location of DMA-able memory region (in the second 2 MiB block).
|
||||||
pub const DMA_HEAP_START: usize = 0x0020_0000;
|
pub const DMA_HEAP_START: usize = 0x0020_0000;
|
||||||
|
/// End of DMA-able memory region.
|
||||||
pub const DMA_HEAP_END: usize = 0x005F_FFFF;
|
pub const DMA_HEAP_END: usize = 0x005F_FFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Types used for compiling the virtual memory layout of the kernel using
|
/// Types used for compiling the virtual memory layout of the kernel using address ranges.
|
||||||
/// address ranges.
|
|
||||||
pub mod kernel_mem_range {
|
pub mod kernel_mem_range {
|
||||||
use core::ops::RangeInclusive;
|
use core::ops::RangeInclusive;
|
||||||
|
|
||||||
|
/// Memory region attributes.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum MemAttributes {
|
pub enum MemAttributes {
|
||||||
|
/// Regular memory
|
||||||
CacheableDRAM,
|
CacheableDRAM,
|
||||||
|
/// Memory without caching
|
||||||
NonCacheableDRAM,
|
NonCacheableDRAM,
|
||||||
|
/// Device memory
|
||||||
Device,
|
Device,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Memory region access permissions.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum AccessPermissions {
|
pub enum AccessPermissions {
|
||||||
|
/// Read-only access
|
||||||
ReadOnly,
|
ReadOnly,
|
||||||
|
/// Read-write access
|
||||||
ReadWrite,
|
ReadWrite,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Memory region translation.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Translation {
|
pub enum Translation {
|
||||||
|
/// One-to-one address mapping
|
||||||
Identity,
|
Identity,
|
||||||
|
/// Mapping with a specified offset
|
||||||
Offset(usize),
|
Offset(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Summary structure of memory region properties.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct AttributeFields {
|
pub struct AttributeFields {
|
||||||
|
/// Attributes
|
||||||
pub mem_attributes: MemAttributes,
|
pub mem_attributes: MemAttributes,
|
||||||
|
/// Permissions
|
||||||
pub acc_perms: AccessPermissions,
|
pub acc_perms: AccessPermissions,
|
||||||
|
/// Disable executable code in this region
|
||||||
pub execute_never: bool,
|
pub execute_never: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,10 +118,17 @@ pub mod kernel_mem_range {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Memory region descriptor.
|
||||||
|
///
|
||||||
|
/// Used to construct iterable kernel memory ranges.
|
||||||
pub struct Descriptor {
|
pub struct Descriptor {
|
||||||
|
/// Name of the region
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
|
/// Virtual memory range
|
||||||
pub virtual_range: fn() -> RangeInclusive<usize>,
|
pub virtual_range: fn() -> RangeInclusive<usize>,
|
||||||
|
/// Mapping translation
|
||||||
pub translation: Translation,
|
pub translation: Translation,
|
||||||
|
/// Attributes
|
||||||
pub attribute_fields: AttributeFields,
|
pub attribute_fields: AttributeFields,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: BlueOak-1.0.0
|
* SPDX-License-Identifier: BlueOak-1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//! Implementation of aarch64 kernel functions.
|
||||||
|
|
||||||
mod boot;
|
mod boot;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
|
|
||||||
|
/// Loop forever in sleep mode.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn endless_sleep() -> ! {
|
pub fn endless_sleep() -> ! {
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
* SPDX-License-Identifier: BlueOak-1.0.0
|
* SPDX-License-Identifier: BlueOak-1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// https://doc.rust-lang.org/src/std/macros.rs.html
|
/// Macro similar to [std](https://doc.rust-lang.org/src/std/macros.rs.html)
|
||||||
|
/// but for writing into kernel-specific output (UART or QEMU console).
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! print {
|
macro_rules! print {
|
||||||
($($arg:tt)*) => ($crate::macros::_print(format_args!($($arg)*)));
|
($($arg:tt)*) => ($crate::macros::_print(format_args!($($arg)*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://doc.rust-lang.org/src/std/macros.rs.html
|
/// Macro similar to [std](https://doc.rust-lang.org/src/std/macros.rs.html)
|
||||||
|
/// but for writing into kernel-specific output (UART or QEMU console).
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! println {
|
macro_rules! println {
|
||||||
() => (print!("\n"));
|
() => (print!("\n"));
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: BlueOak-1.0.0
|
* SPDX-License-Identifier: BlueOak-1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//! Vesper single-address-space exokernel.
|
||||||
|
//!
|
||||||
|
//! This crate implements the kernel binary proper.
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
|
@ -17,6 +22,7 @@ use architecture_not_supported_sorry;
|
||||||
|
|
||||||
extern crate rlibc; // To enable linking memory intrinsics.
|
extern crate rlibc; // To enable linking memory intrinsics.
|
||||||
|
|
||||||
|
/// Architecture-specific code.
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
pub use arch::*;
|
pub use arch::*;
|
||||||
|
@ -41,8 +47,8 @@ fn init_mmu() {
|
||||||
println!("MMU initialised");
|
println!("MMU initialised");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kernel entry point
|
/// Kernel entry point.
|
||||||
// arch crate is responsible for calling this
|
/// `arch` crate is responsible for calling it.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn kmain() -> ! {
|
pub fn kmain() -> ! {
|
||||||
init_mmu();
|
init_mmu();
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: BlueOak-1.0.0
|
* SPDX-License-Identifier: BlueOak-1.0.0
|
||||||
*/
|
*/
|
||||||
// No-alloc write!() implementation from https://stackoverflow.com/a/50201632/145434
|
/// No-alloc write!() implementation from https://stackoverflow.com/a/50201632/145434
|
||||||
// Requires you to allocate a buffer somewhere manually.
|
/// Requires you to allocate a buffer somewhere manually.
|
||||||
// @todo Try to use arrayvec::ArrayString here instead?
|
// @todo Try to use arrayvec::ArrayString here instead?
|
||||||
|
|
||||||
use core::{cmp::min, fmt};
|
use core::{cmp::min, fmt};
|
||||||
|
|
||||||
pub struct WriteTo<'a> {
|
pub struct WriteTo<'a> {
|
||||||
|
|
Loading…
Reference in New Issue