lib.rs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #![no_std]
  2. #![no_main]
  3. #![feature(allocator_api)]
  4. #![feature(c_size_t)]
  5. #![feature(concat_idents)]
  6. #![feature(arbitrary_self_types)]
  7. #![feature(get_mut_unchecked)]
  8. #![feature(macro_metavar_expr)]
  9. extern crate alloc;
  10. #[cfg(any(target_arch = "riscv64", target_arch = "x86_64"))]
  11. extern crate unwinding;
  12. mod driver;
  13. mod fs;
  14. mod hash;
  15. mod io;
  16. mod kernel;
  17. mod kernel_init;
  18. mod net;
  19. #[cfg(any(target_arch = "riscv64", target_arch = "x86_64"))]
  20. mod panic;
  21. mod path;
  22. mod prelude;
  23. mod rcu;
  24. mod sync;
  25. use crate::kernel::task::alloc_pid;
  26. use alloc::{ffi::CString, sync::Arc};
  27. use core::{
  28. hint::spin_loop,
  29. sync::atomic::{AtomicBool, AtomicUsize, Ordering},
  30. };
  31. use eonix_hal::{
  32. arch_exported::bootstrap::shutdown,
  33. context::TaskContext,
  34. processor::{halt, CPU, CPU_COUNT},
  35. traits::{context::RawTaskContext, trap::IrqState},
  36. trap::disable_irqs_save,
  37. };
  38. use eonix_mm::address::PRange;
  39. use eonix_runtime::{executor::Stack, scheduler::RUNTIME};
  40. use kernel::{
  41. mem::GlobalPageAlloc,
  42. task::{KernelStack, ProcessBuilder, ProcessList, ProgramLoader, ThreadBuilder},
  43. vfs::{
  44. dentry::Dentry,
  45. inode::Mode,
  46. mount::{do_mount, MS_NOATIME, MS_NODEV, MS_NOSUID, MS_RDONLY},
  47. FsContext,
  48. },
  49. CharDevice,
  50. };
  51. use kernel_init::setup_memory;
  52. use path::Path;
  53. use prelude::*;
  54. #[cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))]
  55. fn do_panic() -> ! {
  56. #[cfg(target_arch = "riscv64")]
  57. panic::stack_trace();
  58. shutdown();
  59. }
  60. #[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))]
  61. fn do_panic() -> ! {
  62. // Spin forever.
  63. loop {
  64. spin_loop();
  65. }
  66. }
  67. #[panic_handler]
  68. fn panic(info: &core::panic::PanicInfo) -> ! {
  69. if let Some(location) = info.location() {
  70. println_fatal!(
  71. "panicked at {}:{}:{}",
  72. location.file(),
  73. location.line(),
  74. location.column()
  75. );
  76. } else {
  77. println_fatal!("panicked at <UNKNOWN>");
  78. }
  79. println_fatal!();
  80. println_fatal!("{}", info.message());
  81. do_panic()
  82. }
  83. static BSP_OK: AtomicBool = AtomicBool::new(false);
  84. static CPU_SHUTTING_DOWN: AtomicUsize = AtomicUsize::new(0);
  85. fn shutdown_system() -> ! {
  86. let cpu_count = CPU_COUNT.load(Ordering::Relaxed);
  87. if CPU_SHUTTING_DOWN.fetch_add(1, Ordering::AcqRel) + 1 == cpu_count {
  88. println_info!("All CPUs are shutting down. Gracefully powering off...");
  89. shutdown();
  90. } else {
  91. println_info!(
  92. "CPU {} is shutting down. Waiting for other CPUs...",
  93. CPU::local().cpuid()
  94. );
  95. loop {
  96. halt();
  97. }
  98. }
  99. }
  100. #[eonix_hal::main]
  101. fn kernel_init(mut data: eonix_hal::bootstrap::BootStrapData) -> ! {
  102. setup_memory(&mut data);
  103. #[cfg(target_arch = "riscv64")]
  104. {
  105. driver::sbi_console::init_console();
  106. }
  107. BSP_OK.store(true, Ordering::Release);
  108. RUNTIME.spawn(init_process(data.get_early_stack()));
  109. drop(data);
  110. let mut ctx = TaskContext::new();
  111. let stack_bottom = {
  112. let stack = KernelStack::new();
  113. let bottom = stack.get_bottom().addr().get();
  114. core::mem::forget(stack);
  115. bottom
  116. };
  117. ctx.set_interrupt_enabled(true);
  118. ctx.set_program_counter(standard_main as usize);
  119. ctx.set_stack_pointer(stack_bottom);
  120. unsafe {
  121. TaskContext::switch_to_noreturn(&mut ctx);
  122. }
  123. }
  124. #[eonix_hal::ap_main]
  125. fn kernel_ap_main(_stack_range: PRange) -> ! {
  126. while BSP_OK.load(Ordering::Acquire) == false {
  127. // Wait for BSP to finish initializing.
  128. spin_loop();
  129. }
  130. println_debug!("AP{} started", CPU::local().cpuid());
  131. let mut ctx = TaskContext::new();
  132. let stack_bottom = {
  133. let stack = KernelStack::new();
  134. let bottom = stack.get_bottom().addr().get();
  135. core::mem::forget(stack);
  136. bottom
  137. };
  138. ctx.set_interrupt_enabled(true);
  139. ctx.set_program_counter(standard_main as usize);
  140. ctx.set_stack_pointer(stack_bottom);
  141. unsafe {
  142. TaskContext::switch_to_noreturn(&mut ctx);
  143. }
  144. }
  145. fn standard_main() -> ! {
  146. RUNTIME.enter();
  147. shutdown_system();
  148. }
  149. async fn init_process(early_kstack: PRange) {
  150. unsafe {
  151. let irq_ctx = disable_irqs_save();
  152. // SAFETY: IRQ is disabled.
  153. GlobalPageAlloc::add_pages(early_kstack);
  154. irq_ctx.restore();
  155. }
  156. kernel::pcie::init_pcie().expect("Unable to initialize PCIe bus");
  157. CharDevice::init().unwrap();
  158. #[cfg(target_arch = "x86_64")]
  159. {
  160. // We might want the serial initialized as soon as possible.
  161. driver::serial::init().unwrap();
  162. driver::e1000e::register_e1000e_driver();
  163. driver::ahci::register_ahci_driver();
  164. }
  165. #[cfg(target_arch = "riscv64")]
  166. {
  167. driver::serial::init().unwrap();
  168. driver::virtio::init_virtio_devices();
  169. driver::e1000e::register_e1000e_driver();
  170. driver::ahci::register_ahci_driver();
  171. driver::goldfish_rtc::probe();
  172. }
  173. #[cfg(target_arch = "loongarch64")]
  174. {
  175. driver::serial::init().unwrap();
  176. driver::virtio::init_virtio_devices();
  177. driver::e1000e::register_e1000e_driver();
  178. driver::ahci::register_ahci_driver();
  179. }
  180. fs::tmpfs::init();
  181. fs::procfs::init();
  182. fs::fat32::init();
  183. fs::ext4::init();
  184. let load_info = {
  185. // mount fat32 /mnt directory
  186. let fs_context = FsContext::global();
  187. let mnt_dir = Dentry::open(fs_context, Path::new(b"/mnt/").unwrap(), true).unwrap();
  188. mnt_dir.mkdir(Mode::new(0o755)).unwrap();
  189. do_mount(
  190. &mnt_dir,
  191. "/dev/sda",
  192. "/mnt",
  193. "fat32",
  194. MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID,
  195. )
  196. .unwrap();
  197. let init_names = [&b"/init"[..], &b"/sbin/init"[..], &b"/mnt/initsh"[..]];
  198. let mut init_name = None;
  199. let mut init = None;
  200. for name in init_names {
  201. if let Ok(dentry) = Dentry::open(fs_context, Path::new(name).unwrap(), true) {
  202. if dentry.is_valid() {
  203. init_name = Some(CString::new(name).unwrap());
  204. init = Some(dentry);
  205. break;
  206. }
  207. }
  208. }
  209. let init = init.expect("No init binary found in the system.");
  210. let init_name = init_name.unwrap();
  211. let argv = vec![init_name.clone()];
  212. let envp = vec![
  213. CString::new("LANG=C").unwrap(),
  214. CString::new("HOME=/root").unwrap(),
  215. CString::new("PATH=/mnt").unwrap(),
  216. CString::new("PWD=/").unwrap(),
  217. ];
  218. ProgramLoader::parse(fs_context, init_name, init.clone(), argv, envp)
  219. .expect("Failed to parse init program")
  220. .load()
  221. .await
  222. .expect("Failed to load init program")
  223. };
  224. let thread_builder = ThreadBuilder::new()
  225. .name(Arc::from(&b"busybox"[..]))
  226. .entry(load_info.entry_ip, load_info.sp);
  227. let mut process_list = ProcessList::get().write().await;
  228. let (thread, process) = ProcessBuilder::new()
  229. .pid(alloc_pid())
  230. .mm_list(load_info.mm_list)
  231. .thread_builder(thread_builder)
  232. .build(&mut process_list);
  233. process_list.set_init_process(process);
  234. // TODO!!!: Remove this.
  235. thread.files.open_console();
  236. RUNTIME.spawn(thread.run());
  237. }