main.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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 console;
  10. mod dynamic;
  11. use panic_halt as _;
  12. use riscv::register::mstatus;
  13. extern "C" fn main(hart_id: usize, opaque: usize, nonstandard_a2: usize) -> usize {
  14. let _ = (hart_id, opaque);
  15. console::init();
  16. info!("RustSBI version {}", rustsbi::VERSION);
  17. for line in rustsbi::LOGO.lines() {
  18. info!("{}", line);
  19. }
  20. info!("Initializing RustSBI machine-mode environment.");
  21. let info = dynamic::read_paddr(nonstandard_a2).unwrap_or_else(fail_no_dynamic_info_available);
  22. let (mpp, next_addr) = dynamic::mpp_next_addr(&info).unwrap_or_else(fail_invalid_dynamic_info);
  23. unsafe { mstatus::set_mpp(mpp) };
  24. next_addr
  25. }
  26. #[cold]
  27. fn fail_invalid_dynamic_info(_err: dynamic::DynamicError) -> (mstatus::MPP, usize) {
  28. // TODO dynamic information contains invalid privilege mode or next address
  29. loop {
  30. core::hint::spin_loop()
  31. }
  32. }
  33. #[cold]
  34. fn fail_no_dynamic_info_available(_err: ()) -> dynamic::DynamicInfo {
  35. // TODO no dynamic information available
  36. loop {
  37. core::hint::spin_loop()
  38. }
  39. }
  40. const LEN_STACK_PER_HART: usize = 16 * 1024;
  41. pub(crate) const NUM_HART_MAX: usize = 8;
  42. const LEN_STACK: usize = LEN_STACK_PER_HART * NUM_HART_MAX;
  43. // TODO contribute `Stack` struct into the crate `riscv`
  44. #[repr(C, align(128))]
  45. struct Stack<const N: usize>([u8; N]);
  46. #[link_section = ".bss.uninit"]
  47. static STACK: Stack<LEN_STACK> = Stack([0; LEN_STACK]);
  48. #[naked]
  49. #[link_section = ".text.entry"]
  50. #[export_name = "_start"]
  51. unsafe extern "C" fn start() -> ! {
  52. core::arch::asm!(
  53. // 1. Turn off interrupt
  54. " csrw mie, zero",
  55. // 2. Initialize programming langauge runtime
  56. // only clear bss if hartid is zero
  57. " csrr t0, mhartid",
  58. " bnez t0, 2f",
  59. // clear bss segment
  60. " la t0, sbss
  61. la t1, ebss
  62. 1: bgeu t0, t1, 2f
  63. sd zero, 0(t0)
  64. addi t0, t0, 8
  65. j 1b",
  66. // prepare data segment
  67. " la t3, sidata
  68. la t4, sdata
  69. la t5, edata
  70. 1: bgeu t4, t5, 2f
  71. ld t6, 0(t3)
  72. sd t6, 0(t4)
  73. addi t3, t3, 8
  74. addi t4, t4, 8
  75. j 1b",
  76. "2: ",
  77. // 3. Prepare stack for each hart
  78. " la sp, {stack}",
  79. " li t0, {stack_size_per_hart}",
  80. " csrr t1, mhartid",
  81. " addi t1, t1, 1",
  82. "1: ",
  83. " add sp, sp, t0",
  84. " addi t1, t1, -1",
  85. " bnez t1, 1b",
  86. // 4. Run Rust main function
  87. " call {main}",
  88. // 5. Jump to following boot sequences
  89. " csrw mepc, a0",
  90. " mret",
  91. stack_size_per_hart = const LEN_STACK_PER_HART,
  92. stack = sym STACK,
  93. main = sym main,
  94. options(noreturn)
  95. )
  96. }