main.rs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. #![no_std]
  2. #![no_main]
  3. #![feature(naked_functions)]
  4. #![feature(alloc_error_handler)]
  5. #![feature(llvm_asm)]
  6. #![feature(asm)]
  7. #![feature(global_asm)]
  8. mod hal;
  9. use core::alloc::Layout;
  10. use core::panic::PanicInfo;
  11. use linked_list_allocator::LockedHeap;
  12. use rustsbi::{print, println, enter_privileged};
  13. use riscv::register::{
  14. mcause::{self, Exception, Interrupt, Trap},
  15. medeleg, mepc, mhartid, mideleg, mie, mip, misa::{self, MXL},
  16. mstatus::{self, MPP},
  17. mtval,
  18. mtvec::{self, TrapMode},
  19. };
  20. #[global_allocator]
  21. static ALLOCATOR: LockedHeap = LockedHeap::empty();
  22. #[panic_handler]
  23. fn panic(info: &PanicInfo) -> ! {
  24. println!("{}", info);
  25. loop {}
  26. }
  27. #[alloc_error_handler]
  28. fn oom(_layout: Layout) -> ! {
  29. loop {}
  30. }
  31. // #[export_name = "_mp_hook"]
  32. pub extern "C" fn _mp_hook() -> bool {
  33. mhartid::read() == 0
  34. }
  35. #[export_name = "_start"]
  36. #[link_section = ".text.entry"] // this is stable
  37. #[naked]
  38. fn main() -> ! {
  39. unsafe {
  40. llvm_asm!(
  41. "
  42. csrr a2, mhartid
  43. lui t0, %hi(_max_hart_id)
  44. add t0, t0, %lo(_max_hart_id)
  45. bgtu a2, t0, _start_abort
  46. la sp, _stack_start
  47. lui t0, %hi(_hart_stack_size)
  48. add t0, t0, %lo(_hart_stack_size)
  49. .ifdef __riscv_mul
  50. mul t0, a2, t0
  51. .else
  52. beqz a2, 2f // Jump if single-hart
  53. mv t1, a2
  54. mv t2, t0
  55. 1:
  56. add t0, t0, t2
  57. addi t1, t1, -1
  58. bnez t1, 1b
  59. 2:
  60. .endif
  61. sub sp, sp, t0
  62. csrw mscratch, zero
  63. j _start_success
  64. _start_abort:
  65. wfi
  66. j _start_abort
  67. _start_success:
  68. "
  69. )
  70. };
  71. // Ref: https://github.com/qemu/qemu/blob/aeb07b5f6e69ce93afea71027325e3e7a22d2149/hw/riscv/boot.c#L243
  72. let dtb_pa = unsafe {
  73. let dtb_pa: usize;
  74. llvm_asm!("":"={a1}"(dtb_pa));
  75. dtb_pa
  76. };
  77. if _mp_hook() {
  78. // init
  79. }
  80. /* setup trap */
  81. extern "C" {
  82. fn _start_trap();
  83. }
  84. unsafe {
  85. mtvec::write(_start_trap as usize, TrapMode::Direct);
  86. }
  87. /* main function start */
  88. extern "C" {
  89. static mut _sheap: u8;
  90. static _heap_size: u8;
  91. }
  92. if mhartid::read() == 0 {
  93. let sheap = unsafe { &mut _sheap } as *mut _ as usize;
  94. let heap_size = unsafe { &_heap_size } as *const u8 as usize;
  95. unsafe {
  96. ALLOCATOR.lock().init(sheap, heap_size);
  97. }
  98. // 其实这些参数不用提供,直接通过pac库生成
  99. let serial = hal::Ns16550a::new(0x10000000, 0, 11_059_200, 115200);
  100. // use through macro
  101. use rustsbi::legacy_stdio::init_legacy_stdio_embedded_hal;
  102. init_legacy_stdio_embedded_hal(serial);
  103. let clint = hal::Clint::new(0x2000000 as *mut u8);
  104. use rustsbi::init_ipi;
  105. init_ipi(clint);
  106. // todo: do not create two instances
  107. let clint = hal::Clint::new(0x2000000 as *mut u8);
  108. use rustsbi::init_timer;
  109. init_timer(clint);
  110. use rustsbi::init_reset;
  111. init_reset(hal::Reset);
  112. }
  113. // 把S的中断全部委托给S层
  114. unsafe {
  115. mideleg::set_sext();
  116. mideleg::set_stimer();
  117. mideleg::set_ssoft();
  118. medeleg::set_instruction_misaligned();
  119. medeleg::set_breakpoint();
  120. medeleg::set_user_env_call();
  121. medeleg::set_instruction_page_fault();
  122. medeleg::set_load_page_fault();
  123. medeleg::set_store_page_fault();
  124. mie::set_mext();
  125. // 不打开mie::set_mtimer
  126. mie::set_msoft();
  127. }
  128. if mhartid::read() == 0 {
  129. println!("[rustsbi] Version 0.1.0");
  130. println!("{}", rustsbi::LOGO);
  131. println!("[rustsbi] Platform: QEMU");
  132. let isa = misa::read();
  133. if let Some(isa) = isa {
  134. let mxl_str = match isa.mxl() {
  135. MXL::XLEN32 => "RV32",
  136. MXL::XLEN64 => "RV64",
  137. MXL::XLEN128 => "RV128",
  138. };
  139. print!("[rustsbi] misa: {}", mxl_str);
  140. for ext in 'A'..='Z' {
  141. if isa.has_extension(ext) {
  142. print!("{}", ext);
  143. }
  144. }
  145. println!("");
  146. }
  147. println!("[rustsbi] mideleg: {:#x}", mideleg::read().bits());
  148. println!("[rustsbi] medeleg: {:#x}", medeleg::read().bits());
  149. println!("[rustsbi] Kernel entry: 0x80200000");
  150. }
  151. extern "C" {
  152. fn _s_mode_start();
  153. }
  154. unsafe {
  155. mepc::write(_s_mode_start as usize);
  156. mstatus::set_mpp(MPP::Supervisor);
  157. enter_privileged(mhartid::read(), dtb_pa);
  158. }
  159. }
  160. global_asm!(
  161. "
  162. _s_mode_start:
  163. .option push
  164. .option norelax
  165. 1:
  166. auipc ra, %pcrel_hi(1f)
  167. ld ra, %pcrel_lo(1b)(ra)
  168. jr ra
  169. .align 3
  170. 1:
  171. .dword 0x80200000
  172. .option pop
  173. ");
  174. global_asm!(
  175. "
  176. .equ REGBYTES, 8
  177. .macro STORE reg, offset
  178. sd \\reg, \\offset*REGBYTES(sp)
  179. .endm
  180. .macro LOAD reg, offset
  181. ld \\reg, \\offset*REGBYTES(sp)
  182. .endm
  183. .section .text
  184. .global _start_trap
  185. .p2align 2
  186. _start_trap:
  187. csrrw sp, mscratch, sp
  188. bnez sp, 1f
  189. /* from M level, load sp */
  190. csrrw sp, mscratch, zero
  191. 1:
  192. addi sp, sp, -16 * REGBYTES
  193. STORE ra, 0
  194. STORE t0, 1
  195. STORE t1, 2
  196. STORE t2, 3
  197. STORE t3, 4
  198. STORE t4, 5
  199. STORE t5, 6
  200. STORE t6, 7
  201. STORE a0, 8
  202. STORE a1, 9
  203. STORE a2, 10
  204. STORE a3, 11
  205. STORE a4, 12
  206. STORE a5, 13
  207. STORE a6, 14
  208. STORE a7, 15
  209. mv a0, sp
  210. call _start_trap_rust
  211. LOAD ra, 0
  212. LOAD t0, 1
  213. LOAD t1, 2
  214. LOAD t2, 3
  215. LOAD t3, 4
  216. LOAD t4, 5
  217. LOAD t5, 6
  218. LOAD t6, 7
  219. LOAD a0, 8
  220. LOAD a1, 9
  221. LOAD a2, 10
  222. LOAD a3, 11
  223. LOAD a4, 12
  224. LOAD a5, 13
  225. LOAD a6, 14
  226. LOAD a7, 15
  227. addi sp, sp, 16 * REGBYTES
  228. csrrw sp, mscratch, sp
  229. mret
  230. "
  231. );
  232. // #[doc(hidden)]
  233. // #[export_name = "_mp_hook"]
  234. // pub extern "Rust" fn _mp_hook() -> bool {
  235. // match mhartid::read() {
  236. // 0 => true,
  237. // _ => loop {
  238. // unsafe { riscv::asm::wfi() }
  239. // },
  240. // }
  241. // }
  242. #[allow(unused)]
  243. struct TrapFrame {
  244. ra: usize,
  245. t0: usize,
  246. t1: usize,
  247. t2: usize,
  248. t3: usize,
  249. t4: usize,
  250. t5: usize,
  251. t6: usize,
  252. a0: usize,
  253. a1: usize,
  254. a2: usize,
  255. a3: usize,
  256. a4: usize,
  257. a5: usize,
  258. a6: usize,
  259. a7: usize,
  260. }
  261. #[export_name = "_start_trap_rust"]
  262. extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
  263. let cause = mcause::read().cause();
  264. match cause {
  265. Trap::Exception(Exception::SupervisorEnvCall) => {
  266. let params = [trap_frame.a0, trap_frame.a1, trap_frame.a2, trap_frame.a3];
  267. // 调用rust_sbi库的处理函数
  268. let ans = rustsbi::ecall(trap_frame.a7, trap_frame.a6, params);
  269. // 把返回值送还给TrapFrame
  270. trap_frame.a0 = ans.error;
  271. trap_frame.a1 = ans.value;
  272. // 跳过ecall指令
  273. mepc::write(mepc::read().wrapping_add(4));
  274. }
  275. Trap::Interrupt(Interrupt::MachineSoft) => {
  276. // 机器软件中断返回给S层
  277. unsafe {
  278. mip::set_ssoft();
  279. mie::clear_msoft();
  280. }
  281. }
  282. Trap::Interrupt(Interrupt::MachineTimer) => {
  283. // 机器时间中断返回给S层
  284. unsafe {
  285. mip::set_stimer();
  286. mie::clear_mtimer();
  287. }
  288. }
  289. Trap::Exception(Exception::IllegalInstruction) => {
  290. #[inline]
  291. unsafe fn get_vaddr_u32(vaddr: usize) -> u32 {
  292. let mut ans: u32;
  293. llvm_asm!("
  294. li t0, (1 << 17)
  295. mv t1, $1
  296. csrrs t0, mstatus, t0
  297. lwu t1, 0(t1)
  298. csrw mstatus, t0
  299. mv $0, t1
  300. "
  301. :"=r"(ans)
  302. :"r"(vaddr)
  303. :"t0", "t1");
  304. ans
  305. }
  306. let vaddr = mepc::read();
  307. let ins = unsafe { get_vaddr_u32(vaddr) };
  308. if ins & 0xFFFFF07F == 0xC0102073 {
  309. // rdtime
  310. let rd = ((ins >> 7) & 0b1_1111) as u8;
  311. // todo: one instance only
  312. let clint = hal::Clint::new(0x2000000 as *mut u8);
  313. let time_usize = clint.get_mtime() as usize;
  314. match rd {
  315. 10 => trap_frame.a0 = time_usize,
  316. 11 => trap_frame.a1 = time_usize,
  317. 12 => trap_frame.a2 = time_usize,
  318. 13 => trap_frame.a3 = time_usize,
  319. 14 => trap_frame.a4 = time_usize,
  320. 15 => trap_frame.a5 = time_usize,
  321. 16 => trap_frame.a6 = time_usize,
  322. 17 => trap_frame.a7 = time_usize,
  323. 5 => trap_frame.t0 = time_usize,
  324. 6 => trap_frame.t1 = time_usize,
  325. 7 => trap_frame.t2 = time_usize,
  326. 28 => trap_frame.t3 = time_usize,
  327. 29 => trap_frame.t4 = time_usize,
  328. 30 => trap_frame.t5 = time_usize,
  329. 31 => trap_frame.t6 = time_usize,
  330. _ => panic!("invalid target"),
  331. }
  332. mepc::write(mepc::read().wrapping_add(4)); // 跳过指令
  333. } else {
  334. panic!("invalid instruction, mepc: {:016x?}, instruction: {:016x?}", mepc::read(), ins);
  335. }
  336. }
  337. cause => panic!(
  338. "Unhandled exception! mcause: {:?}, mepc: {:016x?}, mtval: {:016x?}",
  339. cause,
  340. mepc::read(),
  341. mtval::read()
  342. ),
  343. }
  344. }