PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
init.c
Go to the documentation of this file.
2#include <kernel/init/init.h>
3
4#include <kernel/cpu/cpu.h>
5#include <kernel/cpu/gdt.h>
6#include <kernel/cpu/idt.h>
7#include <kernel/cpu/ipi.h>
8#include <kernel/cpu/irq.h>
10#include <kernel/drivers/pic.h>
11#include <kernel/fs/devfs.h>
13#include <kernel/fs/netfs.h>
14#include <kernel/fs/procfs.h>
15#include <kernel/fs/sysfs.h>
16#include <kernel/fs/tmpfs.h>
17#include <kernel/fs/vfs.h>
19#include <kernel/log/log.h>
20#include <kernel/log/panic.h>
21#include <kernel/log/screen.h>
22#include <kernel/mem/pmm.h>
23#include <kernel/mem/vmm.h>
26#include <kernel/proc/group.h>
27#include <kernel/proc/process.h>
28#include <kernel/proc/reaper.h>
29#include <kernel/sched/loader.h>
30#include <kernel/sched/sched.h>
31#include <kernel/sched/thread.h>
32#include <kernel/sched/timer.h>
33#include <kernel/sched/wait.h>
34
35#include <boot/boot_info.h>
36
37#include <_libstd/init.h>
38
39#ifdef _TESTING_
40#include <kernel/utils/test.h>
41#endif
42
43#include <stdlib.h>
44#include <string.h>
45#include <strings.h>
46
47static cpu_t bootstrapCpu ALIGNED(PAGE_SIZE) = {0};
48
49void init_early(void)
50{
51 gdt_init();
52 idt_init();
53 irq_init();
54
55 cpu_init(&bootstrapCpu);
56
57 log_init();
58
59 pmm_init();
60 vmm_init();
61
63
65
67
68 _std_init();
69
71
73
74 LOG_INFO("early init done, jumping to boot thread\n");
75 thread_t* bootThread = thread_new(process_get_kernel());
76 if (bootThread == NULL)
77 {
78 panic(NULL, "Failed to create boot thread");
79 }
80
81 bootThread->frame.rip = (uintptr_t)kmain;
82 bootThread->frame.rbp = bootThread->kernelStack.top;
83 bootThread->frame.rsp = bootThread->kernelStack.top;
84 bootThread->frame.cs = GDT_CS_RING0;
85 bootThread->frame.ss = GDT_SS_RING0;
87
88 sched_start(bootThread);
89 panic(NULL, "sched_start returned unexpectedly");
90}
91
92static void init_finalize(void)
93{
95
96 tmpfs_init();
97 devfs_init();
98 sysfs_init();
100 netfs_init();
102
103 log_expose();
104
105 reaper_init();
106
107 perf_init();
108
110
111 if (bootInfo->gop.virtAddr != NULL)
112 {
113 if (module_device_attach("BOOT_GOP", "BOOT_GOP", MODULE_LOAD_ALL) == ERR)
114 {
115 panic(NULL, "Failed to load modules with BOOT_GOP");
116 }
117 }
118 else
119 {
120 LOG_WARN("no GOP provided by bootloader\n");
121 }
122
123 if (bootInfo->rsdp != NULL)
124 {
125 if (module_device_attach("BOOT_RSDP", "BOOT_RSDP", MODULE_LOAD_ALL) == ERR)
126 {
127 panic(NULL, "Failed to load modules with BOOT_RSDP");
128 }
129 }
130 else
131 {
132 LOG_WARN("no RSDP provided by bootloader\n");
133 }
134
135 if (module_device_attach("BOOT_ALWAYS", "BOOT_ALWAYS", MODULE_LOAD_ALL) == ERR)
136 {
137 panic(NULL, "Failed to load modules with BOOT_ALWAYS");
138 }
139
141
142 if (timer_source_amount() == 0)
143 {
144 panic(NULL, "No timer source registered, most likely no timer sources with a provided driver was found");
145 }
146 if (irq_chip_amount() == 0)
147 {
148 panic(NULL, "No IRQ chip registered, most likely no IRQ chips with a provided driver was found");
149 }
150 if (ipi_chip_amount() == 0)
151 {
152 panic(NULL, "No IPI chip registered, most likely no IPI chips with a provided driver was found");
153 }
154
155 LOG_INFO("kernel initalized using %llu kb of memory\n", pmm_used_pages() * PAGE_SIZE / 1024);
156}
157
158static inline void init_process_spawn(void)
159{
160 LOG_INFO("spawning init process\n");
161
163 if (kernelNs == NULL)
164 {
165 panic(NULL, "Failed to get kernel namespace");
166 }
167 UNREF_DEFER(kernelNs);
168
169 namespace_t* rootNs = namespace_new(kernelNs);
170 if (rootNs == NULL)
171 {
172 panic(NULL, "Failed to create root namespace");
173 }
174 UNREF_DEFER(rootNs);
175
176 if (namespace_copy(rootNs, kernelNs) == ERR)
177 {
178 panic(NULL, "Failed to copy kernel namespace to root namespace");
179 }
180
181 process_t* initProcess = process_new(PRIORITY_MAX_USER, NULL, rootNs);
182 if (initProcess == NULL)
183 {
184 panic(NULL, "Failed to create init process");
185 }
186 UNREF_DEFER(initProcess);
187
188 thread_t* initThread = thread_new(initProcess);
189 if (initThread == NULL)
190 {
191 panic(NULL, "Failed to create init thread");
192 }
193
194 char* argv[] = {"/sbin/init", NULL};
195 if (process_set_cmdline(initProcess, argv, 1) == ERR)
196 {
197 panic(NULL, "Failed to set init process cmdline");
198 }
199
200 // Calls loader_exec();
201 initThread->frame.rip = (uintptr_t)loader_exec;
202 initThread->frame.cs = GDT_CS_RING0;
203 initThread->frame.ss = GDT_SS_RING0;
204 initThread->frame.rsp = initThread->kernelStack.top;
206
207 sched_submit(initThread);
208}
209
210void kmain(void)
211{
212 LOG_DEBUG("kmain entered\n");
213
215
216#ifdef _TESTING_
217 TEST_ALL();
218#endif
219
221
222 LOG_INFO("done with boot thread\n");
224}
void _std_init(void)
Definition init.c:13
boot_info_t * bootInfo
Definition boot_info.c:14
void gdt_init(void)
Initialize the GDT.
Definition gdt.c:36
#define GDT_SS_RING0
Value to load into the SS register for kernel data.
Definition gdt.h:36
#define GDT_CS_RING0
Value to load into the CS register for kernel code.
Definition gdt.h:35
void idt_init(void)
Initialize the IDT structure in memory.
Definition idt.c:27
uint64_t ipi_chip_amount(void)
Get the number of registered IPI chips.
Definition ipi.c:104
void irq_init(void)
Initialize the IRQ subsystem.
Definition irq.c:112
uint64_t irq_chip_amount(void)
Get the number of registered IRQ chips.
Definition irq.c:417
#define PERCPU_INIT()
Initialize all percpu variables within the current modules .percpu section.
Definition percpu.h:194
void syscall_table_init(void)
Sort the syscall table and verify that all syscalls are present.
Definition syscall.c:49
void cpu_init(cpu_t *cpu)
Initializes a CPU structure.
Definition cpu.c:27
void perf_init(void)
Initializes the performance driver.
Definition perf.c:150
void pic_disable(void)
Definition pic.c:13
void devfs_init(void)
Initializes the devfs.
Definition devfs.c:50
void filesystem_expose(void)
Exposes the sysfs fs directory.
Definition filesystem.c:215
uint64_t namespace_copy(namespace_t *dest, namespace_t *src)
Copy mounts from one namespace to another.
Definition namespace.c:287
namespace_t * namespace_new(namespace_t *parent)
Create a new namespace.
Definition namespace.c:253
void netfs_init(void)
Initialize the networking filesystem.
Definition netfs.c:805
void procfs_init(void)
Register the procfs filesystem.
Definition procfs.c:1279
void sysfs_init(void)
Initializes the sysfs and mount an instance at /sys.
Definition sysfs.c:50
void tmpfs_init(void)
Registers the tmpfs filesystem and mounts an instance of it containing the boot ram disk as root.
Definition tmpfs.c:377
void boot_info_to_higher_half(void)
Offset all pointers in the boot info structure to the higher half.
Definition boot_info.c:68
boot_info_t * boot_info_get(void)
Gets the boot info structure.
Definition boot_info.c:16
void boot_info_free(void)
Frees the boot info structure and all its associated data.
Definition boot_info.c:87
void init_early(void)
Early kernel initialization.
Definition init.c:49
void kmain(void)
Kernel main function.
Definition init.c:210
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:292
void log_init(void)
Initialize the logging system.
Definition log.c:93
#define LOG_WARN(format,...)
Definition log.h:92
#define LOG_INFO(format,...)
Definition log.h:91
#define LOG_DEBUG(format,...)
Definition log.h:85
void log_expose(void)
Expose kernel logs via the /dev/klog file.
Definition log.c:112
size_t pmm_used_pages(void)
Get the number of used physical pages.
Definition pmm.c:403
void pmm_init(void)
Read the boot info memory map and initialize the PMM.
Definition pmm.c:239
void vmm_init(void)
Initializes the Virtual Memory Manager.
Definition vmm.c:47
void vmm_kernel_space_load(void)
Loads the kernel's address space into the current CPU.
Definition vmm.c:116
void module_init_fake_kernel_module()
Initialize a fake module representing the kernel itself.
Definition module.c:735
uint64_t module_device_attach(const char *type, const char *name, module_load_flags_t flags)
Notify the module system of a device being attached.
Definition module.c:1069
@ MODULE_LOAD_ALL
If set, will load all modules matching the device type.
Definition module.h:399
void reaper_init(void)
Initializes the process reaper.
Definition reaper.c:58
process_t * process_get_kernel(void)
Gets the kernel process.
Definition process.c:374
process_t * process_new(priority_t priority, group_member_t *group, namespace_t *ns)
Allocates and initializes a new process.
Definition process.c:125
uint64_t process_set_cmdline(process_t *process, char **argv, uint64_t argc)
Sets the command line arguments for a process.
Definition process.c:294
namespace_t * process_get_ns(process_t *process)
Gets the namespace of a process.
Definition process.c:206
_NORETURN void loader_exec(void)
Causes the currently running thread to load and execute a new program.
Definition loader.c:40
thread_t * thread_new(process_t *process)
Creates a new thread structure.
Definition thread.c:50
_NORETURN void sched_start(thread_t *bootThread)
Starts the scheduler by jumping to the boot thread.
Definition sched.c:354
void sched_submit(thread_t *thread)
Submits a thread to the scheduler.
Definition sched.c:378
_NORETURN void sched_thread_exit(void)
Terminates the currently executing thread.
Definition sched.c:664
uint64_t timer_source_amount(void)
Get the amount of registered timer sources.
Definition timer.c:131
#define UNREF_DEFER(ptr)
RAII-style cleanup for scoped references.
Definition ref.h:122
#define TEST_ALL()
Run all registered tests in the ._tests section.
Definition test.h:37
#define ALIGNED(alignment)
GCC aligned attribute.
Definition defs.h:23
#define PRIORITY_MAX_USER
The maximum priority user space is allowed to specify, inclusive.
Definition proc.h:44
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
#define PAGE_SIZE
The size of a memory page in bytes.
Definition PAGE_SIZE.h:8
static void init_process_spawn(void)
Definition init.c:158
static void init_finalize(void)
Definition init.c:92
#define RFLAGS_INTERRUPT_ENABLE
Definition regs.h:34
#define RFLAGS_ALWAYS_SET
Definition regs.h:26
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
uint32_t * virtAddr
Definition boot_info.h:45
boot_gop_t gop
Definition boot_info.h:101
void * rsdp
Definition boot_info.h:102
CPU structure.
Definition cpu.h:84
Namespace structure.
Definition namespace.h:57
Process structure.
Definition process.h:76
uintptr_t top
The top of the stack, this address is not inclusive.
Thread of execution structure.
Definition thread.h:61
interrupt_frame_t frame
Definition thread.h:87
stack_pointer_t kernelStack
The kernel stack of the thread.
Definition thread.h:73