PatchworkOS  c9fea19
A non-POSIX operating system.
Loading...
Searching...
No Matches
init.c
Go to the documentation of this file.
1#include <kernel/init/init.h>
2
3#include <kernel/cpu/cpu.h>
4#include <kernel/cpu/gdt.h>
5#include <kernel/cpu/idt.h>
6#include <kernel/cpu/ipi.h>
7#include <kernel/cpu/irq.h>
10#include <kernel/fs/ramfs.h>
11#include <kernel/fs/sysfs.h>
12#include <kernel/fs/vfs.h>
14#include <kernel/log/log.h>
15#include <kernel/log/log_file.h>
16#include <kernel/log/panic.h>
17#include <kernel/mem/pmm.h>
18#include <kernel/mem/vmm.h>
21#include <kernel/sched/loader.h>
22#include <kernel/proc/reaper.h>
23#include <kernel/proc/process.h>
24#include <kernel/sched/sched.h>
25#include <kernel/sched/thread.h>
26#include <kernel/sched/timer.h>
27#include <kernel/sched/wait.h>
28
29#include <boot/boot_info.h>
30
32
33#include <stdlib.h>
34#include <string.h>
35#include <strings.h>
36
37static cpu_t bootstrapCpu ALIGNED(PAGE_SIZE) = {0};
38
39void init_early(void)
40{
41 gdt_init();
42 idt_init();
43 irq_init();
44
45 cpu_init_early(&bootstrapCpu);
46 assert(bootstrapCpu.id == CPU_ID_BOOTSTRAP);
47
48 log_init();
49
50 pmm_init();
51 vmm_init();
52
54
56
57 _std_init();
58
60
61 cpu_init(&bootstrapCpu);
62
63 LOG_INFO("early init done, jumping to boot thread\n");
64 thread_t* bootThread = thread_new(process_get_kernel());
65 if (bootThread == NULL)
66 {
67 panic(NULL, "Failed to create boot thread");
68 }
69
70 bootThread->frame.rip = (uintptr_t)kmain;
71 bootThread->frame.rbp = bootThread->kernelStack.top;
72 bootThread->frame.rsp = bootThread->kernelStack.top;
73 bootThread->frame.cs = GDT_CS_RING0;
74 bootThread->frame.ss = GDT_SS_RING0;
76
77 sched_start(bootThread);
78}
79
80static void init_finalize(void)
81{
83
84 ramfs_init();
85 sysfs_init();
86
89
91
92 perf_init();
93
95
97
98 if (bootInfo->gop.virtAddr != NULL)
99 {
100 if (module_device_attach("BOOT_GOP", "BOOT_GOP", MODULE_LOAD_ALL) == ERR)
101 {
102 panic(NULL, "Failed to load modules with BOOT_GOP");
103 }
104 }
105 else
106 {
107 LOG_WARN("no GOP provided by bootloader\n");
108 }
109
110 if (bootInfo->rsdp != NULL)
111 {
112 if (module_device_attach("BOOT_RSDP", "BOOT_RSDP", MODULE_LOAD_ALL) == ERR)
113 {
114 panic(NULL, "Failed to load modules with BOOT_RSDP");
115 }
116 }
117 else
118 {
119 LOG_WARN("no RSDP provided by bootloader\n");
120 }
121
122 if (module_device_attach("BOOT_ALWAYS", "BOOT_ALWAYS", MODULE_LOAD_ALL) == ERR)
123 {
124 panic(NULL, "Failed to load modules with BOOT_ALWAYS");
125 }
126
128
129 if (timer_source_amount() == 0)
130 {
131 panic(NULL, "No timer source registered, most likely no timer sources with a provided driver was found");
132 }
133 if (irq_chip_amount() == 0)
134 {
135 panic(NULL, "No IRQ chip registered, most likely no IRQ chips with a provided driver was found");
136 }
137 if (ipi_chip_amount() == 0)
138 {
139 panic(NULL, "No IPI chip registered, most likely no IPI chips with a provided driver was found");
140 }
141
142 LOG_INFO("kernel initalized using %llu kb of memory\n", pmm_used_amount() * PAGE_SIZE / 1024);
143}
144
145static inline void init_process_spawn(void)
146{
147 LOG_INFO("spawning init process\n");
148
150 if (initProcess == NULL)
151 {
152 panic(NULL, "Failed to create init process");
153 }
154
155 namespace_set_parent(&initProcess->ns, &process_get_kernel()->ns);
156
157 thread_t* initThread = thread_new(initProcess);
158 if (initThread == NULL)
159 {
160 panic(NULL, "Failed to create init thread");
161 }
162
163 // Calls loader_exec("/bin/init", NULL, 0, NULL, 0);
164 initThread->frame.rip = (uintptr_t)loader_exec;
165 initThread->frame.rdi = (uintptr_t)strdup("/bin/init");
166 if (initThread->frame.rdi == (uintptr_t)NULL)
167 {
168 panic(NULL, "Failed to allocate memory for init executable path");
169 }
170 initThread->frame.rsi = (uintptr_t)NULL;
171 initThread->frame.rdx = 0;
172 initThread->frame.rcx = (uintptr_t)NULL;
173 initThread->frame.r8 = 0;
174
175 initThread->frame.cs = GDT_CS_RING0;
176 initThread->frame.ss = GDT_SS_RING0;
177 initThread->frame.rsp = initThread->kernelStack.top;
179
180 sched_submit(initThread);
181}
182
183void kmain(void)
184{
185 LOG_DEBUG("kmain entered\n");
186
188
190
191 LOG_INFO("done with boot thread\n");
193}
#define assert(expression)
Definition assert.h:29
boot_info_t * bootInfo
Definition boot_info.c:14
#define GID_NONE
Invalid group ID.
Definition gid_t.h:16
void gdt_init(void)
Initialize the GDT.
Definition gdt.c:35
@ GDT_CS_RING0
Value to load into the CS register for kernel code.
Definition gdt.h:45
@ GDT_SS_RING0
Value to load into the SS register for kernel data.
Definition gdt.h:46
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:102
void irq_init(void)
Initialize the IRQ subsystem.
Definition irq.c:111
uint64_t irq_chip_amount(void)
Get the number of registered IRQ chips.
Definition irq.c:419
void syscall_table_init(void)
Sort the syscall table and verify that all syscalls are present.
Definition syscall.c:37
void cpu_init(cpu_t *cpu)
Initializes the CPU represented by the cpu_t structure.
Definition cpu.c:78
#define CPU_ID_BOOTSTRAP
ID of the bootstrap CPU.
Definition cpu.h:56
void cpu_init_early(cpu_t *cpu)
Only initialize the parts of the CPU structure needed for early boot.
Definition cpu.c:30
#define ALIGNED(alignment)
GCC aligned attribute.
Definition defs.h:22
void perf_init(void)
Initializes the performance driver.
Definition perf.c:136
void pic_disable(void)
Definition pic.c:13
uint64_t namespace_set_parent(namespace_t *ns, namespace_t *parent)
Sets the parent of a namespace and inherits all mounts from the parent.
Definition namespace.c:123
void ramfs_init(void)
Registers the ramfs filesystem and mounts it as the root filesystem.
Definition ramfs.c:327
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:39
void kmain(void)
Kernel main function.
Definition init.c:183
void log_file_expose(void)
Expose the kernel log file to userspace in sysfs.
Definition log_file.c:62
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:266
void log_init(void)
Initialize the logging system.
Definition log.c:51
#define LOG_WARN(format,...)
Definition log.h:107
#define LOG_INFO(format,...)
Definition log.h:106
#define LOG_DEBUG(format,...)
Definition log.h:100
uint64_t pmm_used_amount(void)
Retrieves the amount of reserved physical memory.
Definition pmm.c:253
void pmm_init(void)
Initializes the Physical Memory Manager.
Definition pmm.c:158
void vmm_init(void)
Initializes the Virtual Memory Manager.
Definition vmm.c:41
void vmm_kernel_space_load(void)
Loads the kernel's address space into the current CPU.
Definition vmm.c:110
void module_init_fake_kernel_module()
Initialize a fake module representing the kernel itself.
Definition module.c:723
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:1056
@ 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:1031
void process_procfs_init(void)
Initializes the /proc directory.
Definition process.c:1046
process_t * process_new(priority_t priority, gid_t gid)
Allocates and initializes a new process.
Definition process.c:758
_NORETURN void loader_exec(const char *executable, char **argv, uint64_t argc)
Causes the currently running thread to load and execute a new program.
Definition loader.c:39
thread_t * thread_new(process_t *process)
Creates a new thread structure.
Definition thread.c:67
_NORETURN void sched_start(thread_t *bootThread)
Starts the scheduler by jumping to the boot thread.
Definition sched.c:350
void sched_submit(thread_t *thread)
Submits a thread to the scheduler.
Definition sched.c:375
_NORETURN void sched_thread_exit(void)
Terminates the currently executing thread.
Definition sched.c:658
uint64_t timer_source_amount(void)
Get the amount of registered timer sources.
Definition timer.c:126
#define PRIORITY_MAX_USER
The maximum priority user space is allowed to specify, inclusive.
Definition proc.h:51
#define PAGE_SIZE
The size of a memory page in bytes.
Definition proc.h:106
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
static void init_process_spawn(void)
Definition init.c:145
static void init_finalize(void)
Definition init.c:80
void _std_init(void)
Definition init.c:13
#define RFLAGS_INTERRUPT_ENABLE
Definition regs.h:32
#define RFLAGS_ALWAYS_SET
Definition regs.h:24
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
char * strdup(const char *src)
Definition strdup.c:5
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:122
Process structure.
Definition process.h:205
namespace_t ns
Definition process.h:211
uintptr_t top
The top of the stack, this address is not inclusive.
Thread of execution structure.
Definition thread.h:56
interrupt_frame_t frame
Definition thread.h:80
stack_pointer_t kernelStack
The kernel stack of the thread.
Definition thread.h:68
void sysfs_init(void)
Initializes the SysFS.
Definition sysfs.c:82