board.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. use aclint::SifiveClint;
  2. use core::{
  3. cell::RefCell,
  4. fmt::{Display, Formatter, Result},
  5. ops::Range,
  6. sync::atomic::{AtomicBool, AtomicPtr, Ordering},
  7. };
  8. use serde_device_tree::Dtb;
  9. use sifive_test_device::SifiveTestDevice;
  10. use spin::Mutex;
  11. use uart16550::Uart16550;
  12. use uart_xilinx::uart_lite::uart::MmioUartAxiLite;
  13. use crate::fail;
  14. use crate::sbi::console::{ConsoleDevice, SbiConsole};
  15. use crate::sbi::extensions;
  16. use crate::sbi::hsm::SbiHsm;
  17. use crate::sbi::ipi::{IpiDevice, SbiIpi};
  18. use crate::sbi::logger;
  19. use crate::sbi::reset::{ResetDevice, SbiReset};
  20. use crate::sbi::trap_stack;
  21. use crate::sbi::trap_stack::NUM_HART_MAX;
  22. use crate::sbi::SBI;
  23. use crate::{dt, sbi::rfence::SbiRFence};
  24. pub(crate) const UART16650U8_COMPATIBLE: [&str; 1] = ["ns16550a"];
  25. pub(crate) const UART16650U32_COMPATIBLE: [&str; 1] = ["snps,dw-apb-uart"];
  26. pub(crate) const UARTAXILITE_COMPATIBLE: [&str; 1] = ["xlnx,xps-uartlite-1.00.a"];
  27. pub(crate) const SIFIVETEST_COMPATIBLE: [&str; 1] = ["sifive,test0"];
  28. pub(crate) const SIFIVECLINT_COMPATIBLE: [&str; 1] = ["riscv,clint0"];
  29. type BaseAddress = usize;
  30. /// Store finite-length string on the stack.
  31. pub(crate) struct StringInline<const N: usize>(usize, [u8; N]);
  32. impl<const N: usize> Display for StringInline<N> {
  33. fn fmt(&self, f: &mut Formatter<'_>) -> Result {
  34. write!(f, "{}", unsafe {
  35. core::str::from_utf8_unchecked(&self.1[..self.0])
  36. })
  37. }
  38. }
  39. type CpuEnableList = [bool; trap_stack::NUM_HART_MAX];
  40. pub struct BoardInfo {
  41. pub memory_range: Option<Range<usize>>,
  42. pub console: Option<(BaseAddress, MachineConsoleType)>,
  43. pub reset: Option<BaseAddress>,
  44. pub ipi: Option<BaseAddress>,
  45. pub cpu_num: Option<usize>,
  46. pub cpu_enabled: Option<CpuEnableList>,
  47. pub model: StringInline<128>,
  48. }
  49. impl BoardInfo {
  50. pub const fn new() -> Self {
  51. BoardInfo {
  52. memory_range: None,
  53. console: None,
  54. reset: None,
  55. ipi: None,
  56. cpu_enabled: None,
  57. cpu_num: None,
  58. model: StringInline(0, [0u8; 128]),
  59. }
  60. }
  61. }
  62. pub struct Board {
  63. pub info: BoardInfo,
  64. pub sbi: SBI<MachineConsole, SifiveClint, SifiveTestDevice>,
  65. pub ready: AtomicBool,
  66. }
  67. #[allow(unused)]
  68. impl Board {
  69. pub const fn new() -> Self {
  70. Board {
  71. info: BoardInfo::new(),
  72. sbi: SBI::new(),
  73. ready: AtomicBool::new(false),
  74. }
  75. }
  76. pub fn init(&mut self, dtb: &RefCell<Dtb>) {
  77. self.info_init(dtb);
  78. self.sbi_init();
  79. logger::Logger::init().unwrap();
  80. trap_stack::prepare_for_trap();
  81. self.ready.swap(true, Ordering::Release);
  82. }
  83. pub fn have_console(&self) -> bool {
  84. self.sbi.console.is_some()
  85. }
  86. pub fn have_reset(&self) -> bool {
  87. self.sbi.reset.is_some()
  88. }
  89. pub fn have_ipi(&self) -> bool {
  90. self.sbi.ipi.is_some()
  91. }
  92. pub fn have_hsm(&self) -> bool {
  93. self.sbi.hsm.is_some()
  94. }
  95. pub fn have_rfence(&self) -> bool {
  96. self.sbi.rfence.is_some()
  97. }
  98. pub fn ready(&self) -> bool {
  99. self.ready.load(Ordering::Acquire)
  100. }
  101. pub fn print_board_info(&self) {
  102. info!("RustSBI version {}", rustsbi::VERSION);
  103. rustsbi::LOGO.lines().for_each(|line| info!("{}", line));
  104. info!("Initializing RustSBI machine-mode environment.");
  105. info!("Number of CPU: {:?}", self.info.cpu_num);
  106. info!("Enabled hart: {:?}", self.info.cpu_enabled);
  107. info!("Model: {}", self.info.model);
  108. info!("Clint device: {:x?}", self.info.ipi);
  109. info!("Console device: {:x?}", self.info.console);
  110. }
  111. fn info_init(&mut self, dtb: &RefCell<Dtb>) {
  112. let root: serde_device_tree::buildin::Node = serde_device_tree::from_raw_mut(&dtb)
  113. .unwrap_or_else(fail::device_tree_deserialize_root);
  114. let tree: dt::Tree = root.deserialize();
  115. // Get console device info
  116. for console_path in tree.chosen.stdout_path.iter() {
  117. if let Some(node) = root.find(console_path) {
  118. let info = dt::get_compatible_and_range(&node);
  119. let result = info.is_some_and(|info| {
  120. let (compatible, regs) = info;
  121. for device_id in compatible.iter() {
  122. if UART16650U8_COMPATIBLE.contains(&device_id) {
  123. self.info.console = Some((regs.start, MachineConsoleType::Uart16550U8));
  124. return true;
  125. }
  126. if UART16650U32_COMPATIBLE.contains(&device_id) {
  127. self.info.console = Some((regs.start, MachineConsoleType::Uart16550U32));
  128. return true;
  129. }
  130. if UARTAXILITE_COMPATIBLE.contains(&device_id) {
  131. self.info.console = Some((regs.start, MachineConsoleType::UartAxiLite));
  132. return true;
  133. }
  134. }
  135. false
  136. });
  137. if result {
  138. break;
  139. }
  140. }
  141. }
  142. // Get ipi and reset device info
  143. let mut find_device = |node: &serde_device_tree::buildin::Node| {
  144. let info = dt::get_compatible_and_range(node);
  145. if let Some(info) = info {
  146. let (compatible, regs) = info;
  147. let base_address = regs.start;
  148. for device_id in compatible.iter() {
  149. // Initialize clint device.
  150. if SIFIVECLINT_COMPATIBLE.contains(&device_id) {
  151. self.info.ipi = Some(base_address);
  152. }
  153. // Initialize reset device.
  154. if SIFIVETEST_COMPATIBLE.contains(&device_id) {
  155. self.info.reset = Some(base_address);
  156. }
  157. }
  158. }
  159. };
  160. root.search(&mut find_device);
  161. // Get memory info
  162. // TODO: More than one memory node or range?
  163. let memory_reg = tree
  164. .memory
  165. .iter()
  166. .next()
  167. .unwrap()
  168. .deserialize::<dt::Memory>()
  169. .reg;
  170. let memory_range = memory_reg.iter().next().unwrap().0;
  171. self.info.memory_range = Some(memory_range);
  172. // Get cpu number info
  173. self.info.cpu_num = Some(tree.cpus.cpu.len());
  174. // Get model info
  175. if let Some(model) = tree.model {
  176. let model = model.iter().next().unwrap_or("<unspecified>");
  177. self.info.model.0 = model.as_bytes().len();
  178. self.info.model.1[..self.info.model.0].copy_from_slice(model.as_bytes());
  179. } else {
  180. let model = "<unspecified>";
  181. self.info.model.0 = model.as_bytes().len();
  182. self.info.model.1[..self.info.model.0].copy_from_slice(model.as_bytes());
  183. }
  184. // TODO: Need a better extension initialization method
  185. extensions::init(&tree.cpus.cpu);
  186. // Find which hart is enabled by fdt
  187. let mut cpu_list: CpuEnableList = [false; trap_stack::NUM_HART_MAX];
  188. for cpu_iter in tree.cpus.cpu.iter() {
  189. use dt::Cpu;
  190. let cpu = cpu_iter.deserialize::<Cpu>();
  191. let hart_id = cpu.reg.iter().next().unwrap().0.start;
  192. cpu_list.get_mut(hart_id).map(|x| *x = true);
  193. }
  194. self.info.cpu_enabled = Some(cpu_list);
  195. }
  196. fn sbi_init(&mut self) {
  197. self.sbi_console_init();
  198. self.sbi_ipi_init();
  199. self.sbi_hsm_init();
  200. self.sbi_reset_init();
  201. self.sbi_rfence_init();
  202. }
  203. fn sbi_console_init(&mut self) {
  204. if let Some((base, console_type)) = self.info.console {
  205. let new_console = match console_type {
  206. MachineConsoleType::Uart16550U8 => MachineConsole::Uart16550U8(base as _),
  207. MachineConsoleType::Uart16550U32 => MachineConsole::Uart16550U32(base as _),
  208. MachineConsoleType::UartAxiLite => {
  209. MachineConsole::UartAxiLite(MmioUartAxiLite::new(base))
  210. }
  211. };
  212. self.sbi.console = Some(SbiConsole::new(Mutex::new(new_console)));
  213. } else {
  214. self.sbi.console = None;
  215. }
  216. }
  217. fn sbi_reset_init(&mut self) {
  218. if let Some(base) = self.info.reset {
  219. self.sbi.reset = Some(SbiReset::new(AtomicPtr::new(base as _)));
  220. } else {
  221. self.sbi.reset = None;
  222. }
  223. }
  224. fn sbi_ipi_init(&mut self) {
  225. if let Some(base) = self.info.ipi {
  226. self.sbi.ipi = Some(SbiIpi::new(
  227. AtomicPtr::new(base as _),
  228. self.info.cpu_num.unwrap_or(NUM_HART_MAX),
  229. ));
  230. } else {
  231. self.sbi.ipi = None;
  232. }
  233. }
  234. fn sbi_hsm_init(&mut self) {
  235. // TODO: Can HSM work properly when there is no ipi device?
  236. if self.info.ipi.is_some() {
  237. self.sbi.hsm = Some(SbiHsm);
  238. } else {
  239. self.sbi.hsm = None;
  240. }
  241. }
  242. fn sbi_rfence_init(&mut self) {
  243. // TODO: Can rfence work properly when there is no ipi device?
  244. if self.info.ipi.is_some() {
  245. self.sbi.rfence = Some(SbiRFence);
  246. } else {
  247. self.sbi.rfence = None;
  248. }
  249. }
  250. }
  251. pub(crate) static mut BOARD: Board = Board::new();
  252. /// Console Device: Uart16550
  253. #[doc(hidden)]
  254. #[allow(unused)]
  255. #[derive(Clone, Copy, Debug)]
  256. pub enum MachineConsoleType {
  257. Uart16550U8,
  258. Uart16550U32,
  259. UartAxiLite,
  260. }
  261. #[doc(hidden)]
  262. #[allow(unused)]
  263. pub enum MachineConsole {
  264. Uart16550U8(*const Uart16550<u8>),
  265. Uart16550U32(*const Uart16550<u32>),
  266. UartAxiLite(MmioUartAxiLite),
  267. }
  268. unsafe impl Send for MachineConsole {}
  269. unsafe impl Sync for MachineConsole {}
  270. impl ConsoleDevice for MachineConsole {
  271. fn read(&self, buf: &mut [u8]) -> usize {
  272. match self {
  273. Self::Uart16550U8(uart16550) => unsafe { (**uart16550).read(buf) },
  274. Self::Uart16550U32(uart16550) => unsafe { (**uart16550).read(buf) },
  275. Self::UartAxiLite(axilite) => axilite.read(buf),
  276. }
  277. }
  278. fn write(&self, buf: &[u8]) -> usize {
  279. match self {
  280. MachineConsole::Uart16550U8(uart16550) => unsafe { (**uart16550).write(buf) },
  281. MachineConsole::Uart16550U32(uart16550) => unsafe { (**uart16550).write(buf) },
  282. Self::UartAxiLite(axilite) => axilite.write(buf),
  283. }
  284. }
  285. }
  286. /// Ipi Device: Sifive Clint
  287. impl IpiDevice for SifiveClint {
  288. #[inline(always)]
  289. fn read_mtime(&self) -> u64 {
  290. self.read_mtime()
  291. }
  292. #[inline(always)]
  293. fn write_mtime(&self, val: u64) {
  294. self.write_mtime(val)
  295. }
  296. #[inline(always)]
  297. fn read_mtimecmp(&self, hart_idx: usize) -> u64 {
  298. self.read_mtimecmp(hart_idx)
  299. }
  300. #[inline(always)]
  301. fn write_mtimecmp(&self, hart_idx: usize, val: u64) {
  302. self.write_mtimecmp(hart_idx, val)
  303. }
  304. #[inline(always)]
  305. fn read_msip(&self, hart_idx: usize) -> bool {
  306. self.read_msip(hart_idx)
  307. }
  308. #[inline(always)]
  309. fn set_msip(&self, hart_idx: usize) {
  310. self.set_msip(hart_idx)
  311. }
  312. #[inline(always)]
  313. fn clear_msip(&self, hart_idx: usize) {
  314. self.clear_msip(hart_idx)
  315. }
  316. }
  317. /// Reset Device: SifiveTestDevice
  318. impl ResetDevice for SifiveTestDevice {
  319. #[inline]
  320. fn fail(&self, code: u16) -> ! {
  321. self.fail(code)
  322. }
  323. #[inline]
  324. fn pass(&self) -> ! {
  325. self.pass()
  326. }
  327. #[inline]
  328. fn reset(&self) -> ! {
  329. self.reset()
  330. }
  331. }