main.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  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::{
  8. arch::{asm, naked_asm},
  9. ptr::null,
  10. };
  11. use riscv::register::cycle;
  12. use sbi_spec::{
  13. binary::{CounterMask, HartMask, SbiRet},
  14. pmu::firmware_event,
  15. };
  16. use sbi_testing::sbi::{self, ConfigFlags, StartFlags, StopFlags};
  17. // use sbi_spec::pmu::*;
  18. use uart16550::Uart16550;
  19. const RISCV_HEAD_FLAGS: u64 = 0;
  20. const RISCV_HEADER_VERSION: u32 = 0x2;
  21. const RISCV_IMAGE_MAGIC: u64 = 0x5643534952; /* Magic number, little endian, "RISCV" */
  22. const RISCV_IMAGE_MAGIC2: u32 = 0x05435352; /* Magic number 2, little endian, "RSC\x05" */
  23. /// boot header
  24. #[naked]
  25. #[unsafe(no_mangle)]
  26. #[unsafe(link_section = ".head.text")]
  27. unsafe extern "C" fn _boot_header() -> ! {
  28. unsafe {
  29. naked_asm!(
  30. "j _start",
  31. ".word 0",
  32. ".balign 8",
  33. ".dword 0x200000",
  34. ".dword iend - istart",
  35. ".dword {RISCV_HEAD_FLAGS}",
  36. ".word {RISCV_HEADER_VERSION}",
  37. ".word 0",
  38. ".dword 0",
  39. ".dword {RISCV_IMAGE_MAGIC}",
  40. ".balign 4",
  41. ".word {RISCV_IMAGE_MAGIC2}",
  42. ".word 0",
  43. RISCV_HEAD_FLAGS = const RISCV_HEAD_FLAGS,
  44. RISCV_HEADER_VERSION = const RISCV_HEADER_VERSION,
  45. RISCV_IMAGE_MAGIC = const RISCV_IMAGE_MAGIC,
  46. RISCV_IMAGE_MAGIC2 = const RISCV_IMAGE_MAGIC2,
  47. );
  48. }
  49. }
  50. /// 内核入口。
  51. ///
  52. /// # Safety
  53. ///
  54. /// 裸函数。
  55. #[naked]
  56. #[unsafe(no_mangle)]
  57. #[unsafe(link_section = ".text.entry")]
  58. unsafe extern "C" fn _start(hartid: usize, device_tree_paddr: usize) -> ! {
  59. const STACK_SIZE: usize = 16384; // 16 KiB
  60. #[unsafe(link_section = ".bss.uninit")]
  61. static mut STACK: [u8; STACK_SIZE] = [0u8; STACK_SIZE];
  62. unsafe {
  63. naked_asm!(
  64. // clear bss segment
  65. " la t0, sbss
  66. la t1, ebss
  67. 1: bgeu t0, t1, 2f
  68. sd zero, 0(t0)
  69. addi t0, t0, 8
  70. j 1b",
  71. "2:",
  72. " la sp, {stack} + {stack_size}",
  73. " j {main}",
  74. stack_size = const STACK_SIZE,
  75. stack = sym STACK,
  76. main = sym rust_main,
  77. )
  78. }
  79. }
  80. extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
  81. let BoardInfo {
  82. smp,
  83. frequency,
  84. uart,
  85. } = BoardInfo::parse(dtb_pa);
  86. unsafe { UART = Uart16550Map(uart as _) };
  87. rcore_console::init_console(&Console);
  88. rcore_console::set_log_level(option_env!("LOG"));
  89. println!(
  90. r"
  91. _____ _ _ __ _
  92. |_ _|__ ___| |_ | |/ /___ _ __ _ __ ___| |
  93. | |/ _ \/ __| __| | ' // _ \ '__| '_ \ / _ \ |
  94. | | __/\__ \ |_ | . \ __/ | | | | | __/ |
  95. |_|\___||___/\__| |_|\_\___|_| |_| |_|\___|_|
  96. ================================================
  97. | boot hart id | {hartid:20} |
  98. | smp | {smp:20} |
  99. | timebase frequency | {frequency:17} Hz |
  100. | dtb physical address | {dtb_pa:#20x} |
  101. ------------------------------------------------"
  102. );
  103. let testing = sbi_testing::Testing {
  104. hartid,
  105. hart_mask: (1 << smp) - 1,
  106. hart_mask_base: 0,
  107. delay: frequency,
  108. };
  109. let test_result = testing.test();
  110. // PMU test, only available in qemu-system-riscv64 single core
  111. let counters_num = sbi::pmu_num_counters();
  112. println!("[pmu] counters number: {}", counters_num);
  113. for idx in 0..counters_num {
  114. let counter_info = sbi::pmu_counter_get_info(idx);
  115. let counter_info = CounterInfo::new(counter_info.value);
  116. if counter_info.is_firmware_counter() {
  117. println!("[pmu] counter index:{:>2}, is a firmware counter", idx);
  118. } else {
  119. println!(
  120. "[pmu] counter index:{:>2}, csr num: {:#03x}, width: {}",
  121. idx,
  122. counter_info.get_csr(),
  123. counter_info.get_width()
  124. );
  125. }
  126. }
  127. /* PMU test for hardware event */
  128. let counter_mask = CounterMask::from_mask_base(0x7ffff, 0);
  129. let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b110), 0x2, 0);
  130. assert!(result.is_ok());
  131. let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b110), 0x10019, 0);
  132. assert!(result.is_ok());
  133. let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b110), 0x1001b, 0);
  134. assert!(result.is_ok());
  135. let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b110), 0x10021, 0);
  136. assert!(result.is_ok());
  137. let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b110), 0x3, 0);
  138. assert_eq!(result, SbiRet::not_supported());
  139. // `SBI_PMU_HW_CPU_CYCLES` event test
  140. let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b010), 0x1, 0);
  141. assert!(result.is_ok());
  142. // the counter index should be 0(mcycle)
  143. assert_eq!(result.value, 0);
  144. let cycle_counter_idx = result.value;
  145. let cycle_num = cycle::read64();
  146. assert_eq!(cycle_num, 0);
  147. // Start counting `SBI_PMU_HW_CPU_CYCLES` events
  148. let start_result = sbi::pmu_counter_start(
  149. CounterMask::from_mask_base(0x1, cycle_counter_idx),
  150. Flag::new(0x1),
  151. 0xffff,
  152. );
  153. assert!(start_result.is_ok());
  154. let cycle_num = cycle::read64();
  155. assert!(cycle_num >= 0xffff);
  156. // Stop counting `SBI_PMU_HW_CPU_CYCLES` events
  157. let stop_result = sbi::pmu_counter_stop(
  158. CounterMask::from_mask_base(0x1, cycle_counter_idx),
  159. Flag::new(0x0),
  160. );
  161. assert!(stop_result.is_ok());
  162. let old_cycle_num = cycle::read64();
  163. let mut _j = 0;
  164. for i in 0..1000 {
  165. _j += i
  166. }
  167. let new_cycle_num = cycle::read64();
  168. assert_eq!(old_cycle_num, new_cycle_num);
  169. // Restart counting `SBI_PMU_HW_CPU_CYCLES` events
  170. let start_result = sbi::pmu_counter_start(
  171. CounterMask::from_mask_base(0x1, cycle_counter_idx),
  172. Flag::new(0x0),
  173. 0,
  174. );
  175. assert!(start_result.is_ok());
  176. let mut _j = 0;
  177. for i in 0..1000 {
  178. _j += i
  179. }
  180. let restart_cycle_num = cycle::read64();
  181. assert!(restart_cycle_num > new_cycle_num);
  182. /* PMU test for firmware event */
  183. let counter_mask = CounterMask::from_mask_base(0x7ffffffff, 0);
  184. // Mapping a counter to the `SBI_PMU_FW_ACCESS_LOAD` event should result in unsupported
  185. let result = sbi::pmu_counter_config_matching(
  186. counter_mask,
  187. Flag::new(0b010),
  188. EventIdx::new_firmware_event(firmware_event::ACCESS_LOAD).raw(),
  189. 0,
  190. );
  191. assert_eq!(result, SbiRet::not_supported());
  192. // Map a counter to the `SBI_PMU_FW_IPI_SENT` event.
  193. // This counter should be a firmware counter and its value should be initialized to 0.
  194. let result = sbi::pmu_counter_config_matching(
  195. counter_mask,
  196. Flag::new(0b010),
  197. EventIdx::new_firmware_event(firmware_event::IPI_SENT).raw(),
  198. 0,
  199. );
  200. assert!(result.is_ok());
  201. assert!(result.value >= 19);
  202. let ipi_counter_idx = result.value;
  203. let ipi_num = sbi::pmu_counter_fw_read(ipi_counter_idx);
  204. assert!(ipi_num.is_ok());
  205. assert_eq!(ipi_num.value, 0);
  206. // Start counting `SBI_PMU_FW_IPI_SENT` events and assign an initial value of 25 to the event counter
  207. let start_result = sbi::pmu_counter_start(
  208. CounterMask::from_mask_base(0x1, ipi_counter_idx),
  209. Flag::new(0x1),
  210. 25,
  211. );
  212. assert!(start_result.is_ok());
  213. // Read the value of the `SBI_PMU_FW_IPI_SENT` event counter, which should be 25
  214. let ipi_num = sbi::pmu_counter_fw_read(ipi_counter_idx);
  215. assert!(ipi_num.is_ok());
  216. assert_eq!(ipi_num.value, 25);
  217. // Send IPI to other core, and the `SBI_PMU_FW_IPI_SENT` event counter value increases by one
  218. let send_ipi_result = sbi::send_ipi(HartMask::from_mask_base(0b10, 0));
  219. assert_eq!(send_ipi_result, SbiRet::invalid_param());
  220. // Read the value of the `SBI_PMU_FW_IPI_SENT` event counter, which should be 26
  221. let ipi_num = sbi::pmu_counter_fw_read(ipi_counter_idx);
  222. assert!(ipi_num.is_ok());
  223. assert_eq!(ipi_num.value, 26);
  224. // Stop counting `SBI_PMU_FW_IPI_SENT` events
  225. let stop_result = sbi::pmu_counter_stop(
  226. CounterMask::from_mask_base(0x1, ipi_counter_idx),
  227. Flag::new(0x0),
  228. );
  229. assert!(stop_result.is_ok());
  230. // Restop counting `SBI_PMU_FW_IPI_SENT` events, the result should be already stop
  231. let stop_result = sbi::pmu_counter_stop(
  232. CounterMask::from_mask_base(0x1, ipi_counter_idx),
  233. Flag::new(0x0),
  234. );
  235. assert_eq!(stop_result, SbiRet::already_stopped());
  236. // Send IPI to other core, `SBI_PMU_FW_IPI_SENT` event counter should not change
  237. let send_ipi_result = sbi::send_ipi(HartMask::from_mask_base(0b10, 0));
  238. assert_eq!(send_ipi_result, SbiRet::invalid_param());
  239. // Read the value of the `SBI_PMU_FW_IPI_SENT` event counter, which should be 26
  240. let ipi_num = sbi::pmu_counter_fw_read(ipi_counter_idx);
  241. assert!(ipi_num.is_ok());
  242. assert_eq!(ipi_num.value, 26);
  243. // Restart counting `SBI_PMU_FW_IPI_SENT` events
  244. let start_result = sbi::pmu_counter_start(
  245. CounterMask::from_mask_base(0x1, ipi_counter_idx),
  246. Flag::new(0x0),
  247. 0,
  248. );
  249. assert!(start_result.is_ok());
  250. // Send IPI to other core, and the `SBI_PMU_FW_IPI_SENT` event counter value increases by one
  251. let send_ipi_result = sbi::send_ipi(HartMask::from_mask_base(0b10, 0));
  252. assert_eq!(send_ipi_result, SbiRet::invalid_param());
  253. // Read the value of the `SBI_PMU_FW_IPI_SENT` event counter, which should be 27
  254. let ipi_num = sbi::pmu_counter_fw_read(ipi_counter_idx);
  255. assert!(ipi_num.is_ok());
  256. assert_eq!(ipi_num.value, 27);
  257. if test_result {
  258. sbi::system_reset(sbi::Shutdown, sbi::NoReason);
  259. } else {
  260. sbi::system_reset(sbi::Shutdown, sbi::SystemFailure);
  261. }
  262. unreachable!()
  263. }
  264. #[cfg_attr(not(test), panic_handler)]
  265. fn panic(info: &core::panic::PanicInfo) -> ! {
  266. let (hart_id, pc): (usize, usize);
  267. unsafe { asm!("mv {}, tp", out(reg) hart_id) };
  268. unsafe { asm!("auipc {}, 0", out(reg) pc) };
  269. println!("[test-kernel-panic] hart {hart_id} {info}");
  270. println!("[test-kernel-panic] pc = {pc:#x}");
  271. println!("[test-kernel-panic] SBI test FAILED due to panic");
  272. sbi::system_reset(sbi::Shutdown, sbi::SystemFailure);
  273. loop {}
  274. }
  275. struct BoardInfo {
  276. smp: usize,
  277. frequency: u64,
  278. uart: usize,
  279. }
  280. impl BoardInfo {
  281. fn parse(dtb_pa: usize) -> Self {
  282. use dtb_walker::{Dtb, DtbObj, HeaderError as E, Property, Str, WalkOperation::*};
  283. let mut ans = Self {
  284. smp: 0,
  285. frequency: 0,
  286. uart: 0,
  287. };
  288. unsafe {
  289. Dtb::from_raw_parts_filtered(dtb_pa as _, |e| {
  290. matches!(e, E::Misaligned(4) | E::LastCompVersion(_))
  291. })
  292. }
  293. .unwrap()
  294. .walk(|ctx, obj| match obj {
  295. DtbObj::SubNode { name } => {
  296. if ctx.is_root() && (name == Str::from("cpus") || name == Str::from("soc")) {
  297. StepInto
  298. } else if ctx.name() == Str::from("cpus") && name.starts_with("cpu@") {
  299. ans.smp += 1;
  300. StepOver
  301. } else if ctx.name() == Str::from("soc")
  302. && (name.starts_with("uart") || name.starts_with("serial"))
  303. {
  304. StepInto
  305. } else {
  306. StepOver
  307. }
  308. }
  309. DtbObj::Property(Property::Reg(mut reg)) => {
  310. if ctx.name().starts_with("uart") || ctx.name().starts_with("serial") {
  311. ans.uart = reg.next().unwrap().start;
  312. }
  313. StepOut
  314. }
  315. DtbObj::Property(Property::General { name, value }) => {
  316. if ctx.name() == Str::from("cpus") && name == Str::from("timebase-frequency") {
  317. ans.frequency = match *value {
  318. [a, b, c, d] => u32::from_be_bytes([a, b, c, d]) as _,
  319. [a, b, c, d, e, f, g, h] => u64::from_be_bytes([a, b, c, d, e, f, g, h]),
  320. _ => unreachable!(),
  321. };
  322. }
  323. StepOver
  324. }
  325. DtbObj::Property(_) => StepOver,
  326. });
  327. ans
  328. }
  329. }
  330. struct Console;
  331. static mut UART: Uart16550Map = Uart16550Map(null());
  332. pub struct Uart16550Map(*const Uart16550<u8>);
  333. unsafe impl Sync for Uart16550Map {}
  334. impl Uart16550Map {
  335. #[inline]
  336. pub fn get(&self) -> &Uart16550<u8> {
  337. unsafe { &*self.0 }
  338. }
  339. }
  340. impl rcore_console::Console for Console {
  341. #[inline]
  342. fn put_char(&self, c: u8) {
  343. unsafe { UART.get().write(core::slice::from_ref(&c)) };
  344. }
  345. #[inline]
  346. fn put_str(&self, s: &str) {
  347. unsafe { UART.get().write(s.as_bytes()) };
  348. }
  349. }
  350. struct Flag {
  351. inner: usize,
  352. }
  353. impl ConfigFlags for Flag {
  354. fn raw(&self) -> usize {
  355. self.inner
  356. }
  357. }
  358. impl StartFlags for Flag {
  359. fn raw(&self) -> usize {
  360. self.inner
  361. }
  362. }
  363. impl StopFlags for Flag {
  364. fn raw(&self) -> usize {
  365. self.inner
  366. }
  367. }
  368. impl Flag {
  369. pub fn new(flag: usize) -> Self {
  370. Self { inner: flag }
  371. }
  372. }
  373. /// Wrap for counter info
  374. struct CounterInfo {
  375. /// Packed representation of counter information:
  376. /// - Bits [11:0]: CSR number for hardware counters
  377. /// - Bits [17:12]: Counter width (typically 63 for RV64)
  378. /// - MSB: Set for firmware counters, clear for hardware counters
  379. inner: usize,
  380. }
  381. #[allow(unused)]
  382. impl CounterInfo {
  383. const CSR_MASK: usize = 0xFFF; // Bits [11:0]
  384. const WIDTH_MASK: usize = 0x3F << 12; // Bits [17:12]
  385. const FIRMWARE_FLAG: usize = 1 << (size_of::<usize>() * 8 - 1); // MSB
  386. #[inline]
  387. pub const fn new(counter_info: usize) -> Self {
  388. Self {
  389. inner: counter_info,
  390. }
  391. }
  392. #[inline]
  393. pub fn set_csr(&mut self, csr_num: u16) {
  394. self.inner = (self.inner & !Self::CSR_MASK) | ((csr_num as usize) & Self::CSR_MASK);
  395. }
  396. #[inline]
  397. pub fn get_csr(&self) -> usize {
  398. self.inner & Self::CSR_MASK
  399. }
  400. #[inline]
  401. pub fn set_width(&mut self, width: u8) {
  402. self.inner = (self.inner & !Self::WIDTH_MASK) | (((width as usize) & 0x3F) << 12);
  403. }
  404. #[inline]
  405. pub fn get_width(&self) -> usize {
  406. (self.inner & Self::WIDTH_MASK) >> 12
  407. }
  408. #[inline]
  409. pub fn is_firmware_counter(&self) -> bool {
  410. self.inner & Self::FIRMWARE_FLAG != 0
  411. }
  412. #[inline]
  413. pub const fn with_hardware_info(csr_num: u16, width: u8) -> Self {
  414. Self {
  415. inner: ((csr_num as usize) & Self::CSR_MASK) | (((width as usize) & 0x3F) << 12),
  416. }
  417. }
  418. #[inline]
  419. pub const fn with_firmware_info() -> Self {
  420. Self {
  421. inner: Self::FIRMWARE_FLAG,
  422. }
  423. }
  424. #[inline]
  425. pub const fn inner(self) -> usize {
  426. self.inner
  427. }
  428. }
  429. struct EventIdx {
  430. inner: usize,
  431. }
  432. impl EventIdx {
  433. fn raw(&self) -> usize {
  434. self.inner
  435. }
  436. fn new_firmware_event(event_code: usize) -> Self {
  437. let inner = 0xf << 16 | event_code;
  438. Self { inner }
  439. }
  440. }