main.rs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #![no_std]
  2. #![no_main]
  3. #![feature(naked_functions)]
  4. #![allow(static_mut_refs)]
  5. #[macro_use]
  6. extern crate rcore_console;
  7. use core::{
  8. arch::{asm, naked_asm},
  9. ptr::null,
  10. };
  11. use sbi_testing::sbi;
  12. use uart16550::Uart16550;
  13. const RISCV_HEAD_FLAGS: u64 = 0;
  14. const RISCV_HEADER_VERSION: u32 = 0x2;
  15. const RISCV_IMAGE_MAGIC: u64 = 0x5643534952; /* Magic number, little endian, "RISCV" */
  16. const RISCV_IMAGE_MAGIC2: u32 = 0x05435352; /* Magic number 2, little endian, "RSC\x05" */
  17. /// boot header
  18. #[naked]
  19. #[unsafe(no_mangle)]
  20. #[unsafe(link_section = ".head.text")]
  21. unsafe extern "C" fn _boot_header() -> ! {
  22. unsafe {
  23. naked_asm!(
  24. "j _start",
  25. ".word 0",
  26. ".balign 8",
  27. ".dword 0x200000",
  28. ".dword iend - istart",
  29. ".dword {RISCV_HEAD_FLAGS}",
  30. ".word {RISCV_HEADER_VERSION}",
  31. ".word 0",
  32. ".dword 0",
  33. ".dword {RISCV_IMAGE_MAGIC}",
  34. ".balign 4",
  35. ".word {RISCV_IMAGE_MAGIC2}",
  36. ".word 0",
  37. RISCV_HEAD_FLAGS = const RISCV_HEAD_FLAGS,
  38. RISCV_HEADER_VERSION = const RISCV_HEADER_VERSION,
  39. RISCV_IMAGE_MAGIC = const RISCV_IMAGE_MAGIC,
  40. RISCV_IMAGE_MAGIC2 = const RISCV_IMAGE_MAGIC2,
  41. );
  42. }
  43. }
  44. /// 内核入口。
  45. ///
  46. /// # Safety
  47. ///
  48. /// 裸函数。
  49. #[naked]
  50. #[unsafe(no_mangle)]
  51. #[unsafe(link_section = ".text.entry")]
  52. unsafe extern "C" fn _start(hartid: usize, device_tree_paddr: usize) -> ! {
  53. const STACK_SIZE: usize = 16384; // 16 KiB
  54. #[unsafe(link_section = ".bss.uninit")]
  55. static mut STACK: [u8; STACK_SIZE] = [0u8; STACK_SIZE];
  56. unsafe {
  57. naked_asm!(
  58. // clear bss segment
  59. " la t0, sbss
  60. la t1, ebss
  61. 1: bgeu t0, t1, 2f
  62. sd zero, 0(t0)
  63. addi t0, t0, 8
  64. j 1b",
  65. "2:",
  66. " la sp, {stack} + {stack_size}",
  67. " j {main}",
  68. stack_size = const STACK_SIZE,
  69. stack = sym STACK,
  70. main = sym rust_main,
  71. )
  72. }
  73. }
  74. extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
  75. let BoardInfo {
  76. smp,
  77. frequency,
  78. uart,
  79. } = BoardInfo::parse(dtb_pa);
  80. unsafe { UART = Uart16550Map(uart as _) };
  81. rcore_console::init_console(&Console);
  82. rcore_console::set_log_level(option_env!("LOG"));
  83. println!(
  84. r"
  85. _____ _ _ __ _
  86. |_ _|__ ___| |_ | |/ /___ _ __ _ __ ___| |
  87. | |/ _ \/ __| __| | ' // _ \ '__| '_ \ / _ \ |
  88. | | __/\__ \ |_ | . \ __/ | | | | | __/ |
  89. |_|\___||___/\__| |_|\_\___|_| |_| |_|\___|_|
  90. ================================================
  91. | boot hart id | {hartid:20} |
  92. | smp | {smp:20} |
  93. | timebase frequency | {frequency:17} Hz |
  94. | dtb physical address | {dtb_pa:#20x} |
  95. ------------------------------------------------"
  96. );
  97. let testing = sbi_testing::Testing {
  98. hartid,
  99. hart_mask: (1 << smp) - 1,
  100. hart_mask_base: 0,
  101. delay: frequency,
  102. };
  103. if testing.test() {
  104. sbi::system_reset(sbi::Shutdown, sbi::NoReason);
  105. } else {
  106. sbi::system_reset(sbi::Shutdown, sbi::SystemFailure);
  107. }
  108. unreachable!()
  109. }
  110. #[cfg_attr(not(test), panic_handler)]
  111. fn panic(info: &core::panic::PanicInfo) -> ! {
  112. let (hart_id, pc): (usize, usize);
  113. unsafe { asm!("mv {}, tp", out(reg) hart_id) };
  114. unsafe { asm!("auipc {}, 0", out(reg) pc) };
  115. println!("[test-kernel-panic] hart {hart_id} {info}");
  116. println!("[test-kernel-panic] pc = {pc:#x}");
  117. println!("[test-kernel-panic] SBI test FAILED due to panic");
  118. sbi::system_reset(sbi::Shutdown, sbi::SystemFailure);
  119. loop {}
  120. }
  121. struct BoardInfo {
  122. smp: usize,
  123. frequency: u64,
  124. uart: usize,
  125. }
  126. impl BoardInfo {
  127. fn parse(dtb_pa: usize) -> Self {
  128. use dtb_walker::{Dtb, DtbObj, HeaderError as E, Property, Str, WalkOperation::*};
  129. let mut ans = Self {
  130. smp: 0,
  131. frequency: 0,
  132. uart: 0,
  133. };
  134. unsafe {
  135. Dtb::from_raw_parts_filtered(dtb_pa as _, |e| {
  136. matches!(e, E::Misaligned(4) | E::LastCompVersion(_))
  137. })
  138. }
  139. .unwrap()
  140. .walk(|ctx, obj| match obj {
  141. DtbObj::SubNode { name } => {
  142. if ctx.is_root() && (name == Str::from("cpus") || name == Str::from("soc")) {
  143. StepInto
  144. } else if ctx.name() == Str::from("cpus") && name.starts_with("cpu@") {
  145. ans.smp += 1;
  146. StepOver
  147. } else if ctx.name() == Str::from("soc")
  148. && (name.starts_with("uart") || name.starts_with("serial"))
  149. {
  150. StepInto
  151. } else {
  152. StepOver
  153. }
  154. }
  155. DtbObj::Property(Property::Reg(mut reg)) => {
  156. if ctx.name().starts_with("uart") || ctx.name().starts_with("serial") {
  157. ans.uart = reg.next().unwrap().start;
  158. }
  159. StepOut
  160. }
  161. DtbObj::Property(Property::General { name, value }) => {
  162. if ctx.name() == Str::from("cpus") && name == Str::from("timebase-frequency") {
  163. ans.frequency = match *value {
  164. [a, b, c, d] => u32::from_be_bytes([a, b, c, d]) as _,
  165. [a, b, c, d, e, f, g, h] => u64::from_be_bytes([a, b, c, d, e, f, g, h]),
  166. _ => unreachable!(),
  167. };
  168. }
  169. StepOver
  170. }
  171. DtbObj::Property(_) => StepOver,
  172. });
  173. ans
  174. }
  175. }
  176. struct Console;
  177. static mut UART: Uart16550Map = Uart16550Map(null());
  178. pub struct Uart16550Map(*const Uart16550<u8>);
  179. unsafe impl Sync for Uart16550Map {}
  180. impl Uart16550Map {
  181. #[inline]
  182. pub fn get(&self) -> &Uart16550<u8> {
  183. unsafe { &*self.0 }
  184. }
  185. }
  186. impl rcore_console::Console for Console {
  187. #[inline]
  188. fn put_char(&self, c: u8) {
  189. unsafe { UART.get().write(core::slice::from_ref(&c)) };
  190. }
  191. #[inline]
  192. fn put_str(&self, s: &str) {
  193. unsafe { UART.get().write(s.as_bytes()) };
  194. }
  195. }