AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
isr.c
Go to the documentation of this file.
1
10
11#include <core/system.h>
12#include <core/arch.h>
13
14#include <core/panic.h>
15#include <core/string.h>
16#include <cpu/cpu.h>
17#include <sys/sched.h>
18#include <sys/signal.h>
19#include <sys/lock.h>
20#include <mm/mm.h>
21
22extern void __x86_isr0 (void);
23extern void __x86_isr1 (void);
24extern void __x86_isr2 (void);
25extern void __x86_isr3 (void);
26extern void __x86_isr4 (void);
27extern void __x86_isr5 (void);
28extern void __x86_isr6 (void);
29extern void __x86_isr7 (void);
30extern void __x86_isr8 (void);
31extern void __x86_isr9 (void);
32extern void __x86_isr10(void);
33extern void __x86_isr11(void);
34extern void __x86_isr12(void);
35extern void __x86_isr13(void);
36extern void __x86_isr14(void);
37extern void __x86_isr15(void);
38extern void __x86_isr16(void);
39extern void __x86_isr17(void);
40extern void __x86_isr18(void);
41extern void __x86_isr19(void);
42extern void __x86_isr20(void);
43extern void __x86_isr21(void);
44extern void __x86_isr22(void);
45extern void __x86_isr23(void);
46extern void __x86_isr24(void);
47extern void __x86_isr25(void);
48extern void __x86_isr26(void);
49extern void __x86_isr27(void);
50extern void __x86_isr28(void);
51extern void __x86_isr29(void);
52extern void __x86_isr30(void);
53extern void __x86_isr31(void);
54extern void __x86_isr128(void);
55
56/* The exceptions' names: see the Intel 64 and IA-32 Architectures
57 * Software Developer's Manual, Volume 3 (System Programming Guide), Table
58 * 6-1, "Protected-Mode Exceptions and Interrupts". */
59
60static const char *int_msg[32] = {
61 /* 0x00 */ "#DE: Divide Error",
62 /* 0x01 */ "#DB: Debug Exception",
63 /* 0x02 */ "NMI Interrupt",
64 /* 0x03 */ "#BP: Breakpoint",
65 /* 0x04 */ "#OF: Overflow",
66 /* 0x05 */ "#BR: BOUND Range Exceeded",
67 /* 0x06 */ "#UD: Invalid Opcode (Undefined Opcode)",
68 /* 0x07 */ "#NM: Device Not Available (No Math Coprocessor)",
69 /* 0x08 */ "#DF: Double Fault",
70 /* 0x09 */ "Coprocessor Segment Overrun (reserved)",
71 /* 0x0a */ "#TS: Invalid TSS",
72 /* 0x0b */ "#NP: Segment Not Present",
73 /* 0x0C */ "#SS: Stack-Segment Fault",
74 /* 0x0D */ "#GP: General Protection",
75 /* 0x0E */ "#PF: Page Fault",
76 /* 0x0F */ "Reserved",
77 /* 0x10 */ "#MF: x87 FPU Floating-Point Error (Math Fault)",
78 /* 0x11 */ "#AC: Alignment Check",
79 /* 0x12 */ "#MC: Machine Check",
80 /* 0x13 */ "#XM: SIMD Floating-Point Exception",
81 /* 0x14 */ "#VE: Virtualization Exception",
82 /* 0x15 */ "Reserved",
83 /* 0x16 */ "Reserved",
84 /* 0x17 */ "Reserved",
85 /* 0x18 */ "Reserved",
86 /* 0x19 */ "Reserved",
87 /* 0x1A */ "Reserved",
88 /* 0x1B */ "Reserved",
89 /* 0x1C */ "Reserved",
90 /* 0x1D */ "Reserved",
91 /* 0x1E */ "Reserved",
92 /* 0x1F */ "Reserved"
93};
94
95/* The signal that an exception in user mode sends to the process, or 0
96 * if the exception is the kernel's to handle (or fatal). */
97static const int int_sig[32] = {
98 /* 0x00 */ SIGFPE, /* #DE */
99 /* 0x01 */ SIGTRAP, /* #DB */
100 /* 0x02 */ 0,
101 /* 0x03 */ SIGTRAP, /* #BP */
102 /* 0x04 */ SIGSEGV, /* #OF */
103 /* 0x05 */ SIGSEGV, /* #BR */
104 /* 0x06 */ SIGILL, /* #UD */
105 /* 0x07 */ 0,
106 /* 0x08 */ 0,
107 /* 0x09 */ SIGFPE,
108 /* 0x0A */ 0,
109 /* 0x0B */ SIGBUS, /* #NP */
110 /* 0x0C */ SIGBUS, /* #SS */
111 /* 0x0D */ SIGSEGV, /* #GP */
112 /* 0x0E */ SIGSEGV, /* #PF */
113 /* 0x0F */ 0,
114 /* 0x10 */ SIGFPE, /* #MF */
115 /* 0x11 */ SIGBUS, /* #AC */
116 /* 0x12 */ 0,
117 /* 0x13 */ SIGFPE, /* #XM */
118};
119
124static int uaccess_fixup(struct x86_regs *regs)
125{
126 extern uintptr_t x86_uaccess_fixups[], x86_uaccess_fixups_end[];
127#if ARCH_BITS==32
128 uintptr_t ip = regs->eip;
129#else
130 uintptr_t ip = regs->rip;
131#endif
132
133 for (uintptr_t *f = x86_uaccess_fixups; f < x86_uaccess_fixups_end; f += 2) {
134 if (ip == f[0]) {
135#if ARCH_BITS==32
136 regs->eip = f[1];
137#else
138 regs->rip = f[1];
139#endif
140 return 1;
141 }
142 }
143
144 return 0;
145}
146
148static void isr_dispatch(struct x86_regs *regs)
149{
150 unsigned vec = regs->vec;
151
152 if (vec == 0xE && curthread) { /* a page fault */
153 uintptr_t addr = read_cr2();
154
155 if (!arch_mm_page_fault(addr, regs->err)) {
157 return;
158 }
159
160 /* one from user mode that can't be resolved: SIGSEGV, delivered
161 * on the way back */
162 if ((regs->cs & 3) == 3) {
163 signal_force(curproc, SIGSEGV);
165 return;
166 }
167
168 /* one from the kernel, copying from or to user memory: the copy
169 * fails with -EFAULT (a fault on the kernel's side of the copy is
170 * a bug, as anywhere else) */
171 if (addr < USER_STACK && uaccess_fixup(regs))
172 return;
173
174 /* one from the kernel anywhere else, even at a user address, is a
175 * bug: the kernel only touches user memory through copyin() and
176 * copyout() */
177 printk("kernel: page fault at %p%s\n", (void *) addr,
178 addr < USER_STACK ? " (user memory, outside copyin/copyout)" : "");
180 panic("page fault in the kernel");
181 }
182
183 if (vec == 0x07) { /* #NM: the thread's first FPU use since its switch */
184 x86_fpu_trap();
186 return;
187 }
188
189 if (vec == 0x80) { /* a system call */
190 if (!curthread)
191 panic("syscall without a current thread");
192
193 struct x86_thread *arch = curthread->arch;
194 arch->regs = regs;
196 return;
197 }
198
199
200 /* an exception caused by user code: a signal to the process */
201 if (vec < 32 && (regs->cs & 3) == 3 && curthread
202 && int_sig[vec]) {
203 struct x86_thread *arch = curthread->arch;
204 arch->regs = regs;
205
206 /* the faulting instruction */
207#if ARCH_BITS==32
208 curthread->fault_addr = regs->eip;
209#else
210 curthread->fault_addr = regs->rip;
211#endif
214 return;
215 }
216
217 if (vec < 32) {
218 const char *msg = int_msg[vec];
219 printk("Recieved interrupt %d [err=%d]: %s\n", vec, (int) regs->err, msg);
220
221 if (vec == 0x0E) { /* a page fault */
222 printk("CR2 = %p\n", read_cr2());
223 }
225 panic("Kernel Exception");
226 } else {
227 printk("Unhandled interrupt %d\n", vec);
228 panic("Kernel Exception");
229 }
230}
231
240{
241 int took = kernel_enter();
242
243 /* its process was killed while it ran (from another CPU): the thread
244 * ends now, and what it came in for is dropped */
245 if (took && curthread && curthread->killed)
247
249 kernel_leave(took);
250}
251
254{
288}
void arch_syscall(struct aarch64_regs *r)
Definition syscall.c:23
#define USER_STACK
Definition arch.h:60
#define panic(s)
Definition panic.h:15
static uintptr_t read_cr2(void)
Definition cpu.h:190
void x86_return_to_user(struct x86_regs *r, int syscall)
Delivers the current process's pending signals on the way back to user mode: stops and default action...
Definition signal.c:246
static void x86_dump_registers(struct x86_regs *regs)
Definition cpu.h:29
int arch_mm_page_fault(vaddr_t vaddr, int err)
Handles a page fault: turns the CPU's error code into the kernel's PF_* flags, and calls mm_page_faul...
Definition i386.c:449
void x86_fpu_trap(void)
Handles #NM, the current thread's first FPU or SSE instruction since it was switched in: it saves the...
Definition fpu.c:131
void x86_idt_gate_user_set(uint32_t id, uintptr_t offset)
Sets an interrupt gate that user mode may raise with int too: the system call vector.
Definition idt.c:67
void x86_idt_gate_set(uint32_t id, uintptr_t offset)
Sets an interrupt gate that only the hardware (and the kernel) can raise: an exception or a device in...
Definition idt.c:45
void __x86_isr15(void)
void __x86_isr21(void)
void __x86_isr24(void)
static const char * int_msg[32]
Definition isr.c:60
void __x86_isr22(void)
void __x86_isr16(void)
void __x86_isr7(void)
void __x86_isr8(void)
void __x86_isr3(void)
void __x86_isr31(void)
void __x86_isr4(void)
void x86_isr_setup(void)
Sets the IDT's gates for the exceptions and the system call vector.
Definition isr.c:253
void __x86_isr0(void)
void __x86_isr(struct x86_regs *regs)
Handles an exception or a system call, which the stubs in cpu.S call.
Definition isr.c:239
void __x86_isr25(void)
void __x86_isr12(void)
void __x86_isr18(void)
static const int int_sig[32]
Definition isr.c:97
void __x86_isr29(void)
void __x86_isr11(void)
void __x86_isr13(void)
void __x86_isr14(void)
void __x86_isr128(void)
void __x86_isr23(void)
void __x86_isr17(void)
void __x86_isr6(void)
void __x86_isr28(void)
void __x86_isr10(void)
void __x86_isr20(void)
static void isr_dispatch(struct x86_regs *regs)
Handles an exception or a system call, by its vector.
Definition isr.c:148
void __x86_isr27(void)
void __x86_isr5(void)
void __x86_isr9(void)
void __x86_isr1(void)
void __x86_isr30(void)
void __x86_isr19(void)
void __x86_isr26(void)
void __x86_isr2(void)
void kernel_leave(int took)
Lets go of the kernel lock on leaving the kernel, if kernel_enter() took it.
Definition lock.c:83
int kernel_enter(void)
Takes the kernel lock on entering the kernel, unless this CPU holds it already (an exception inside t...
Definition lock.c:68
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
Definition printk.c:249
#define curproc
Definition sched.h:13
void sched_thread_killed(void)
Ends the current thread, which was killed while it ran on this CPU (thread->killed).
Definition sched.c:258
#define curthread
Definition sched.h:12
void signal_force(struct proc *proc, int signal)
Sends a signal that can't be blocked or ignored, such as the SIGSEGV of a fault: if the process block...
Definition signal.c:230
__SIZE_TYPE__ uintptr_t
Definition stddef.h:12
The registers an interrupt or exception saved, on the kernel stack, as cpu.S's stubs push them: the g...
Definition cpu.h:12
uint64_t cs
Definition cpu.h:24
uint64_t err
Definition cpu.h:23
uint64_t vec
Definition cpu.h:23
uint64_t rip
Definition cpu.h:24
A thread's x86 state: its kernel stack, and where it resumes.
Definition arch.h:16
struct x86_regs * regs
Definition arch.h:34
static int uaccess_fixup(struct aarch64_regs *r)
Handles a fault in a copy from or to user memory (cpu/uaccess.S): the copy goes on at its fixup,...
Definition trap.c:55