PatchworkOS  dbbdc99
A non-POSIX operating system.
Loading...
Searching...
No Matches
trampoline.c
Go to the documentation of this file.
1#include "trampoline.h"
2
3#include <kernel/cpu/cpu.h>
4#include <kernel/cpu/gdt.h>
5#include <kernel/cpu/percpu.h>
6#include <kernel/log/log.h>
7#include <kernel/log/panic.h>
8#include <kernel/mem/pmm.h>
9#include <kernel/mem/vmm.h>
10#include <kernel/sched/clock.h>
11#include <kernel/sched/sched.h>
12#include <kernel/sched/thread.h>
13#include <kernel/sched/timer.h>
14#include <kernel/utils/utils.h>
15
17#include <string.h>
18
19static void* backupBuffer;
20static void* trampolineStack;
21
22static atomic_bool cpuReadyFlag = ATOMIC_VAR_INIT(false);
23
25{
26 pfn_t pfn = pmm_alloc();
27 if (pfn == ERR)
28 {
29 panic(NULL, "Failed to allocate memory for trampoline backup");
30 }
32
33 pfn = pmm_alloc();
34 if (pfn == ERR)
35 {
36 panic(NULL, "Failed to allocate memory for trampoline stack");
37 }
39
41
43 NULL) == NULL)
44 {
45 panic(NULL, "Failed to map trampoline");
46 }
47
52
55
57
58 LOG_DEBUG("trampoline initialized\n");
59}
60
75
88
90{
91 clock_t elapsed = 0;
92
93 while (elapsed < timeout)
94 {
96 {
97 return 0;
98 }
99
100 clock_wait(CLOCKS_PER_SEC / 10000);
101 elapsed += CLOCKS_PER_SEC / 10000;
102 }
103
104 return ERR;
105}
106
107static void trampoline_after_jump(void)
108{
111}
112
114{
115 cpu_init(cpu);
116
118
120 assert(thread != NULL);
121 assert(sched_is_idle(cpu));
123 thread->frame.rsp = thread->kernelStack.top;
124 thread->frame.cs = GDT_CS_RING0;
125 thread->frame.ss = GDT_SS_RING0;
127 thread_jump(thread);
128}
#define assert(expression)
Definition assert.h:29
#define CLOCKS_PER_SEC
Definition clock_t.h:15
#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 percpu_update(void)
Update percpu sections on the current CPU.
Definition percpu.c:99
void cpu_init(cpu_t *cpu)
Initializes a CPU structure.
Definition cpu.c:27
void lapic_send_init(lapic_id_t id)
Send an INIT IPI to the specified local APIC.
Definition lapic.c:66
void lapic_send_sipi(lapic_id_t id, void *entryPoint)
Send a Startup IPI (SIPI) to the specified local APIC.
Definition lapic.c:72
uint8_t lapic_id_t
Local APIC ID type.
Definition lapic.h:34
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:292
#define LOG_DEBUG(format,...)
Definition log.h:85
#define VIRT_TO_PFN(_addr)
Convert a identity mapped higher half virtual address to its PFN.
#define PFN_TO_VIRT(_pfn)
Convert a PFN to its identity mapped higher half virtual address.
#define PML_LOWER_TO_HIGHER(addr)
Converts an address from the lower half to the higher half.
size_t pfn_t
Page Frame Number type.
#define PML_ENSURE_LOWER_HALF(addr)
Ensures that the given address is in the lower half of the address space.
@ PML_PRESENT
@ PML_WRITE
void pmm_free(pfn_t pfn)
Free a single page of physical memory.
Definition pmm.c:341
pfn_t pmm_alloc(void)
Allocate a single page of physical memory.
Definition pmm.c:249
space_t * vmm_kernel_space_get(void)
Retrieves the kernel's address space.
Definition vmm.c:123
void * vmm_map(space_t *space, void *virtAddr, phys_addr_t physAddr, size_t length, pml_flags_t flags, space_callback_func_t func, void *data)
Maps physical memory to virtual memory in a given address space.
Definition vmm.c:226
void * vmm_unmap(space_t *space, void *virtAddr, size_t length)
Unmaps virtual memory from a given address space.
Definition vmm.c:336
void clock_wait(clock_t nanoseconds)
Wait for a specified number of nanoseconds.
Definition clock.c:121
_NORETURN void thread_jump(thread_t *thread)
Jump to a thread by calling thread_load() and then loading its interrupt frame.
static thread_t * thread_current_unsafe(void)
Retrieves the currently running thread without disabling interrupts.
Definition thread.h:137
bool sched_is_idle(cpu_t *cpu)
Checks if the CPU is currently idle.
Definition sched.c:618
_NORETURN void sched_idle_loop(void)
The idle loop for the scheduler.
void trampoline_send_startup_ipi(cpu_t *cpu, lapic_id_t lapicId)
Sends the startup IPI to a CPU to start it up.
Definition trampoline.c:76
#define TRAMPOLINE_PML4_OFFSET
Offset within the trampoline page where the PML4 address is stored.
Definition trampoline.h:40
#define TRAMPOLINE_STACK_OFFSET
Offset within the trampoline page where the stack pointer for the trampoline is stored.
Definition trampoline.h:55
#define TRAMPOLINE_SIZE
The size of the trampoline code.
Definition trampoline.h:72
void trampoline_start(void)
The start of the trampoline code, defined in trampoline.s.
#define TRAMPOLINE_BASE_ADDR
The physical address where the trampoline code will be copied to and executed from.
Definition trampoline.h:27
void trampoline_deinit(void)
Deinitializes the trampoline by restoring the original contents of the trampoline memory location.
Definition trampoline.c:61
#define TRAMPOLINE_ENTRY_OFFSET
Offset within the trampoline page where the entry point to jump to is stored.
Definition trampoline.h:45
#define TRAMPOLINE_CPU_OFFSET
Offset within the trampoline page where the CPU structure pointer is stored.
Definition trampoline.h:50
uint64_t trampoline_wait_ready(clock_t timeout)
Waits for the currently starting CPU to signal that it is ready.
Definition trampoline.c:89
void trampoline_c_entry(cpu_t *cpu)
After the trampoline is done with basic initialization, it calls this C entry point to continue CPU i...
Definition trampoline.c:113
#define TRAMPOLINE_DATA_OFFSET
The offset within the trampoline page where we can store data.
Definition trampoline.h:35
void trampoline_init(void)
Initializes the trampoline by copying the trampoline code to its designated memory location.
Definition trampoline.c:24
#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
__UINT64_TYPE__ clock_t
A nanosecond time.
Definition clock_t.h:13
#define RFLAGS_INTERRUPT_ENABLE
Definition regs.h:34
#define RFLAGS_ALWAYS_SET
Definition regs.h:26
#define atomic_store(object, desired)
Definition stdatomic.h:289
#define atomic_load(object)
Definition stdatomic.h:288
#define ATOMIC_VAR_INIT(value)
Definition stdatomic.h:74
#define atomic_init(obj, value)
Definition stdatomic.h:75
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition memcpy.c:61
_PUBLIC void * memset(void *s, int c, size_t n)
Definition memset.c:4
CPU structure.
Definition cpu.h:84
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
static atomic_bool cpuReadyFlag
Definition trampoline.c:22
static void * backupBuffer
Definition trampoline.c:19
static void trampoline_after_jump(void)
Definition trampoline.c:107
static void * trampolineStack
Definition trampoline.c:20
#define WRITE_64(address, value)
Definition utils.h:19