Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

draft: wip #35

Closed
wants to merge 8 commits into from
Closed
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
6 changes: 6 additions & 0 deletions aarch64/lib/kernel.ld
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ SECTIONS {
}
ebss = .;

heap = .;
.heap : ALIGN(4096) {
. = ALIGN(8*2097152);
}
eheap = .;

/* Reserve section for early pagetables. Align to 2MiB to allow us to map
as a 2MiB page.Note that this won't be needed once we transition to
recursive pagetables.
Expand Down
143 changes: 143 additions & 0 deletions aarch64/src/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use crate::devcons;
use crate::kmem;
use crate::kmem::from_virt_to_physaddr;
use crate::kmem::heap_virtrange;
use crate::mailbox;
use crate::pagealloc;
use crate::registers;
use crate::trap;
use crate::vm;
use crate::vm::kernel_root;
use crate::vm::PageTable;
use crate::vmalloc;
use alloc::boxed::Box;
use core::ptr;
use port::bumpalloc::Bump;
use port::fdt::DeviceTree;
use port::mem::PAGE_SIZE_4K;
use port::mem::{PhysRange, VirtRange};
use port::println;

static mut KPGTBL: PageTable = PageTable::empty();

unsafe fn print_memory_range(name: &str, range: VirtRange) {
let start = range.start();
let end = range.end();
let size = range.size();
println!(" {name}{start:#x}..{end:#x} ({size:#x})");
}

fn print_binary_sections() {
println!("Binary sections:");
unsafe {
print_memory_range("boottext:\t", kmem::boottext_virtrange());
print_memory_range("text:\t\t", kmem::text_virtrange());
print_memory_range("rodata:\t", kmem::rodata_virtrange());
print_memory_range("data:\t\t", kmem::data_virtrange());
print_memory_range("bss:\t\t", kmem::bss_virtrange());
print_memory_range("heap:\t\t", kmem::heap_virtrange());
print_memory_range("total:\t", kmem::total_virtrange());
}
}

fn print_physical_memory_info() {
println!("Physical memory map:");
let arm_mem = mailbox::get_arm_memory();
println!(" Memory:\t{arm_mem} ({:#x})", arm_mem.size());
let vc_mem = mailbox::get_vc_memory();
println!(" Video:\t{vc_mem} ({:#x})", vc_mem.size());
}

fn print_memory_info() {
println!("Memory usage:");
let (used, total) = pagealloc::usage_bytes();
println!(" Used:\t\t{used:#016x}");
println!(" Total:\t{total:#016x}");
}

// https://github.com/raspberrypi/documentation/blob/develop/documentation/asciidoc/computers/raspberry-pi/revision-codes.adoc
fn print_pi_name(board_revision: u32) {
let name = match board_revision {
0xa21041 => "Raspberry Pi 2B",
0xa02082 => "Raspberry Pi 3B",
0xb03115 => "Raspberry Pi 4B",
0xa220a0 => "Raspberry Compute Module 3",
_ => "Unrecognised",
};
println!(" Board Name:\t{name}");
}

fn print_board_info() {
println!("Board information:");
let board_revision = mailbox::get_board_revision();
print_pi_name(board_revision);
println!(" Board Rev:\t{board_revision:#010x}");
let model = mailbox::get_board_model();
println!(" Board Model:\t{model:#010x}");
let serial = mailbox::get_board_serial();
println!(" Serial Num:\t{serial:#010x}");
let mailbox::MacAddress { a, b, c, d, e, f } = mailbox::get_board_macaddr();
println!(" MAC Address:\t{a:02x}:{b:02x}:{c:02x}:{d:02x}:{e:02x}:{f:02x}");
let fw_revision = mailbox::get_firmware_revision();
println!(" Firmware Rev:\t{fw_revision:#010x}");
}

/// This function is concerned with preparing the system to the point where an
/// allocator can be set up and allocation is available. We can't assume
/// there's any allocator available when executing this function.
fn init_pre_allocator(dtb_va: usize) {
trap::init();

// Parse the DTB before we set up memory so we can correctly map it
let dt = unsafe { DeviceTree::from_usize(dtb_va).unwrap() };

// Set up uart so we can log as early as possible
mailbox::init(&dt);
devcons::init(&dt);

println!();
println!("r9 from the Internet");
println!("DTB found at: {:#x}", dtb_va);
println!("midr_el1: {:?}", registers::MidrEl1::read());

print_binary_sections();
print_physical_memory_info();
print_board_info();

// Map address space accurately using rust VM code to manage page tables
unsafe {
let dtb_range = PhysRange::with_len(from_virt_to_physaddr(dtb_va).addr(), dt.size());
vm::init(&mut *ptr::addr_of_mut!(KPGTBL), dtb_range, mailbox::get_arm_memory());
vm::switch(&*ptr::addr_of!(KPGTBL));
}
}

pub fn init(dtb_va: usize) {
init_pre_allocator(dtb_va);

static BUMP_ALLOC: Bump<{ 4 * PAGE_SIZE_4K }, PAGE_SIZE_4K> = Bump::new(0);
vmalloc::init(&BUMP_ALLOC, heap_virtrange());
BUMP_ALLOC.print_status();

// From this point we can use the global allocator

let _b = Box::new("ddododo");

print_memory_info();

kernel_root().print_recursive_tables();

println!("looping now");

// {
// let test = vmalloc::alloc(unsafe { Layout::from_size_align_unchecked(1024, 16) });
// println!("test alloc: {:p}", test);
// let test2 = vmalloc::alloc(unsafe { Layout::from_size_align_unchecked(1024, 16) });
// println!("test alloc: {:p}", test2);
// let test3 = vmalloc::alloc(unsafe { Layout::from_size_align_unchecked(1024, 4096) });
// println!("test alloc: {:p}", test3);
// }

#[allow(clippy::empty_loop)]
loop {}
}
112 changes: 103 additions & 9 deletions aarch64/src/kmem.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,86 @@
use crate::param::KZERO;
use port::mem::{PhysAddr, PhysRange};
use port::mem::{PhysAddr, PhysRange, VirtRange};

// These map to definitions in kernel.ld
extern "C" {
static boottext: [u64; 0];
static eboottext: [u64; 0];
static text: [u64; 0];
static etext: [u64; 0];
static rodata: [u64; 0];
static erodata: [u64; 0];
static data: [u64; 0];
static edata: [u64; 0];
static bss: [u64; 0];
static ebss: [u64; 0];
static early_pagetables: [u64; 0];
static eearly_pagetables: [u64; 0];
static heap: [u64; 0];
static eheap: [u64; 0];
static end: [u64; 0];
}

pub fn text_addr() -> usize {
0xffff_8000_0000_0000
fn start_addr() -> usize {
unsafe { boottext.as_ptr().addr() }
}

pub fn etext_addr() -> usize {
fn end_addr() -> usize {
unsafe { end.as_ptr().addr() }
}

fn boottext_addr() -> usize {
unsafe { boottext.as_ptr().addr() }
}

fn eboottext_addr() -> usize {
unsafe { eboottext.as_ptr().addr() }
}

fn text_addr() -> usize {
unsafe { text.as_ptr().addr() }
}

fn etext_addr() -> usize {
unsafe { etext.as_ptr().addr() }
}

pub fn erodata_addr() -> usize {
fn rodata_addr() -> usize {
unsafe { rodata.as_ptr().addr() }
}

fn erodata_addr() -> usize {
unsafe { erodata.as_ptr().addr() }
}

pub fn ebss_addr() -> usize {
fn data_addr() -> usize {
unsafe { data.as_ptr().addr() }
}

fn edata_addr() -> usize {
unsafe { edata.as_ptr().addr() }
}

fn bss_addr() -> usize {
unsafe { bss.as_ptr().addr() }
}

fn ebss_addr() -> usize {
unsafe { ebss.as_ptr().addr() }
}

pub fn early_pagetables_addr() -> usize {
fn heap_addr() -> usize {
unsafe { heap.as_ptr().addr() }
}

fn eheap_addr() -> usize {
unsafe { eheap.as_ptr().addr() }
}

fn early_pagetables_addr() -> usize {
unsafe { early_pagetables.as_ptr().addr() }
}

pub fn eearly_pagetables_addr() -> usize {
fn eearly_pagetables_addr() -> usize {
unsafe { eearly_pagetables.as_ptr().addr() }
}

Expand All @@ -50,7 +100,51 @@ pub fn from_ptr_to_physaddr<T>(a: *const T) -> PhysAddr {
from_virt_to_physaddr(a.addr())
}

pub fn early_pages_range() -> PhysRange {
pub fn kernel_text_physrange() -> PhysRange {
PhysRange(from_virt_to_physaddr(text_addr())..from_virt_to_physaddr(etext_addr()))
}

pub fn kernel_data_physrange() -> PhysRange {
PhysRange::with_len(from_virt_to_physaddr(etext_addr()).addr(), erodata_addr() - etext_addr())
}

pub fn kernel_bss_physrange() -> PhysRange {
PhysRange::with_len(from_virt_to_physaddr(erodata_addr()).addr(), ebss_addr() - erodata_addr())
}

pub fn kernel_heap_physrange() -> PhysRange {
PhysRange::with_len(from_virt_to_physaddr(heap_addr()).addr(), eheap_addr() - heap_addr())
}

pub fn total_virtrange() -> VirtRange {
VirtRange(start_addr()..end_addr())
}

pub fn boottext_virtrange() -> VirtRange {
VirtRange(boottext_addr()..eboottext_addr())
}

pub fn text_virtrange() -> VirtRange {
VirtRange(text_addr()..etext_addr())
}

pub fn rodata_virtrange() -> VirtRange {
VirtRange(rodata_addr()..erodata_addr())
}

pub fn data_virtrange() -> VirtRange {
VirtRange(data_addr()..edata_addr())
}

pub fn bss_virtrange() -> VirtRange {
VirtRange(bss_addr()..ebss_addr())
}

pub fn heap_virtrange() -> VirtRange {
VirtRange::with_len(heap_addr(), eheap_addr() - heap_addr())
}

pub fn early_pages_physrange() -> PhysRange {
PhysRange::new(
from_virt_to_physaddr(early_pagetables_addr()),
from_virt_to_physaddr(eearly_pagetables_addr()),
Expand Down
Loading
Loading