main.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #![feature(naked_functions, asm_const)]
  2. #![no_std]
  3. #![no_main]
  4. #[macro_use]
  5. extern crate log;
  6. #[macro_use]
  7. mod macros;
  8. mod board;
  9. mod clint;
  10. mod console;
  11. mod dt;
  12. mod dynamic;
  13. mod fail;
  14. mod hart_context;
  15. mod hsm;
  16. mod reset;
  17. mod rfence;
  18. mod riscv_spec;
  19. mod trap;
  20. mod trap_stack;
  21. use clint::ClintDevice;
  22. use core::sync::atomic::{AtomicBool, Ordering};
  23. use core::{arch::asm, mem::MaybeUninit};
  24. use reset::TestDevice;
  25. use riscv::register::mstatus;
  26. use crate::board::{Board, SBI};
  27. use crate::clint::SIFIVECLINT;
  28. use crate::console::{ConsoleDevice, CONSOLE};
  29. use crate::hsm::{local_remote_hsm, Hsm};
  30. use crate::reset::RESET;
  31. use crate::rfence::RFence;
  32. use crate::riscv_spec::{current_hartid, menvcfg};
  33. use crate::trap::trap_vec;
  34. use crate::trap_stack::NUM_HART_MAX;
  35. #[no_mangle]
  36. extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
  37. // parse dynamic information
  38. let info = dynamic::read_paddr(nonstandard_a2).unwrap_or_else(fail::no_dynamic_info_available);
  39. static GENESIS: AtomicBool = AtomicBool::new(true);
  40. let is_boot_hart = if info.boot_hart == usize::MAX {
  41. GENESIS.swap(false, Ordering::AcqRel)
  42. } else {
  43. current_hartid() == info.boot_hart
  44. };
  45. if is_boot_hart {
  46. let (mpp, next_addr) =
  47. dynamic::mpp_next_addr(&info).unwrap_or_else(fail::invalid_dynamic_data);
  48. // parse the device tree
  49. let dtb = dt::parse_device_tree(opaque).unwrap_or_else(fail::device_tree_format);
  50. let dtb = dtb.share();
  51. let tree =
  52. serde_device_tree::from_raw_mut(&dtb).unwrap_or_else(fail::device_tree_deserialize);
  53. // TODO: The device base address needs to be parsed from FDT
  54. reset::init(0x100000);
  55. console::init(0x10000000);
  56. clint::init(0x2000000);
  57. info!("RustSBI version {}", rustsbi::VERSION);
  58. rustsbi::LOGO.lines().for_each(|line| info!("{}", line));
  59. info!("Initializing RustSBI machine-mode environment.");
  60. if let Some(model) = tree.model {
  61. info!("Model: {}", model.iter().next().unwrap_or("<unspecified>"));
  62. }
  63. info!(
  64. "Chosen stdout item: {}",
  65. tree.chosen
  66. .stdout_path
  67. .iter()
  68. .next()
  69. .unwrap_or("<unspecified>")
  70. );
  71. // Init SBI
  72. unsafe {
  73. SBI = MaybeUninit::new(Board {
  74. uart16550: Some(ConsoleDevice::new(&CONSOLE)),
  75. clint: Some(ClintDevice::new(&SIFIVECLINT, NUM_HART_MAX)),
  76. hsm: Some(Hsm),
  77. sifive_test: Some(TestDevice::new(&RESET)),
  78. rfence: Some(RFence),
  79. });
  80. }
  81. // TODO: PMP configuration needs to be obtained through the memory range in the device tree
  82. use riscv::register::*;
  83. unsafe {
  84. pmpcfg0::set_pmp(0, Range::OFF, Permission::NONE, false);
  85. pmpaddr0::write(0);
  86. pmpcfg0::set_pmp(1, Range::TOR, Permission::RWX, false);
  87. pmpaddr1::write(usize::MAX >> 2);
  88. }
  89. // 设置陷入栈
  90. trap_stack::prepare_for_trap();
  91. // 设置内核入口
  92. local_remote_hsm().start(NextStage {
  93. start_addr: next_addr,
  94. next_mode: mpp,
  95. opaque,
  96. });
  97. info!(
  98. "Redirecting hart {} to 0x{:0>16x} in {:?} mode.",
  99. current_hartid(),
  100. next_addr,
  101. mpp
  102. );
  103. } else {
  104. // TODO: PMP configuration needs to be obtained through the memory range in the device tree
  105. use riscv::register::*;
  106. unsafe {
  107. pmpcfg0::set_pmp(0, Range::OFF, Permission::NONE, false);
  108. pmpaddr0::write(0);
  109. pmpcfg0::set_pmp(1, Range::TOR, Permission::RWX, false);
  110. pmpaddr1::write(usize::MAX >> 2);
  111. }
  112. // 设置陷入栈
  113. trap_stack::prepare_for_trap();
  114. }
  115. clint::clear();
  116. unsafe {
  117. asm!("csrw mideleg, {}", in(reg) !0);
  118. asm!("csrw medeleg, {}", in(reg) !0);
  119. asm!("csrw mcounteren, {}", in(reg) !0);
  120. use riscv::register::{medeleg, mtvec};
  121. medeleg::clear_supervisor_env_call();
  122. medeleg::clear_illegal_instruction();
  123. menvcfg::set_bits(
  124. menvcfg::STCE | menvcfg::CBIE_INVALIDATE | menvcfg::CBCFE | menvcfg::CBZE,
  125. );
  126. mtvec::write(trap_vec as _, mtvec::TrapMode::Vectored);
  127. }
  128. }
  129. #[naked]
  130. #[link_section = ".text.entry"]
  131. #[export_name = "_start"]
  132. unsafe extern "C" fn start() -> ! {
  133. core::arch::asm!(
  134. // 1. Turn off interrupt
  135. " csrw mie, zero",
  136. // 2. Initialize programming langauge runtime
  137. // only clear bss if hartid matches preferred boot hart id
  138. " csrr t0, mhartid",
  139. " ld t1, 0(a2)",
  140. " li t2, {magic}",
  141. " bne t1, t2, 3f",
  142. " ld t2, 40(a2)",
  143. " bne t0, t2, 2f",
  144. " j 4f",
  145. "3:",
  146. " j 3b", // TODO multi hart preempt for runtime init
  147. "4:",
  148. // clear bss segment
  149. " la t0, sbss
  150. la t1, ebss
  151. 1: bgeu t0, t1, 2f
  152. sd zero, 0(t0)
  153. addi t0, t0, 8
  154. j 1b",
  155. // prepare data segment
  156. " la t3, sidata
  157. la t4, sdata
  158. la t5, edata
  159. 1: bgeu t4, t5, 2f
  160. ld t6, 0(t3)
  161. sd t6, 0(t4)
  162. addi t3, t3, 8
  163. addi t4, t4, 8
  164. j 1b",
  165. "2:",
  166. // 3. Prepare stack for each hart
  167. " call {locate_stack}",
  168. " call {main}",
  169. " csrw mscratch, sp",
  170. " j {hart_boot}",
  171. magic = const dynamic::MAGIC,
  172. locate_stack = sym trap_stack::locate,
  173. main = sym rust_main,
  174. hart_boot = sym trap::msoft,
  175. options(noreturn)
  176. )
  177. }
  178. #[derive(Debug)]
  179. pub struct NextStage {
  180. start_addr: usize,
  181. opaque: usize,
  182. next_mode: mstatus::MPP,
  183. }
  184. #[panic_handler]
  185. fn panic(info: &core::panic::PanicInfo) -> ! {
  186. use riscv::register::*;
  187. println!(
  188. "[rustsbi-panic] hart {} {info}",
  189. riscv::register::mhartid::read()
  190. );
  191. println!(
  192. "-----------------------------
  193. > mcause: {:?}
  194. > mepc: {:#018x}
  195. > mtval: {:#018x}
  196. -----------------------------",
  197. mcause::read().cause(),
  198. mepc::read(),
  199. mtval::read()
  200. );
  201. println!("[rustsbi-panic] system shutdown scheduled due to RustSBI panic");
  202. loop {}
  203. }