lib.rs 7.5 KB

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