lib.rs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #![no_std]
  2. #![no_main]
  3. #![feature(c_size_t)]
  4. #![feature(concat_idents)]
  5. #![feature(arbitrary_self_types)]
  6. #![feature(get_mut_unchecked)]
  7. #![feature(macro_metavar_expr)]
  8. extern crate alloc;
  9. #[allow(warnings)]
  10. mod bindings;
  11. mod driver;
  12. mod elf;
  13. mod fs;
  14. mod hash;
  15. mod io;
  16. mod kernel;
  17. mod net;
  18. mod path;
  19. mod prelude;
  20. mod rcu;
  21. mod sync;
  22. use alloc::ffi::CString;
  23. use arch::task::rdmsr;
  24. use core::{
  25. alloc::{GlobalAlloc, Layout},
  26. arch::{asm, global_asm},
  27. sync::atomic::AtomicU32,
  28. };
  29. use elf::ParsedElf32;
  30. use kernel::{
  31. mem::{
  32. paging::Page,
  33. phys::{CachedPP, PhysPtr as _},
  34. },
  35. task::{init_multitasking, Scheduler, Thread},
  36. vfs::{
  37. dentry::Dentry,
  38. mount::{do_mount, MS_NOATIME, MS_NODEV, MS_NOSUID, MS_RDONLY},
  39. FsContext,
  40. },
  41. CharDevice,
  42. };
  43. use path::Path;
  44. use prelude::*;
  45. use sync::preempt;
  46. #[panic_handler]
  47. fn panic(info: &core::panic::PanicInfo) -> ! {
  48. if let Some(location) = info.location() {
  49. println_fatal!(
  50. "panicked at {}:{}:{}",
  51. location.file(),
  52. location.line(),
  53. location.column()
  54. );
  55. } else {
  56. println_fatal!("panicked at <UNKNOWN>");
  57. }
  58. println_fatal!();
  59. println_fatal!("{}", info.message());
  60. arch::task::freeze()
  61. }
  62. extern "C" {
  63. fn _do_allocate(size: usize) -> *mut core::ffi::c_void;
  64. fn _do_deallocate(ptr: *mut core::ffi::c_void, size: core::ffi::c_size_t) -> i32;
  65. fn init_pci();
  66. }
  67. struct Allocator {}
  68. unsafe impl GlobalAlloc for Allocator {
  69. unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
  70. let result = _do_allocate(layout.size());
  71. if result.is_null() {
  72. core::ptr::null_mut()
  73. } else {
  74. result as *mut u8
  75. }
  76. }
  77. unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
  78. match _do_deallocate(ptr as *mut core::ffi::c_void, layout.size()) {
  79. 0 => (),
  80. _ => panic!("Failed to deallocate memory"),
  81. }
  82. }
  83. }
  84. #[global_allocator]
  85. static ALLOCATOR: Allocator = Allocator {};
  86. global_asm!(
  87. r"
  88. .globl to_init_process
  89. to_init_process:
  90. push %rbp
  91. mov %rbx, %rdi
  92. jmp {}
  93. ",
  94. sym init_process,
  95. options(att_syntax)
  96. );
  97. extern "C" {
  98. fn to_init_process();
  99. fn boot_semaphore();
  100. }
  101. fn bootstrap_cpus() {
  102. let apic_base = rdmsr(0x1b);
  103. assert_eq!(apic_base & 0x800, 0x800, "LAPIC not enabled");
  104. assert_eq!(apic_base & 0x100, 0x100, "Is not bootstrap processor");
  105. let apic_base = apic_base & !0xfff;
  106. println_debug!("IA32_APIC_BASE: {apic_base:#x}");
  107. let apic_base = CachedPP::new(apic_base as usize);
  108. let spurious = apic_base.offset(0xf0).as_ptr::<u32>();
  109. let icr = apic_base.offset(0x300).as_ptr::<u32>();
  110. println_debug!("SPURIOUS: {:#x}", unsafe { spurious.read() });
  111. unsafe { icr.write_volatile(0xc4500) };
  112. while unsafe { icr.read_volatile() } & 0x1000 != 0 {
  113. unsafe { asm!("pause") };
  114. }
  115. unsafe { icr.write_volatile(0xc4601) };
  116. while unsafe { icr.read_volatile() } & 0x1000 != 0 {
  117. unsafe { asm!("pause") };
  118. }
  119. let sem = unsafe { AtomicU32::from_ptr(boot_semaphore as *mut _) };
  120. while sem.load(core::sync::atomic::Ordering::Acquire) != 3 {}
  121. println_info!("Processors startup finished");
  122. }
  123. #[no_mangle]
  124. pub extern "C" fn rust_kinit(early_kstack_pfn: usize) -> ! {
  125. // We don't call global constructors.
  126. // Rust doesn't need that, and we're not going to use global variables in C++.
  127. unsafe { kernel::arch::init::init_bscpu() };
  128. kernel::interrupt::init().unwrap();
  129. // TODO: Move this to rust.
  130. unsafe { init_pci() };
  131. kernel::vfs::mount::init_vfs().unwrap();
  132. // We need root dentry to be present in constructor of `FsContext`.
  133. // So call `init_vfs` first, then `init_multitasking`.
  134. init_multitasking();
  135. Thread::current().prepare_kernel_stack(|kstack| {
  136. let mut writer = kstack.get_writer();
  137. writer.entry = to_init_process;
  138. writer.flags = 0x200;
  139. writer.rbp = 0;
  140. writer.rbx = early_kstack_pfn; // `to_init_process` arg
  141. writer.finish();
  142. });
  143. // To satisfy the `Scheduler` "preempt count == 0" assertion.
  144. preempt::disable();
  145. Scheduler::get().lock().uwake(&Thread::current());
  146. arch::task::context_switch_light(
  147. CachedPP::new(early_kstack_pfn).as_ptr(), // We will never come back
  148. unsafe { Scheduler::idle_task().get_sp_ptr() },
  149. );
  150. arch::task::freeze()
  151. }
  152. /// We enter this function with `preempt count == 0`
  153. extern "C" fn init_process(early_kstack_pfn: usize) {
  154. unsafe { Page::take_pfn(early_kstack_pfn, 9) };
  155. preempt::enable();
  156. kernel::timer::init().unwrap();
  157. // Use the PIT timer for now.
  158. driver::timer::init();
  159. kernel::syscall::register_syscalls();
  160. CharDevice::init().unwrap();
  161. // We might want the serial initialized as soon as possible.
  162. driver::serial::init().unwrap();
  163. driver::e1000e::register_e1000e_driver();
  164. driver::ahci::register_ahci_driver();
  165. fs::procfs::init();
  166. fs::fat32::init();
  167. bootstrap_cpus();
  168. let (ip, sp) = {
  169. // mount fat32 /mnt directory
  170. let fs_context = FsContext::get_current();
  171. let mnt_dir = Dentry::open(&fs_context, Path::new(b"/mnt/").unwrap(), true).unwrap();
  172. mnt_dir.mkdir(0o755).unwrap();
  173. do_mount(
  174. &mnt_dir,
  175. "/dev/sda",
  176. "/mnt",
  177. "fat32",
  178. MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID,
  179. )
  180. .unwrap();
  181. let init = Dentry::open(&fs_context, Path::new(b"/mnt/busybox").unwrap(), true)
  182. .expect("busybox should be present in /mnt");
  183. let argv = vec![
  184. CString::new("/mnt/busybox").unwrap(),
  185. CString::new("sh").unwrap(),
  186. CString::new("/mnt/initsh").unwrap(),
  187. ];
  188. let envp = vec![
  189. CString::new("LANG=C").unwrap(),
  190. CString::new("HOME=/root").unwrap(),
  191. CString::new("PATH=/mnt").unwrap(),
  192. CString::new("PWD=/").unwrap(),
  193. ];
  194. let elf = ParsedElf32::parse(init.clone()).unwrap();
  195. elf.load(&Thread::current().process.mm_list, argv, envp)
  196. .unwrap()
  197. };
  198. Thread::current().files.open_console();
  199. unsafe {
  200. asm!(
  201. "swapgs",
  202. "mov ${ds}, %rax",
  203. "mov %ax, %ds",
  204. "mov %ax, %es",
  205. "push ${ds}",
  206. "push {sp}",
  207. "push $0x200",
  208. "push ${cs}",
  209. "push {ip}",
  210. "iretq",
  211. ds = const 0x33,
  212. cs = const 0x2b,
  213. in("rax") 0,
  214. ip = in(reg) ip.0,
  215. sp = in(reg) sp.0,
  216. options(att_syntax, noreturn),
  217. );
  218. }
  219. }