main.rs 6.0 KB

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