main.rs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #![feature(naked_functions)]
  2. #![feature(fn_align)]
  3. #![no_std]
  4. #![no_main]
  5. #![allow(static_mut_refs)]
  6. #[macro_use]
  7. extern crate log;
  8. #[macro_use]
  9. mod macros;
  10. mod dt;
  11. mod fail;
  12. mod firmware;
  13. mod platform;
  14. mod riscv_spec;
  15. mod sbi;
  16. use core::arch::asm;
  17. use crate::platform::PLATFORM;
  18. use crate::riscv_spec::{current_hartid, menvcfg};
  19. use crate::sbi::extensions::{
  20. hart_extension_probe, hart_privileged_version, privileged_version_detection, Extension,
  21. PrivilegedVersion,
  22. };
  23. use crate::sbi::hart_context::NextStage;
  24. use crate::sbi::hsm::local_remote_hsm;
  25. use crate::sbi::ipi;
  26. use crate::sbi::trap::{self, trap_vec};
  27. use crate::sbi::trap_stack;
  28. pub const START_ADDRESS: usize = 0x80000000;
  29. pub const R_RISCV_RELATIVE: usize = 3;
  30. #[no_mangle]
  31. extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
  32. // Track whether SBI is initialized and ready.
  33. let boot_hart_info = firmware::get_boot_hart(opaque, nonstandard_a2);
  34. // boot hart task entry.
  35. if boot_hart_info.is_boot_hart {
  36. // parse the device tree
  37. let fdt_address = boot_hart_info.fdt_address;
  38. unsafe {
  39. PLATFORM.init(fdt_address);
  40. PLATFORM.print_board_info();
  41. }
  42. firmware::set_pmp(unsafe { PLATFORM.info.memory_range.as_ref().unwrap() });
  43. // Get boot information and prepare for kernel entry.
  44. let boot_info = firmware::get_boot_info(nonstandard_a2);
  45. let (mpp, next_addr) = (boot_info.mpp, boot_info.next_address);
  46. // Start kernel.
  47. local_remote_hsm().start(NextStage {
  48. start_addr: next_addr,
  49. next_mode: mpp,
  50. opaque: fdt_address,
  51. });
  52. info!(
  53. "Redirecting hart {} to 0x{:0>16x} in {:?} mode.",
  54. current_hartid(),
  55. next_addr,
  56. mpp
  57. );
  58. } else {
  59. // 设置陷入栈
  60. trap_stack::prepare_for_trap();
  61. // Wait for boot hart to complete SBI initialization.
  62. while !unsafe { PLATFORM.ready() } {
  63. core::hint::spin_loop()
  64. }
  65. firmware::set_pmp(unsafe { PLATFORM.info.memory_range.as_ref().unwrap() });
  66. }
  67. // Detection Priv Ver
  68. privileged_version_detection();
  69. // Clear all pending IPIs.
  70. ipi::clear_all();
  71. // Configure CSRs and trap handling.
  72. unsafe {
  73. // Delegate all interrupts and exceptions to supervisor mode.
  74. asm!("csrw mideleg, {}", in(reg) !0);
  75. asm!("csrw medeleg, {}", in(reg) !0);
  76. asm!("csrw mcounteren, {}", in(reg) !0);
  77. asm!("csrw scounteren, {}", in(reg) !0);
  78. use riscv::register::{medeleg, mtvec};
  79. // Keep supervisor environment calls and illegal instructions in M-mode.
  80. medeleg::clear_supervisor_env_call();
  81. medeleg::clear_illegal_instruction();
  82. if hart_privileged_version(current_hartid()) >= PrivilegedVersion::Version1_12 {
  83. // Configure environment features based on available extensions.
  84. if hart_extension_probe(current_hartid(), Extension::Sstc) {
  85. menvcfg::set_bits(
  86. menvcfg::STCE | menvcfg::CBIE_INVALIDATE | menvcfg::CBCFE | menvcfg::CBZE,
  87. );
  88. } else {
  89. menvcfg::set_bits(menvcfg::CBIE_INVALIDATE | menvcfg::CBCFE | menvcfg::CBZE);
  90. }
  91. }
  92. // Set up vectored trap handling.
  93. mtvec::write(trap_vec as _, mtvec::TrapMode::Vectored);
  94. }
  95. }
  96. #[naked]
  97. #[link_section = ".text.entry"]
  98. #[export_name = "_start"]
  99. unsafe extern "C" fn start() -> ! {
  100. core::arch::asm!(
  101. // 1. Turn off interrupt.
  102. " csrw mie, zero",
  103. // 2. Initialize programming language runtime.
  104. // only clear bss if hartid matches preferred boot hart id.
  105. " csrr t0, mhartid",
  106. " bne t0, zero, 4f",
  107. " call {relocation_update}",
  108. "1:",
  109. // 3. Hart 0 clear bss segment.
  110. " lla t0, sbi_bss_start
  111. lla t1, sbi_bss_end
  112. 2: bgeu t0, t1, 3f
  113. sd zero, 0(t0)
  114. addi t0, t0, 8
  115. j 2b",
  116. "3: ", // Hart 0 set bss ready signal.
  117. " lla t0, 6f
  118. li t1, 1
  119. amoadd.w t0, t1, 0(t0)
  120. j 5f",
  121. "4:", // Other harts are waiting for bss ready signal.
  122. " li t1, 1
  123. lla t0, 6f
  124. lw t0, 0(t0)
  125. bne t0, t1, 4b",
  126. "5:",
  127. // 4. Prepare stack for each hart.
  128. " call {locate_stack}",
  129. " call {main}",
  130. " csrw mscratch, sp",
  131. " j {hart_boot}",
  132. " .balign 4",
  133. "6:", // bss ready signal.
  134. " .word 0",
  135. relocation_update = sym relocation_update,
  136. locate_stack = sym trap_stack::locate,
  137. main = sym rust_main,
  138. hart_boot = sym trap::msoft,
  139. options(noreturn)
  140. )
  141. }
  142. // Handle relocations for position-independent code
  143. #[naked]
  144. unsafe extern "C" fn relocation_update() {
  145. asm!(
  146. // Get load offset.
  147. " li t0, {START_ADDRESS}",
  148. " lla t1, sbi_start",
  149. " sub t2, t1, t0",
  150. // Foreach rela.dyn and update relocation.
  151. " lla t0, __rel_dyn_start",
  152. " lla t1, __rel_dyn_end",
  153. " li t3, {R_RISCV_RELATIVE}",
  154. "1:",
  155. " ld t4, 8(t0)",
  156. " bne t4, t3, 2f",
  157. " ld t4, 0(t0)", // Get offset
  158. " ld t5, 16(t0)", // Get append
  159. " add t4, t4, t2", // Add load offset to offset add append
  160. " add t5, t5, t2",
  161. " sd t5, 0(t4)", // Update address
  162. " addi t0, t0, 24", // Get next rela item
  163. "2:",
  164. " blt t0, t1, 1b",
  165. // Return
  166. " ret",
  167. R_RISCV_RELATIVE = const R_RISCV_RELATIVE,
  168. START_ADDRESS = const START_ADDRESS,
  169. options(noreturn)
  170. )
  171. }
  172. #[panic_handler]
  173. fn panic(info: &core::panic::PanicInfo) -> ! {
  174. use riscv::register::*;
  175. error!("Hart {} {info}", riscv::register::mhartid::read());
  176. error!("-----------------------------");
  177. error!("mcause: {:?}", mcause::read().cause());
  178. error!("mepc: {:#018x}", mepc::read());
  179. error!("mtval: {:#018x}", mtval::read());
  180. error!("-----------------------------");
  181. error!("System shutdown scheduled due to RustSBI panic");
  182. loop {}
  183. }