main.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  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. medeleg::set_instruction_fault();
  153. medeleg::set_load_fault();
  154. medeleg::set_store_fault();
  155. mie::set_mext();
  156. // 不打开mie::set_mtimer
  157. mie::set_msoft();
  158. }
  159. if mhartid::read() == 0 {
  160. println!("[rustsbi] Version 0.1.0");
  161. println!("{}", rustsbi::LOGO);
  162. println!("[rustsbi] Platform: QEMU");
  163. let isa = misa::read();
  164. if let Some(isa) = isa {
  165. let mxl_str = match isa.mxl() {
  166. MXL::XLEN32 => "RV32",
  167. MXL::XLEN64 => "RV64",
  168. MXL::XLEN128 => "RV128",
  169. };
  170. print!("[rustsbi] misa: {}", mxl_str);
  171. for ext in 'A'..='Z' {
  172. if isa.has_extension(ext) {
  173. print!("{}", ext);
  174. }
  175. }
  176. println!("");
  177. }
  178. println!("[rustsbi] mideleg: {:#x}", mideleg::read().bits());
  179. println!("[rustsbi] medeleg: {:#x}", medeleg::read().bits());
  180. println!("[rustsbi] Kernel entry: 0x80200000");
  181. }
  182. extern "C" {
  183. fn _s_mode_start();
  184. }
  185. unsafe {
  186. mepc::write(_s_mode_start as usize);
  187. mstatus::set_mpp(MPP::Supervisor);
  188. enter_privileged(mhartid::read(), dtb_pa);
  189. }
  190. }
  191. global_asm!(
  192. "
  193. _s_mode_start:
  194. .option push
  195. .option norelax
  196. 1:
  197. auipc ra, %pcrel_hi(1f)
  198. ld ra, %pcrel_lo(1b)(ra)
  199. jr ra
  200. .align 3
  201. 1:
  202. .dword 0x80200000
  203. .option pop
  204. ");
  205. global_asm!(
  206. "
  207. .equ REGBYTES, 8
  208. .macro STORE reg, offset
  209. sd \\reg, \\offset*REGBYTES(sp)
  210. .endm
  211. .macro LOAD reg, offset
  212. ld \\reg, \\offset*REGBYTES(sp)
  213. .endm
  214. .section .text
  215. .global _start_trap
  216. .p2align 2
  217. _start_trap:
  218. csrrw sp, mscratch, sp
  219. bnez sp, 1f
  220. /* from M level, load sp */
  221. csrrw sp, mscratch, zero
  222. 1:
  223. addi sp, sp, -16 * REGBYTES
  224. STORE ra, 0
  225. STORE t0, 1
  226. STORE t1, 2
  227. STORE t2, 3
  228. STORE t3, 4
  229. STORE t4, 5
  230. STORE t5, 6
  231. STORE t6, 7
  232. STORE a0, 8
  233. STORE a1, 9
  234. STORE a2, 10
  235. STORE a3, 11
  236. STORE a4, 12
  237. STORE a5, 13
  238. STORE a6, 14
  239. STORE a7, 15
  240. mv a0, sp
  241. call _start_trap_rust
  242. LOAD ra, 0
  243. LOAD t0, 1
  244. LOAD t1, 2
  245. LOAD t2, 3
  246. LOAD t3, 4
  247. LOAD t4, 5
  248. LOAD t5, 6
  249. LOAD t6, 7
  250. LOAD a0, 8
  251. LOAD a1, 9
  252. LOAD a2, 10
  253. LOAD a3, 11
  254. LOAD a4, 12
  255. LOAD a5, 13
  256. LOAD a6, 14
  257. LOAD a7, 15
  258. addi sp, sp, 16 * REGBYTES
  259. csrrw sp, mscratch, sp
  260. mret
  261. "
  262. );
  263. // #[doc(hidden)]
  264. // #[export_name = "_mp_hook"]
  265. // pub extern "Rust" fn _mp_hook() -> bool {
  266. // match mhartid::read() {
  267. // 0 => true,
  268. // _ => loop {
  269. // unsafe { riscv::asm::wfi() }
  270. // },
  271. // }
  272. // }
  273. #[allow(unused)]
  274. struct TrapFrame {
  275. ra: usize,
  276. t0: usize,
  277. t1: usize,
  278. t2: usize,
  279. t3: usize,
  280. t4: usize,
  281. t5: usize,
  282. t6: usize,
  283. a0: usize,
  284. a1: usize,
  285. a2: usize,
  286. a3: usize,
  287. a4: usize,
  288. a5: usize,
  289. a6: usize,
  290. a7: usize,
  291. }
  292. #[export_name = "_start_trap_rust"]
  293. extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
  294. let cause = mcause::read().cause();
  295. match cause {
  296. Trap::Exception(Exception::SupervisorEnvCall) => {
  297. let params = [trap_frame.a0, trap_frame.a1, trap_frame.a2, trap_frame.a3];
  298. // 调用rust_sbi库的处理函数
  299. let ans = rustsbi::ecall(trap_frame.a7, trap_frame.a6, params);
  300. // 把返回值送还给TrapFrame
  301. trap_frame.a0 = ans.error;
  302. trap_frame.a1 = ans.value;
  303. // 跳过ecall指令
  304. mepc::write(mepc::read().wrapping_add(4));
  305. }
  306. Trap::Interrupt(Interrupt::MachineSoft) => {
  307. // 机器软件中断返回给S层
  308. unsafe {
  309. mip::set_ssoft();
  310. mie::clear_msoft();
  311. }
  312. }
  313. Trap::Interrupt(Interrupt::MachineTimer) => {
  314. // 机器时间中断返回给S层
  315. unsafe {
  316. mip::set_stimer();
  317. mie::clear_mtimer();
  318. }
  319. }
  320. Trap::Exception(Exception::IllegalInstruction) => {
  321. #[inline]
  322. unsafe fn get_vaddr_u32(vaddr: usize) -> u32 {
  323. let mut ans: u32;
  324. llvm_asm!("
  325. li t0, (1 << 17)
  326. mv t1, $1
  327. csrrs t0, mstatus, t0
  328. lwu t1, 0(t1)
  329. csrw mstatus, t0
  330. mv $0, t1
  331. "
  332. :"=r"(ans)
  333. :"r"(vaddr)
  334. :"t0", "t1");
  335. ans
  336. }
  337. let vaddr = mepc::read();
  338. let ins = unsafe { get_vaddr_u32(vaddr) };
  339. if ins & 0xFFFFF07F == 0xC0102073 {
  340. // rdtime
  341. let rd = ((ins >> 7) & 0b1_1111) as u8;
  342. // todo: one instance only
  343. let clint = hal::Clint::new(0x2000000 as *mut u8);
  344. let time_usize = clint.get_mtime() as usize;
  345. match rd {
  346. 10 => trap_frame.a0 = time_usize,
  347. 11 => trap_frame.a1 = time_usize,
  348. 12 => trap_frame.a2 = time_usize,
  349. 13 => trap_frame.a3 = time_usize,
  350. 14 => trap_frame.a4 = time_usize,
  351. 15 => trap_frame.a5 = time_usize,
  352. 16 => trap_frame.a6 = time_usize,
  353. 17 => trap_frame.a7 = time_usize,
  354. 5 => trap_frame.t0 = time_usize,
  355. 6 => trap_frame.t1 = time_usize,
  356. 7 => trap_frame.t2 = time_usize,
  357. 28 => trap_frame.t3 = time_usize,
  358. 29 => trap_frame.t4 = time_usize,
  359. 30 => trap_frame.t5 = time_usize,
  360. 31 => trap_frame.t6 = time_usize,
  361. _ => panic!("invalid target"),
  362. }
  363. mepc::write(mepc::read().wrapping_add(4)); // 跳过指令
  364. } else {
  365. #[cfg(target_pointer_width = "64")]
  366. panic!("invalid instruction, mepc: {:016x?}, instruction: {:016x?}", mepc::read(), ins);
  367. #[cfg(target_pointer_width = "32")]
  368. panic!("invalid instruction, mepc: {:08x?}, instruction: {:08x?}", mepc::read(), ins);
  369. }
  370. }
  371. #[cfg(target_pointer_width = "64")]
  372. cause => panic!(
  373. "Unhandled exception! mcause: {:?}, mepc: {:016x?}, mtval: {:016x?}",
  374. cause,
  375. mepc::read(),
  376. mtval::read()
  377. ),
  378. #[cfg(target_pointer_width = "32")]
  379. cause => panic!(
  380. "Unhandled exception! mcause: {:?}, mepc: {:08x?}, mtval: {:08x?}",
  381. cause,
  382. mepc::read(),
  383. mtval::read()
  384. ),
  385. }
  386. }