main.rs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #![no_std]
  2. #![no_main]
  3. #![allow(static_mut_refs)]
  4. #[macro_use]
  5. extern crate rcore_console;
  6. use core::mem::MaybeUninit;
  7. use core::sync::{atomic::AtomicBool, atomic::AtomicU64, atomic::Ordering};
  8. use core::{
  9. arch::{asm, naked_asm},
  10. ptr::null,
  11. };
  12. use log::*;
  13. use sbi::SbiRet;
  14. use sbi_spec::binary::{HartMask, MaskError};
  15. use sbi_spec::hsm::hart_state;
  16. use sbi_testing::sbi;
  17. use serde::Deserialize;
  18. use serde_device_tree::{
  19. Dtb, DtbPtr,
  20. buildin::{Node, NodeSeq, Reg, StrSeq},
  21. };
  22. use uart16550::Uart16550;
  23. const RISCV_HEAD_FLAGS: u64 = 0;
  24. const RISCV_HEADER_VERSION: u32 = 0x2;
  25. const RISCV_IMAGE_MAGIC: u64 = 0x5643534952; /* Magic number, little endian, "RISCV" */
  26. const RISCV_IMAGE_MAGIC2: u32 = 0x05435352; /* Magic number 2, little endian, "RSC\x05" */
  27. /// boot header
  28. #[unsafe(naked)]
  29. #[unsafe(no_mangle)]
  30. #[unsafe(link_section = ".head.text")]
  31. unsafe extern "C" fn _boot_header() -> ! {
  32. naked_asm!(
  33. "j _start",
  34. ".word 0",
  35. ".balign 8",
  36. ".dword 0x200000",
  37. ".dword iend - istart",
  38. ".dword {RISCV_HEAD_FLAGS}",
  39. ".word {RISCV_HEADER_VERSION}",
  40. ".word 0",
  41. ".dword 0",
  42. ".dword {RISCV_IMAGE_MAGIC}",
  43. ".balign 4",
  44. ".word {RISCV_IMAGE_MAGIC2}",
  45. ".word 0",
  46. RISCV_HEAD_FLAGS = const RISCV_HEAD_FLAGS,
  47. RISCV_HEADER_VERSION = const RISCV_HEADER_VERSION,
  48. RISCV_IMAGE_MAGIC = const RISCV_IMAGE_MAGIC,
  49. RISCV_IMAGE_MAGIC2 = const RISCV_IMAGE_MAGIC2,
  50. );
  51. }
  52. const STACK_SIZE: usize = 512 * 1024; // 512 KiB
  53. const MAX_HART_NUM: usize = 128;
  54. #[allow(dead_code)]
  55. #[derive(Copy, Clone)]
  56. struct HartStack([u8; STACK_SIZE]);
  57. impl HartStack {
  58. #[inline]
  59. pub const fn new() -> Self {
  60. HartStack([0; STACK_SIZE])
  61. }
  62. }
  63. #[unsafe(link_section = ".bss.uninit")]
  64. static mut STACK: HartStack = HartStack::new();
  65. #[unsafe(link_section = ".bss.uninit")]
  66. static mut HART_STACK: [HartStack; MAX_HART_NUM] = [HartStack::new(); MAX_HART_NUM];
  67. #[unsafe(link_section = ".bss.uninit")]
  68. static mut IPI_SENT: [MaybeUninit<AtomicBool>; MAX_HART_NUM] =
  69. [const { MaybeUninit::uninit() }; MAX_HART_NUM];
  70. #[unsafe(link_section = ".bss.uninit")]
  71. static mut SMP_COUNT: usize = 0;
  72. #[unsafe(link_section = ".bss.uninit")]
  73. static mut BOOT_HART_ID: usize = 0;
  74. /// 内核入口。
  75. ///
  76. /// # Safety
  77. ///
  78. /// 裸函数。
  79. #[unsafe(naked)]
  80. #[unsafe(no_mangle)]
  81. #[unsafe(link_section = ".text.entry")]
  82. unsafe extern "C" fn _start(hartid: usize, device_tree_paddr: usize) -> ! {
  83. naked_asm!(
  84. // clear bss segment
  85. " la t0, sbss
  86. la t1, ebss
  87. 1: bgeu t0, t1, 2f
  88. sd zero, 0(t0)
  89. addi t0, t0, 8
  90. j 1b",
  91. "2:",
  92. " la sp, {stack} + {stack_size}",
  93. " j {main}",
  94. stack_size = const STACK_SIZE,
  95. stack = sym STACK,
  96. main = sym rust_main,
  97. )
  98. }
  99. #[unsafe(naked)]
  100. #[unsafe(no_mangle)]
  101. extern "C" fn init_hart(hartid: usize, opaque: usize) {
  102. naked_asm!(
  103. "add sp, a1, zero",
  104. "csrw sscratch, sp",
  105. "call {init_main}",
  106. init_main = sym init_main,
  107. )
  108. }
  109. #[unsafe(naked)]
  110. #[unsafe(no_mangle)]
  111. extern "C" fn core_send_ipi(hartid: usize, opaque: usize) {
  112. naked_asm!(
  113. "add sp, a1, zero",
  114. "csrw sscratch, sp",
  115. "call {send_ipi}",
  116. send_ipi = sym send_ipi,
  117. )
  118. }
  119. extern "C" fn send_ipi(hartid: usize) -> ! {
  120. if unsafe { !(IPI_SENT[hartid].assume_init_mut().load(Ordering::Relaxed)) } {
  121. unsafe {
  122. IPI_SENT[hartid]
  123. .assume_init_mut()
  124. .swap(true, Ordering::AcqRel);
  125. };
  126. let mut mask = Some(HartMask::from_mask_base(0, 0));
  127. for i in 0..unsafe { SMP_COUNT } {
  128. if i == unsafe { BOOT_HART_ID } {
  129. continue;
  130. }
  131. if let Some(ref mut mask) = mask {
  132. match mask.insert(i) {
  133. Ok(_) => continue,
  134. Err(MaskError::InvalidBit) => {
  135. sbi::remote_sfence_vma(*mask, 0, 0);
  136. }
  137. Err(_) => unreachable!("Failed to construct mask"),
  138. }
  139. }
  140. mask = Some(HartMask::from_mask_base(0b1, i));
  141. }
  142. if let Some(mask) = mask {
  143. sbi::remote_sfence_vma(mask, 0, 0);
  144. }
  145. unsafe {
  146. WAIT_COUNT.fetch_sub(1, Ordering::AcqRel);
  147. while WAIT_COUNT.load(Ordering::Relaxed) != 0 {}
  148. }
  149. } else {
  150. unreachable!("resend {}", hartid);
  151. }
  152. sbi::hart_suspend(sbi::NonRetentive, core_send_ipi as _, unsafe {
  153. core::ptr::addr_of!(HART_STACK[hartid + 1]) as _
  154. });
  155. unreachable!()
  156. }
  157. extern "C" fn init_main(hartid: usize) -> ! {
  158. sbi::hart_suspend(sbi::NonRetentive, core_send_ipi as _, unsafe {
  159. core::ptr::addr_of!(HART_STACK[hartid + 1]) as _
  160. });
  161. unreachable!()
  162. }
  163. static mut WAIT_COUNT: AtomicU64 = AtomicU64::new(0);
  164. const SUSPENDED: SbiRet = SbiRet::success(hart_state::SUSPENDED);
  165. fn get_time() -> u64 {
  166. const CSR_TIME: u32 = 0xc01;
  167. let mut low_time: u64;
  168. unsafe {
  169. asm!("csrr {}, {CSR_TIME}", out(reg) low_time, CSR_TIME = const CSR_TIME);
  170. }
  171. low_time
  172. }
  173. extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
  174. #[derive(Deserialize)]
  175. struct Tree<'a> {
  176. cpus: Cpus<'a>,
  177. chosen: Chosen<'a>,
  178. }
  179. #[derive(Deserialize)]
  180. #[serde(rename_all = "kebab-case")]
  181. struct Cpus<'a> {
  182. timebase_frequency: u32,
  183. cpu: NodeSeq<'a>,
  184. }
  185. #[derive(Deserialize)]
  186. #[serde(rename_all = "kebab-case")]
  187. struct Chosen<'a> {
  188. stdout_path: StrSeq<'a>,
  189. }
  190. rcore_console::init_console(&Console);
  191. rcore_console::set_log_level(option_env!("LOG"));
  192. let dtb_ptr = DtbPtr::from_raw(dtb_pa as _).unwrap();
  193. let dtb = Dtb::from(dtb_ptr).share();
  194. let root: Node = serde_device_tree::from_raw_mut(&dtb).unwrap();
  195. let tree: Tree = root.deserialize();
  196. let stdout_path = tree.chosen.stdout_path.iter().next().unwrap();
  197. if let Some(node) = root.find(stdout_path) {
  198. let reg = node.get_prop("reg").unwrap().deserialize::<Reg>();
  199. let address = reg.iter().next().unwrap().0.start;
  200. unsafe { UART = Uart16550Map(address as _) };
  201. }
  202. let smp = tree.cpus.cpu.len();
  203. let frequency = tree.cpus.timebase_frequency;
  204. info!(
  205. r"
  206. ____ _ _ __ _
  207. | __ ) ___ _ __ ___| |__ | |/ /___ _ __ _ __ ___| |
  208. | _ \ / _ \ '_ \ / __| '_ \ | ' // _ \ '__| '_ \ / _ \ |
  209. | |_) | __/ | | | (__| | | | | . \ __/ | | | | | __/ |
  210. |____/ \___|_| |_|\___|_| |_| |_|\_\___|_| |_| |_|\___|_|
  211. ==========================================================
  212. | boot hart id | {hartid:20} |
  213. | smp | {smp:20} |
  214. | timebase frequency | {frequency:17} Hz |
  215. | dtb physical address | {dtb_pa:#20x} |
  216. ----------------------------------------------------------"
  217. );
  218. unsafe {
  219. SMP_COUNT = smp;
  220. BOOT_HART_ID = hartid;
  221. }
  222. for i in 0..smp {
  223. unsafe {
  224. IPI_SENT[i].write(AtomicBool::new(false));
  225. }
  226. if i != hartid {
  227. sbi::hart_start(i, init_hart as _, unsafe {
  228. core::ptr::addr_of!(HART_STACK[i + 1]) as _
  229. });
  230. while sbi::hart_get_status(i) != SUSPENDED {
  231. core::hint::spin_loop();
  232. }
  233. }
  234. }
  235. info!("Starting test");
  236. for i in 0..4 {
  237. info!("Test #{i} started");
  238. unsafe {
  239. for (i, ipi_sent) in IPI_SENT.iter_mut().enumerate().take(smp) {
  240. ipi_sent.assume_init_mut().swap(false, Ordering::AcqRel);
  241. if i != hartid {
  242. while sbi::hart_get_status(i) != SUSPENDED {}
  243. }
  244. }
  245. WAIT_COUNT.swap((smp - 1) as u64, Ordering::AcqRel);
  246. }
  247. debug!("send ipi!");
  248. let start_time = get_time();
  249. let mut mask = Some(HartMask::from_mask_base(0, 0));
  250. for i in 0..smp {
  251. if i == hartid {
  252. continue;
  253. }
  254. if let Some(ref mut mask) = mask {
  255. match mask.insert(i) {
  256. Ok(_) => continue,
  257. Err(MaskError::InvalidBit) => {
  258. sbi::send_ipi(*mask);
  259. }
  260. Err(_) => unreachable!("Failed to construct mask"),
  261. }
  262. }
  263. mask = Some(HartMask::from_mask_base(0b1, i));
  264. }
  265. if let Some(mask) = mask {
  266. sbi::send_ipi(mask);
  267. }
  268. while unsafe { WAIT_COUNT.load(Ordering::Acquire) } != 0 {}
  269. let end_time = get_time();
  270. println!("Test #{}: {}", i, end_time - start_time);
  271. }
  272. sbi::system_reset(sbi::Shutdown, sbi::NoReason);
  273. unreachable!()
  274. }
  275. #[cfg_attr(not(test), panic_handler)]
  276. fn panic(info: &core::panic::PanicInfo) -> ! {
  277. let (hart_id, pc): (usize, usize);
  278. unsafe { asm!("mv {}, tp", out(reg) hart_id) };
  279. unsafe { asm!("auipc {}, 0", out(reg) pc) };
  280. info!("[test-kernel-panic] hart {hart_id} {info}");
  281. info!("[test-kernel-panic] pc = {pc:#x}");
  282. info!("[test-kernel-panic] SBI test FAILED due to panic");
  283. sbi::system_reset(sbi::Shutdown, sbi::SystemFailure);
  284. loop {}
  285. }
  286. struct Console;
  287. static mut UART: Uart16550Map = Uart16550Map(null());
  288. pub struct Uart16550Map(*const Uart16550<u8>);
  289. unsafe impl Sync for Uart16550Map {}
  290. impl Uart16550Map {
  291. #[inline]
  292. pub fn get(&self) -> &Uart16550<u8> {
  293. unsafe { &*self.0 }
  294. }
  295. }
  296. impl rcore_console::Console for Console {
  297. #[inline]
  298. fn put_char(&self, c: u8) {
  299. unsafe { UART.get().write(core::slice::from_ref(&c)) };
  300. }
  301. #[inline]
  302. fn put_str(&self, s: &str) {
  303. unsafe { UART.get().write(s.as_bytes()) };
  304. }
  305. }