PatchworkOS
Loading...
Searching...
No Matches
interrupt.c
Go to the documentation of this file.
2
3#include <kernel/cpu/cpu.h>
4#include <kernel/cpu/gdt.h>
6#include <kernel/cpu/irq.h>
7#include <kernel/cpu/smp.h>
10#include <kernel/log/log.h>
11#include <kernel/log/panic.h>
12#include <kernel/sched/thread.h>
13#include <kernel/sched/wait.h>
14
15#include <kernel/cpu/regs.h>
16
17#include <assert.h>
18
20{
21 ctx->oldRflags = 0;
22 ctx->disableDepth = 0;
23 ctx->inInterrupt = false;
24}
25
27{
28 uint64_t rflags = rflags_read();
29 asm volatile("cli");
31 if (ctx->disableDepth == 0)
32 {
33 ctx->oldRflags = rflags;
34 }
35 ctx->disableDepth++;
36}
37
39{
40 uint64_t rflags = rflags_read();
42
44 assert(ctx->disableDepth != 0);
45 ctx->disableDepth--;
46
47 if (ctx->disableDepth == 0 && (ctx->oldRflags & RFLAGS_INTERRUPT_ENABLE))
48 {
49 asm volatile("sti" ::: "memory");
50 }
51}
52
54{
55 switch (frame->vector)
56 {
58 if (thread_handle_page_fault(frame) != ERR)
59 {
60 return;
61 }
62 break;
63 default:
64 break;
65 }
66
68 {
69 cpu_t* self = smp_self_unsafe();
70 thread_t* thread = sched_thread_unsafe();
71 process_t* process = thread->process;
72
73 uint64_t cr2 = cr2_read();
74
75 LOG_WARN("unhandled user space exception in process pid=%d tid=%d vector=%lld error=0x%llx rip=0x%llx "
76 "cr2=0x%llx errno='%s'\n",
77 process->id, thread->id, frame->vector, frame->errorCode, frame->rip, cr2, strerror(thread->error));
78
79#ifndef NDEBUG
80 panic_stack_trace(frame);
81#endif
82
83 process_kill(process, EFAULT);
84 sched_invoke(frame, self, SCHED_DIE);
85 }
86 else
87 {
88 panic(frame, "unhandled kernel exception");
89 }
90}
91
93{
94 if (frame->vector < EXCEPTION_AMOUNT)
95 {
96 exception_handler(frame);
97 return;
98 }
99
100 cpu_t* self = smp_self_unsafe();
101
102 if (self->interrupt.inInterrupt)
103 {
104 panic(frame, "Interrupt handler called while already in an interrupt");
105 }
106 self->interrupt.inInterrupt = true;
107
108 statistics_interrupt_begin(frame, self);
109
110 switch (frame->vector)
111 {
113 {
114 vmm_shootdown_handler(frame, self);
115 lapic_eoi();
116 }
117 break;
118 case INTERRUPT_DIE:
119 {
120 sched_invoke(frame, self, SCHED_DIE);
121 }
122 break;
123 case INTERRUPT_NOTE:
124 {
125 // Notes should only be handled when in user space otherwise we get so many edge cases to deal with.
126 // There is a check when a system call occurs to make sure that the note will eventually be handled.
128 {
129 note_interrupt_handler(frame, self);
130 }
131 lapic_eoi();
132 }
133 break;
134 case INTERRUPT_TIMER:
135 {
136 timer_interrupt_handler(frame, self);
137 lapic_eoi();
138 }
139 break;
140 case INTERRUPT_HALT:
141 {
142 while (1)
143 {
144 asm volatile("hlt");
145 }
146 }
147 break;
148 default:
149 {
151 {
152 irq_dispatch(frame);
153 }
154 else
155 {
156 panic(frame, "Unknown vector");
157 }
158 }
159 }
160
162
163 statistics_interrupt_end(frame, self);
164 self->interrupt.inInterrupt = false;
165
166 // This is a sanity check to make sure blocking and scheduling is functioning correctly. For instance, a trap should
167 // never return with a lock acquired nor should one be invoked with a lock acquired.
169}
#define assert(expression)
Definition assert.h:29
void interrupt_ctx_init(interrupt_ctx_t *ctx)
Initializes the CLI context.
Definition interrupt.c:19
void interrupt_handler(interrupt_frame_t *frame)
Handles CPU interrupts.
Definition interrupt.c:92
#define INTERRUPT_FRAME_IN_USER_SPACE(frame)
Checks if a interrupt frame is from user space.
Definition interrupt.h:76
void interrupt_disable(void)
Disable interrupts and increment the disableDepth.
Definition interrupt.c:26
void interrupt_enable(void)
Decrement the CLI depth and enable interrupts if depth reaches zero and interrupts were previously en...
Definition interrupt.c:38
@ EXCEPTION_AMOUNT
Definition interrupt.h:130
@ INTERRUPT_TIMER
The timer subsystem interrupt.
Definition interrupt.h:137
@ INTERRUPT_NOTE
Nofify that a note is available.
Definition interrupt.h:136
@ INTERRUPT_DIE
Kills and frees the current thread.
Definition interrupt.h:135
@ INTERRUPT_TLB_SHOOTDOWN
TLB shootdown interrupt.
Definition interrupt.h:134
@ EXTERNAL_INTERRUPT_BASE
Definition interrupt.h:132
@ EXCEPTION_PAGE_FAULT
Definition interrupt.h:112
@ INTERRUPT_HALT
Halt the CPU.
Definition interrupt.h:138
void irq_dispatch(interrupt_frame_t *frame)
Dispatch an IRQ.
Definition irq.c:13
@ IRQ_AMOUNT
Definition irq.h:40
static cpu_t * smp_self_unsafe(void)
Returns a pointer to the cpu_t structure of the current CPU.
Definition smp.h:90
void cpu_stacks_overflow_check(cpu_t *cpu)
Checks for CPU stack overflows.
Definition cpu.c:69
void lapic_eoi(void)
Send an End Of Interrupt (EOI) signal to the local apic.
Definition apic.c:236
void statistics_interrupt_begin(interrupt_frame_t *frame, cpu_t *self)
Called at the beginning of an interrupt.
Definition statistics.c:120
void statistics_interrupt_end(interrupt_frame_t *frame, cpu_t *self)
Called at the end of an interrupt.
Definition statistics.c:140
void note_interrupt_handler(interrupt_frame_t *frame, cpu_t *self)
Note interrupt handler.
Definition note.c:77
void panic_stack_trace(const interrupt_frame_t *frame)
Print a stack trace from a interrupt frame.
Definition panic.c:281
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:362
#define LOG_WARN(format,...)
Definition log.h:88
void vmm_shootdown_handler(interrupt_frame_t *frame, cpu_t *self)
TLB shootdown interrupt handler.
Definition vmm.c:458
void process_kill(process_t *process, uint64_t status)
Kills a process.
Definition process.c:483
uint64_t thread_handle_page_fault(const interrupt_frame_t *frame)
Handles a page fault that occurred in the currently running thread.
Definition thread.c:173
thread_t * sched_thread_unsafe(void)
Retrieves the currently running thread without disabling interrupts.
Definition sched.c:175
void sched_invoke(interrupt_frame_t *frame, cpu_t *self, schedule_flags_t flags)
The main scheduling function.
Definition sched.c:480
@ SCHED_DIE
Kill and free the currently running thread.
Definition sched.h:277
void timer_interrupt_handler(interrupt_frame_t *frame, cpu_t *self)
Handle timer interrupt.
Definition timer.c:96
#define EFAULT
Bad address.
Definition errno.h:102
#define ERR
Integer error value.
Definition ERR.h:17
static void exception_handler(interrupt_frame_t *frame)
Definition interrupt.c:53
#define RFLAGS_INTERRUPT_ENABLE
Definition regs.h:32
static uint64_t cr2_read()
Definition regs.h:114
static uint64_t rflags_read()
Definition regs.h:78
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC char * strerror(int errnum)
Definition strerror.c:6
CPU structure.
Definition cpu.h:42
interrupt_ctx_t interrupt
Definition cpu.h:47
Per-CPU Interrupt Context.
Definition interrupt.h:85
uint32_t disableDepth
Definition interrupt.h:87
uint64_t oldRflags
Definition interrupt.h:86
Trap Frame Structure.
Definition interrupt.h:42
uint64_t rflags
Definition interrupt.h:64
uint64_t errorCode
Definition interrupt.h:60
uint64_t vector
Definition interrupt.h:59
Process structure.
Definition process.h:53
pid_t id
Definition process.h:55
Thread of execution structure.
Definition thread.h:55
process_t * process
The parent process that the thread executes within.
Definition thread.h:57
errno_t error
Definition thread.h:67
tid_t id
The thread id, unique within a process_t.
Definition thread.h:59