main.rs 9.9 KB

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