123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- #![no_std]
- #![no_main]
- #![feature(naked_functions)]
- #![allow(static_mut_refs)]
- #[macro_use]
- extern crate rcore_console;
- use core::{
- arch::{asm, naked_asm},
- ptr::null,
- };
- use sbi_testing::sbi;
- use uart16550::Uart16550;
- const RISCV_HEAD_FLAGS: u64 = 0;
- const RISCV_HEADER_VERSION: u32 = 0x2;
- const RISCV_IMAGE_MAGIC: u64 = 0x5643534952; /* Magic number, little endian, "RISCV" */
- const RISCV_IMAGE_MAGIC2: u32 = 0x05435352; /* Magic number 2, little endian, "RSC\x05" */
- /// boot header
- #[naked]
- #[unsafe(no_mangle)]
- #[unsafe(link_section = ".head.text")]
- unsafe extern "C" fn _boot_header() -> ! {
- unsafe {
- naked_asm!(
- "j _start",
- ".word 0",
- ".balign 8",
- ".dword 0x200000",
- ".dword iend - istart",
- ".dword {RISCV_HEAD_FLAGS}",
- ".word {RISCV_HEADER_VERSION}",
- ".word 0",
- ".dword 0",
- ".dword {RISCV_IMAGE_MAGIC}",
- ".balign 4",
- ".word {RISCV_IMAGE_MAGIC2}",
- ".word 0",
- RISCV_HEAD_FLAGS = const RISCV_HEAD_FLAGS,
- RISCV_HEADER_VERSION = const RISCV_HEADER_VERSION,
- RISCV_IMAGE_MAGIC = const RISCV_IMAGE_MAGIC,
- RISCV_IMAGE_MAGIC2 = const RISCV_IMAGE_MAGIC2,
- );
- }
- }
- /// 内核入口。
- ///
- /// # Safety
- ///
- /// 裸函数。
- #[naked]
- #[unsafe(no_mangle)]
- #[unsafe(link_section = ".text.entry")]
- unsafe extern "C" fn _start(hartid: usize, device_tree_paddr: usize) -> ! {
- const STACK_SIZE: usize = 16384; // 16 KiB
- #[unsafe(link_section = ".bss.uninit")]
- static mut STACK: [u8; STACK_SIZE] = [0u8; STACK_SIZE];
- unsafe {
- naked_asm!(
- // clear bss segment
- " la t0, sbss
- la t1, ebss
- 1: bgeu t0, t1, 2f
- sd zero, 0(t0)
- addi t0, t0, 8
- j 1b",
- "2:",
- " la sp, {stack} + {stack_size}",
- " j {main}",
- stack_size = const STACK_SIZE,
- stack = sym STACK,
- main = sym rust_main,
- )
- }
- }
- extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
- let BoardInfo {
- smp,
- frequency,
- uart,
- } = BoardInfo::parse(dtb_pa);
- unsafe { UART = Uart16550Map(uart as _) };
- rcore_console::init_console(&Console);
- rcore_console::set_log_level(option_env!("LOG"));
- println!(
- r"
- _____ _ _ __ _
- |_ _|__ ___| |_ | |/ /___ _ __ _ __ ___| |
- | |/ _ \/ __| __| | ' // _ \ '__| '_ \ / _ \ |
- | | __/\__ \ |_ | . \ __/ | | | | | __/ |
- |_|\___||___/\__| |_|\_\___|_| |_| |_|\___|_|
- ================================================
- | boot hart id | {hartid:20} |
- | smp | {smp:20} |
- | timebase frequency | {frequency:17} Hz |
- | dtb physical address | {dtb_pa:#20x} |
- ------------------------------------------------"
- );
- let testing = sbi_testing::Testing {
- hartid,
- hart_mask: (1 << smp) - 1,
- hart_mask_base: 0,
- delay: frequency,
- };
- if testing.test() {
- sbi::system_reset(sbi::Shutdown, sbi::NoReason);
- } else {
- sbi::system_reset(sbi::Shutdown, sbi::SystemFailure);
- }
- unreachable!()
- }
- #[cfg_attr(not(test), panic_handler)]
- fn panic(info: &core::panic::PanicInfo) -> ! {
- let (hart_id, pc): (usize, usize);
- unsafe { asm!("mv {}, tp", out(reg) hart_id) };
- unsafe { asm!("auipc {}, 0", out(reg) pc) };
- println!("[test-kernel-panic] hart {hart_id} {info}");
- println!("[test-kernel-panic] pc = {pc:#x}");
- println!("[test-kernel-panic] SBI test FAILED due to panic");
- sbi::system_reset(sbi::Shutdown, sbi::SystemFailure);
- loop {}
- }
- struct BoardInfo {
- smp: usize,
- frequency: u64,
- uart: usize,
- }
- impl BoardInfo {
- fn parse(dtb_pa: usize) -> Self {
- use dtb_walker::{Dtb, DtbObj, HeaderError as E, Property, Str, WalkOperation::*};
- let mut ans = Self {
- smp: 0,
- frequency: 0,
- uart: 0,
- };
- unsafe {
- Dtb::from_raw_parts_filtered(dtb_pa as _, |e| {
- matches!(e, E::Misaligned(4) | E::LastCompVersion(_))
- })
- }
- .unwrap()
- .walk(|ctx, obj| match obj {
- DtbObj::SubNode { name } => {
- if ctx.is_root() && (name == Str::from("cpus") || name == Str::from("soc")) {
- StepInto
- } else if ctx.name() == Str::from("cpus") && name.starts_with("cpu@") {
- ans.smp += 1;
- StepOver
- } else if ctx.name() == Str::from("soc")
- && (name.starts_with("uart") || name.starts_with("serial"))
- {
- StepInto
- } else {
- StepOver
- }
- }
- DtbObj::Property(Property::Reg(mut reg)) => {
- if ctx.name().starts_with("uart") || ctx.name().starts_with("serial") {
- ans.uart = reg.next().unwrap().start;
- }
- StepOut
- }
- DtbObj::Property(Property::General { name, value }) => {
- if ctx.name() == Str::from("cpus") && name == Str::from("timebase-frequency") {
- ans.frequency = match *value {
- [a, b, c, d] => u32::from_be_bytes([a, b, c, d]) as _,
- [a, b, c, d, e, f, g, h] => u64::from_be_bytes([a, b, c, d, e, f, g, h]),
- _ => unreachable!(),
- };
- }
- StepOver
- }
- DtbObj::Property(_) => StepOver,
- });
- ans
- }
- }
- struct Console;
- static mut UART: Uart16550Map = Uart16550Map(null());
- pub struct Uart16550Map(*const Uart16550<u8>);
- unsafe impl Sync for Uart16550Map {}
- impl Uart16550Map {
- #[inline]
- pub fn get(&self) -> &Uart16550<u8> {
- unsafe { &*self.0 }
- }
- }
- impl rcore_console::Console for Console {
- #[inline]
- fn put_char(&self, c: u8) {
- unsafe { UART.get().write(core::slice::from_ref(&c)) };
- }
- #[inline]
- fn put_str(&self, s: &str) {
- unsafe { UART.get().write(s.as_bytes()) };
- }
- }
|