1use alloc::{
2 string::{String, ToString},
3 sync::Arc,
4};
5
6use ax_kernel_guard::NoPreemptIrqSave;
7use ax_runtime::hal::cpu::uspace::UserContext;
8use ax_sync::Mutex;
9use ax_task::{AxTaskExt, spawn_task_with};
10use starry_process::{Pid, Process};
11
12use crate::{
13 file::FD_TABLE,
14 mm::{copy_from_kernel, load_user_app, new_user_aspace_empty},
15 pseudofs::{self, dev::tty},
16 task::{ProcessData, ProcessImage, Thread, add_task_to_table, new_user_task, spawn_alarm_task},
17 tracepoint::tracepoint_init,
18};
19
20pub fn init(args: &[String], envs: &[String]) {
22 static_keys::global_init();
23 crate::cgroup::init();
24
25 tracepoint_init().expect("Failed to initialize tracepoints");
26
27 crate::ebpf::init_ebpf();
28 crate::perf::perf_event_init();
29 crate::kmod::init_kmod();
30
31 pseudofs::mount_all().expect("Failed to mount pseudofs");
32 spawn_alarm_task();
33 if ax_driver::cpufreq::calibrate_wanted() {
37 run_opp_calibration();
38 } else {
39 spawn_cpufreq_governor();
40 }
41 pseudofs::usbfs::start_event_pump();
42
43 ax_alloc::register_page_reclaim_fn(ax_fs_ng::vfs::page_cache_reclaim);
44
45 let loc = ax_fs_ng::vfs::current_fs_context()
46 .lock()
47 .resolve(&args[0])
48 .expect("Failed to resolve executable path");
49 let path = loc
50 .absolute_path()
51 .expect("Failed to get executable absolute path");
52 let name = loc.name().into_owned();
53
54 let mut uspace = new_user_aspace_empty()
55 .and_then(|mut it| {
56 copy_from_kernel(&mut it)?;
57 Ok(it)
58 })
59 .expect("Failed to create user address space");
60
61 let (entry_vaddr, ustack_top, auxv) = load_user_app(&mut uspace, loc, &args[0], args, envs)
62 .unwrap_or_else(|e| panic!("Failed to load user app: {}", e));
63
64 let uctx = UserContext::new(entry_vaddr.into(), ustack_top, 0);
65 let mut task = new_user_task(&name, uctx, 0);
66 task.ctx_mut().set_page_table_root(uspace.page_table_root());
67
68 const INIT_PID: Pid = 1;
77 let pid = INIT_PID;
78 let proc = Process::new_init(pid);
79 proc.add_thread(pid);
80
81 if let Err(err) = tty::bind_console_to(&proc) {
82 warn!("Failed to bind console tty: {err:?}");
83 }
84
85 let proc = ProcessData::new(
86 proc,
87 ProcessImage::new(
88 path.to_string(),
89 Arc::new(args.to_vec()),
90 Arc::new(envs.to_vec()),
91 auxv,
92 "/".to_string(),
93 "/".to_string(),
94 ),
95 Arc::new(Mutex::new(uspace)),
96 Arc::default(),
97 None,
98 pid,
99 false,
100 );
101 crate::cgroup::attach_initial_process(pid)
103 .expect("Failed to attach init process to cgroup root");
104
105 let mut scope = scope_local::Scope::new();
106 crate::file::add_stdio(&mut FD_TABLE.scope_mut(&mut scope).write())
107 .expect("Failed to add stdio");
108
109 let thr = Thread::new(pid, proc, None, starry_signal::SignalSet::default(), scope);
110 *task.task_ext_mut() = Some(AxTaskExt::from_impl(thr));
111
112 let task = {
113 let _guard = NoPreemptIrqSave::new();
114 let task = spawn_task_with(task, add_task_to_table);
115 tty::arm_console_irq();
116 task
117 };
118
119 let exit_code = task.join();
121 info!("Init process exited with code: {exit_code:?}");
122
123 let fs_context = ax_fs_ng::vfs::current_fs_context();
124 let cx = fs_context.lock();
125 if let Err(err) = cx.root_dir().unmount_all() {
131 warn!("shutdown: unmount_all failed (best-effort): {err:?}");
132 }
133 cx.root_dir()
134 .filesystem()
135 .flush()
136 .expect("Failed to flush rootfs");
137}
138
139fn run_opp_calibration() {
146 info!("cpufreq: running OPP calibration sweep (governor disabled this boot)");
147 for &(cluster_idx, cpu) in &[(0usize, 0usize), (1, 4), (2, 6)] {
148 let task = ax_task::spawn_raw(
149 move || {
150 ax_task::set_current_affinity(ax_task::AxCpuMask::one_shot(cpu));
151 ax_driver::cpufreq::calibrate_cluster(cluster_idx, cpu);
152 },
153 String::from("cpufreq-cal"),
154 ax_task::default_task_stack_size(),
155 );
156 task.join();
157 }
158 info!("cpufreq: OPP calibration sweep complete");
159}
160
161fn spawn_cpufreq_governor() {
174 if !ax_driver::cpufreq::governor_wanted() {
175 return;
176 }
177 info!("Initialize cpufreq ondemand governor...");
178 ax_task::spawn_raw(
179 cpufreq_governor_loop,
180 String::from("cpufreq-gov"),
181 ax_task::default_task_stack_size(),
182 );
183}
184
185fn cpufreq_governor_loop() {
191 let period = core::time::Duration::from_millis(ax_driver::cpufreq::governor_period_ms());
192 loop {
193 ax_task::sleep(period);
194 let mut busy = [0u64; 8];
197 for (cpu, slot) in busy.iter_mut().enumerate() {
198 *slot = ax_task::cpu_busy_ticks(cpu);
199 }
200 ax_driver::cpufreq::governor_poll(&busy);
201 }
202}