main.rs 11 KB

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