main.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. #![no_std]
  2. #![no_main]
  3. #![feature(alloc_error_handler)]
  4. #![feature(global_asm)]
  5. #![feature(llvm_asm)]
  6. use core::alloc::Layout;
  7. use core::panic::PanicInfo;
  8. use k210_hal::{clock::Clocks, fpioa, pac, prelude::*};
  9. use linked_list_allocator::LockedHeap;
  10. use rustsbi::{enter_privileged, print, println};
  11. use riscv::register::{
  12. mcause::{self, Exception, Interrupt, Trap},
  13. medeleg, mepc, mhartid, mideleg, mie, mip, misa::{self, MXL},
  14. mstatus::{self, MPP},
  15. mtval,
  16. mtvec::{self, TrapMode},
  17. };
  18. #[global_allocator]
  19. static ALLOCATOR: LockedHeap = LockedHeap::empty();
  20. #[panic_handler]
  21. fn panic(_info: &PanicInfo) -> ! {
  22. loop {}
  23. }
  24. #[alloc_error_handler]
  25. fn oom(_layout: Layout) -> ! {
  26. loop {}
  27. }
  28. fn mp_hook() -> bool {
  29. use riscv::asm::wfi;
  30. use k210_hal::clint::msip;
  31. let hartid = mhartid::read();
  32. if hartid == 0 {
  33. true
  34. } else {
  35. unsafe {
  36. // Clear IPI
  37. msip::clear_ipi(hartid);
  38. // Start listening for software interrupts
  39. mie::set_msoft();
  40. loop {
  41. wfi();
  42. if mip::read().msoft() {
  43. break;
  44. }
  45. }
  46. // Stop listening for software interrupts
  47. mie::clear_msoft();
  48. // Clear IPI
  49. msip::clear_ipi(hartid);
  50. }
  51. false
  52. }
  53. }
  54. #[export_name = "_start"]
  55. #[link_section = ".text.entry"] // this is stable
  56. fn main() -> ! {
  57. unsafe {
  58. llvm_asm!(
  59. "
  60. csrr a2, mhartid
  61. lui t0, %hi(_max_hart_id)
  62. add t0, t0, %lo(_max_hart_id)
  63. bgtu a2, t0, _start_abort
  64. la sp, _stack_start
  65. lui t0, %hi(_hart_stack_size)
  66. add t0, t0, %lo(_hart_stack_size)
  67. .ifdef __riscv_mul
  68. mul t0, a2, t0
  69. .else
  70. beqz a2, 2f // Jump if single-hart
  71. mv t1, a2
  72. mv t2, t0
  73. 1:
  74. add t0, t0, t2
  75. addi t1, t1, -1
  76. bnez t1, 1b
  77. 2:
  78. .endif
  79. sub sp, sp, t0
  80. csrw mscratch, zero
  81. j _start_success
  82. _start_abort:
  83. wfi
  84. j _start_abort
  85. _start_success:
  86. "
  87. )
  88. };
  89. if mp_hook() {
  90. extern "C" {
  91. static mut _ebss: u32;
  92. static mut _sbss: u32;
  93. static mut _edata: u32;
  94. static mut _sdata: u32;
  95. static _sidata: u32;
  96. }
  97. unsafe {
  98. r0::zero_bss(&mut _sbss, &mut _ebss);
  99. r0::init_data(&mut _sdata, &mut _edata, &_sidata);
  100. }
  101. }
  102. extern "C" {
  103. fn _start_trap();
  104. }
  105. unsafe {
  106. mtvec::write(_start_trap as usize, TrapMode::Direct);
  107. }
  108. if mhartid::read() == 0 {
  109. extern "C" {
  110. fn _sheap();
  111. fn _heap_size();
  112. }
  113. let sheap = &mut _sheap as *mut _ as usize;
  114. let heap_size = &_heap_size as *const _ as usize;
  115. unsafe {
  116. ALLOCATOR.lock().init(sheap, heap_size);
  117. }
  118. let p = pac::Peripherals::take().unwrap();
  119. let mut sysctl = p.SYSCTL.constrain();
  120. let fpioa = p.FPIOA.split(&mut sysctl.apb0);
  121. let clocks = Clocks::new();
  122. let _uarths_tx = fpioa.io5.into_function(fpioa::UARTHS_TX);
  123. let _uarths_rx = fpioa.io4.into_function(fpioa::UARTHS_RX);
  124. // Configure UART
  125. let serial = p.UARTHS.configure(115_200.bps(), &clocks);
  126. let (tx, rx) = serial.split();
  127. use rustsbi::legacy_stdio::init_legacy_stdio_embedded_hal_fuse;
  128. init_legacy_stdio_embedded_hal_fuse(tx, rx);
  129. struct Ipi;
  130. impl rustsbi::Ipi for Ipi {
  131. fn max_hart_id(&self) -> usize {
  132. 1
  133. }
  134. fn send_ipi_many(&mut self, hart_mask: rustsbi::HartMask) {
  135. use k210_hal::clint::msip;
  136. for i in 0..=1 {
  137. if hart_mask.has_bit(i) {
  138. msip::set_ipi(i);
  139. msip::clear_ipi(i);
  140. }
  141. }
  142. }
  143. }
  144. use rustsbi::init_ipi;
  145. init_ipi(Ipi);
  146. struct Timer;
  147. impl rustsbi::Timer for Timer {
  148. fn set_timer(&mut self, stime_value: u64) {
  149. // This function must clear the pending timer interrupt bit as well.
  150. use k210_hal::clint::mtimecmp;
  151. mtimecmp::write(mhartid::read(), stime_value);
  152. unsafe { mip::clear_mtimer() };
  153. }
  154. }
  155. use rustsbi::init_timer;
  156. init_timer(Timer);
  157. }
  158. unsafe {
  159. mideleg::set_sext();
  160. mideleg::set_stimer();
  161. mideleg::set_ssoft();
  162. medeleg::set_instruction_misaligned();
  163. medeleg::set_breakpoint();
  164. medeleg::set_user_env_call();
  165. medeleg::set_instruction_page_fault();
  166. medeleg::set_load_page_fault();
  167. medeleg::set_store_page_fault();
  168. mie::set_mext();
  169. // 不打开mie::set_mtimer
  170. mie::set_msoft();
  171. }
  172. if mhartid::read() == 0 {
  173. println!("[rustsbi] Version 0.1.0");
  174. println!("{}", rustsbi::LOGO);
  175. println!("[rustsbi] Platform: K210");
  176. let isa = misa::read();
  177. if let Some(isa) = isa {
  178. let mxl_str = match isa.mxl() {
  179. MXL::XLEN32 => "RV32",
  180. MXL::XLEN64 => "RV64",
  181. MXL::XLEN128 => "RV128",
  182. };
  183. print!("[rustsbi] misa: {}", mxl_str);
  184. for ext in 'A'..='Z' {
  185. if isa.has_extension(ext) {
  186. print!("{}", ext);
  187. }
  188. }
  189. println!("");
  190. }
  191. println!("[rustsbi] mideleg: {:#x}", mideleg::read().bits());
  192. println!("[rustsbi] medeleg: {:#x}", medeleg::read().bits());
  193. println!("[rustsbi] Kernel entry: 0x80020000");
  194. }
  195. extern "C" {
  196. fn _s_mode_start();
  197. }
  198. unsafe {
  199. mepc::write(_s_mode_start as usize);
  200. mstatus::set_mpp(MPP::Supervisor);
  201. enter_privileged(mhartid::read(), 0x2333333366666666);
  202. }
  203. }
  204. global_asm!(
  205. "
  206. .section .text
  207. .globl _s_mode_start
  208. _s_mode_start:
  209. 1: auipc ra, %pcrel_hi(1f)
  210. ld ra, %pcrel_lo(1b)(ra)
  211. jr ra
  212. .align 3
  213. 1: .dword 0x80020000
  214. "
  215. );
  216. // todo: configurable target address
  217. global_asm!(
  218. "
  219. .equ REGBYTES, 8
  220. .macro STORE reg, offset
  221. sd \\reg, \\offset*REGBYTES(sp)
  222. .endm
  223. .macro LOAD reg, offset
  224. ld \\reg, \\offset*REGBYTES(sp)
  225. .endm
  226. .section .text
  227. .global _start_trap
  228. .p2align 2
  229. _start_trap:
  230. csrrw sp, mscratch, sp
  231. bnez sp, 1f
  232. /* from M level, load sp */
  233. csrrw sp, mscratch, zero
  234. 1:
  235. addi sp, sp, -16 * REGBYTES
  236. STORE ra, 0
  237. STORE t0, 1
  238. STORE t1, 2
  239. STORE t2, 3
  240. STORE t3, 4
  241. STORE t4, 5
  242. STORE t5, 6
  243. STORE t6, 7
  244. STORE a0, 8
  245. STORE a1, 9
  246. STORE a2, 10
  247. STORE a3, 11
  248. STORE a4, 12
  249. STORE a5, 13
  250. STORE a6, 14
  251. STORE a7, 15
  252. mv a0, sp
  253. call _start_trap_rust
  254. LOAD ra, 0
  255. LOAD t0, 1
  256. LOAD t1, 2
  257. LOAD t2, 3
  258. LOAD t3, 4
  259. LOAD t4, 5
  260. LOAD t5, 6
  261. LOAD t6, 7
  262. LOAD a0, 8
  263. LOAD a1, 9
  264. LOAD a2, 10
  265. LOAD a3, 11
  266. LOAD a4, 12
  267. LOAD a5, 13
  268. LOAD a6, 14
  269. LOAD a7, 15
  270. addi sp, sp, 16 * REGBYTES
  271. csrrw sp, mscratch, sp
  272. mret
  273. "
  274. );
  275. #[allow(unused)]
  276. struct TrapFrame {
  277. ra: usize,
  278. t0: usize,
  279. t1: usize,
  280. t2: usize,
  281. t3: usize,
  282. t4: usize,
  283. t5: usize,
  284. t6: usize,
  285. a0: usize,
  286. a1: usize,
  287. a2: usize,
  288. a3: usize,
  289. a4: usize,
  290. a5: usize,
  291. a6: usize,
  292. a7: usize,
  293. }
  294. #[export_name = "_start_trap_rust"]
  295. extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
  296. let cause = mcause::read().cause();
  297. match cause {
  298. Trap::Exception(Exception::SupervisorEnvCall) => {
  299. let params = [trap_frame.a0, trap_frame.a1, trap_frame.a2, trap_frame.a3];
  300. let ans = rustsbi::ecall(trap_frame.a7, trap_frame.a6, params);
  301. trap_frame.a0 = ans.error;
  302. trap_frame.a1 = ans.value;
  303. mepc::write(mepc::read().wrapping_add(4));
  304. }
  305. Trap::Interrupt(Interrupt::MachineSoft) => {
  306. unsafe {
  307. mip::set_ssoft();
  308. mie::clear_msoft();
  309. }
  310. }
  311. Trap::Interrupt(Interrupt::MachineTimer) => {
  312. unsafe {
  313. mip::set_stimer();
  314. mie::clear_mtimer();
  315. }
  316. }
  317. Trap::Exception(Exception::IllegalInstruction) => {
  318. let vaddr = mepc::read();
  319. let ins = unsafe { get_vaddr_u32(vaddr) };
  320. if ins & 0xFFFFF07F == 0xC0102073 { // rdtime instruction
  321. // rdtime is actually a csrrw instruction
  322. let rd = ((ins >> 7) & 0b1_1111) as u8;
  323. let mtime = k210_hal::clint::mtime::read();
  324. let time_usize = mtime as usize;
  325. set_rd(trap_frame, rd, time_usize);
  326. mepc::write(mepc::read().wrapping_add(4)); // skip current instruction
  327. } else if ins & 0xFE007FFF == 0x12000073 { // sfence.vma instruction
  328. // sfence.vma: | 31..25 funct7=SFENCE.VMA(0001001) | 24..20 rs2/asid | 19..15 rs1/vaddr |
  329. // 14..12 funct3=PRIV(000) | 11..7 rd, =0 | 6..0 opcode=SYSTEM(1110011) |
  330. // sfence.vm(1.9): | 31..=20 SFENCE.VM(000100000100) | 19..15 rs1/vaddr |
  331. // 14..12 funct3=PRIV(000) | 11..7 rd, =0 | 6..0 opcode=SYSTEM(1110011) |
  332. // discard rs2 // let _rs2_asid = ((ins >> 20) & 0b1_1111) as u8;
  333. // let rs1_vaddr = ((ins >> 15) & 0b1_1111) as u8;
  334. // emulate with sfence.vm (declared in privileged spec v1.9)
  335. unsafe { llvm_asm!(".word 0x10400073") }; // sfence.vm x0
  336. // ::"r"(rs1_vaddr)
  337. mepc::write(mepc::read().wrapping_add(4)); // skip current instruction
  338. } else {
  339. panic!("invalid instruction, mepc: {:016x?}, instruction: {:016x?}", mepc::read(), ins);
  340. }
  341. }
  342. cause => panic!(
  343. "Unhandled exception! mcause: {:?}, mepc: {:016x?}, mtval: {:016x?}",
  344. cause,
  345. mepc::read(),
  346. mtval::read()
  347. ),
  348. }
  349. }
  350. #[inline]
  351. unsafe fn get_vaddr_u32(vaddr: usize) -> u32 {
  352. let mut ans: u32;
  353. llvm_asm!("
  354. li t0, (1 << 17)
  355. mv t1, $1
  356. csrrs t0, mstatus, t0
  357. lwu t1, 0(t1)
  358. csrw mstatus, t0
  359. mv $0, t1
  360. "
  361. :"=r"(ans)
  362. :"r"(vaddr)
  363. :"t0", "t1");
  364. ans
  365. }
  366. #[inline]
  367. fn set_rd(trap_frame: &mut TrapFrame, rd: u8, value: usize) {
  368. match rd {
  369. 10 => trap_frame.a0 = value,
  370. 11 => trap_frame.a1 = value,
  371. 12 => trap_frame.a2 = value,
  372. 13 => trap_frame.a3 = value,
  373. 14 => trap_frame.a4 = value,
  374. 15 => trap_frame.a5 = value,
  375. 16 => trap_frame.a6 = value,
  376. 17 => trap_frame.a7 = value,
  377. 5 => trap_frame.t0 = value,
  378. 6 => trap_frame.t1 = value,
  379. 7 => trap_frame.t2 = value,
  380. 28 => trap_frame.t3 = value,
  381. 29 => trap_frame.t4 = value,
  382. 30 => trap_frame.t5 = value,
  383. 31 => trap_frame.t6 = value,
  384. _ => panic!("invalid target `rd`"),
  385. }
  386. }