Handle IRQs inside the kernel
All checks were successful
Build documentation / build-and-deploy (push) Successful in 2m42s
All checks were successful
Build documentation / build-and-deploy (push) Successful in 2m42s
This commit is contained in:
@@ -195,6 +195,16 @@ uint32_t lapic_id (void) { return lapic_read (LAPIC_ID) >> 24; }
|
||||
/* Send End of interrupt command to Local APIC */
|
||||
void lapic_eoi (void) { lapic_write (LAPIC_EOI, 0); }
|
||||
|
||||
void lapic_timer_mask (void) {
|
||||
uint32_t v = lapic_read (LAPIC_LVTTR);
|
||||
lapic_write (LAPIC_LVTTR, v | (1 << 16));
|
||||
}
|
||||
|
||||
void lapic_timer_unmask (void) {
|
||||
uint32_t v = lapic_read (LAPIC_LVTTR);
|
||||
lapic_write (LAPIC_LVTTR, v & ~(1 << 16));
|
||||
}
|
||||
|
||||
/*
|
||||
* Calibrate Local APIC to send interrupts in a set interval.
|
||||
*
|
||||
|
||||
@@ -4,11 +4,19 @@
|
||||
#include <libk/std.h>
|
||||
|
||||
void ioapic_route_irq (uint32_t vec, uint32_t irq, uint64_t flags, uint64_t lapic_id);
|
||||
|
||||
void ioapic_init (void);
|
||||
|
||||
uint32_t lapic_id (void);
|
||||
|
||||
void lapic_eoi (void);
|
||||
|
||||
void lapic_ipi (uint32_t lapic_id, uint32_t vec);
|
||||
|
||||
void lapic_init (uint32_t us);
|
||||
|
||||
void lapic_timer_mask (void);
|
||||
|
||||
void lapic_timer_unmask (void);
|
||||
|
||||
#endif // _KERNEL_AMD64_APIC_H
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <libk/string.h>
|
||||
#include <limine/limine.h>
|
||||
#include <limine/requests.h>
|
||||
#include <mm/liballoc.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <proc/proc.h>
|
||||
#include <proc/reschedule.h>
|
||||
|
||||
@@ -60,6 +60,30 @@ void debugprintf (const char* fmt, ...) {
|
||||
spin_unlock (&serial_lock, f1);
|
||||
}
|
||||
|
||||
void debugprintf_nolock (const char* fmt, ...) {
|
||||
uint64_t f1;
|
||||
|
||||
if (!debug_is_init)
|
||||
return;
|
||||
|
||||
char buffer[BUFFER_SIZE];
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
vsnprintf (buffer, sizeof (buffer), fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
buffer[sizeof (buffer) - 1] = '\0';
|
||||
|
||||
const char* p = buffer;
|
||||
|
||||
while (*p) {
|
||||
debug_serial_write (*p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize serial */
|
||||
void debug_init (void) {
|
||||
outb (PORT_COM1 + 1, 0x00);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <libk/lengthof.h>
|
||||
#include <libk/std.h>
|
||||
#include <libk/string.h>
|
||||
#include <mm/liballoc.h>
|
||||
#include <proc/reschedule.h>
|
||||
#include <sys/debug.h>
|
||||
#include <sys/smp.h>
|
||||
@@ -114,22 +113,22 @@ static void idt_init (void) {
|
||||
extern void intr##n (void); \
|
||||
idt_set (&idt_entries[(n)], (uint64_t)&intr##n, 0x8E, (ist))
|
||||
/* clang-format off */
|
||||
IDT_ENTRY (0, 0); IDT_ENTRY (1, 0); IDT_ENTRY (2, 0); IDT_ENTRY (3, 0);
|
||||
IDT_ENTRY (4, 0); IDT_ENTRY (5, 0); IDT_ENTRY (6, 0); IDT_ENTRY (7, 0);
|
||||
IDT_ENTRY (8, 0); IDT_ENTRY (9, 0); IDT_ENTRY (10, 0); IDT_ENTRY (11, 0);
|
||||
IDT_ENTRY (12, 0); IDT_ENTRY (13, 0); IDT_ENTRY (14, 0); IDT_ENTRY (15, 0);
|
||||
IDT_ENTRY (16, 0); IDT_ENTRY (17, 0); IDT_ENTRY (18, 0); IDT_ENTRY (19, 0);
|
||||
IDT_ENTRY (20, 0); IDT_ENTRY (21, 0); IDT_ENTRY (22, 0); IDT_ENTRY (23, 0);
|
||||
IDT_ENTRY (24, 0); IDT_ENTRY (25, 0); IDT_ENTRY (26, 0); IDT_ENTRY (27, 0);
|
||||
IDT_ENTRY (28, 0); IDT_ENTRY (29, 0); IDT_ENTRY (30, 0); IDT_ENTRY (31, 0);
|
||||
IDT_ENTRY (32, 1); IDT_ENTRY (33, 1); IDT_ENTRY (34, 1); IDT_ENTRY (35, 1);
|
||||
IDT_ENTRY (36, 1); IDT_ENTRY (37, 1); IDT_ENTRY (38, 1); IDT_ENTRY (39, 1);
|
||||
IDT_ENTRY (40, 1); IDT_ENTRY (41, 1); IDT_ENTRY (42, 1); IDT_ENTRY (43, 1);
|
||||
IDT_ENTRY (44, 1); IDT_ENTRY (45, 1); IDT_ENTRY (46, 1); IDT_ENTRY (47, 1);
|
||||
IDT_ENTRY (0, 1); IDT_ENTRY (1, 1); IDT_ENTRY (2, 1); IDT_ENTRY (3, 1);
|
||||
IDT_ENTRY (4, 1); IDT_ENTRY (5, 1); IDT_ENTRY (6, 1); IDT_ENTRY (7, 1);
|
||||
IDT_ENTRY (8, 1); IDT_ENTRY (9, 1); IDT_ENTRY (10, 1); IDT_ENTRY (11, 1);
|
||||
IDT_ENTRY (12, 1); IDT_ENTRY (13, 1); IDT_ENTRY (14, 1); IDT_ENTRY (15, 1);
|
||||
IDT_ENTRY (16, 1); IDT_ENTRY (17, 1); IDT_ENTRY (18, 1); IDT_ENTRY (19, 1);
|
||||
IDT_ENTRY (20, 1); IDT_ENTRY (21, 1); IDT_ENTRY (22, 1); IDT_ENTRY (23, 1);
|
||||
IDT_ENTRY (24, 1); IDT_ENTRY (25, 1); IDT_ENTRY (26, 1); IDT_ENTRY (27, 1);
|
||||
IDT_ENTRY (28, 1); IDT_ENTRY (29, 1); IDT_ENTRY (30, 1); IDT_ENTRY (31, 1);
|
||||
IDT_ENTRY (32, 2); IDT_ENTRY (33, 2); IDT_ENTRY (34, 2); IDT_ENTRY (35, 2);
|
||||
IDT_ENTRY (36, 2); IDT_ENTRY (37, 2); IDT_ENTRY (38, 2); IDT_ENTRY (39, 2);
|
||||
IDT_ENTRY (40, 2); IDT_ENTRY (41, 2); IDT_ENTRY (42, 2); IDT_ENTRY (43, 2);
|
||||
IDT_ENTRY (44, 2); IDT_ENTRY (45, 2); IDT_ENTRY (46, 2); IDT_ENTRY (47, 2);
|
||||
|
||||
IDT_ENTRY (SCHED_PREEMPT_TIMER, 1);
|
||||
IDT_ENTRY (CPU_REQUEST_SCHED, 1);
|
||||
IDT_ENTRY (CPU_SPURIOUS, 1);
|
||||
IDT_ENTRY (SCHED_PREEMPT_TIMER, 2);
|
||||
IDT_ENTRY (CPU_REQUEST_SCHED, 2);
|
||||
IDT_ENTRY (CPU_SPURIOUS, 2);
|
||||
/* clang-format on */
|
||||
#undef IDT_ENTRY
|
||||
|
||||
@@ -141,25 +140,25 @@ static void idt_init (void) {
|
||||
|
||||
/* Handle CPU exception and dump registers. If incoming CS has CPL3, kill the process. */
|
||||
static void intr_exception (struct saved_regs* regs) {
|
||||
DEBUG ("cpu exception %lu (%lu)\n", regs->trap, regs->error);
|
||||
DEBUG_NOLOCK ("cpu exception %lu (%lu)\n", regs->trap, regs->error);
|
||||
|
||||
uint64_t cr2;
|
||||
__asm__ volatile ("movq %%cr2, %0" : "=r"(cr2));
|
||||
uint64_t cr3;
|
||||
__asm__ volatile ("movq %%cr3, %0" : "=r"(cr3));
|
||||
|
||||
debugprintf ("r15=%016lx r14=%016lx r13=%016lx\n"
|
||||
"r12=%016lx r11=%016lx r10=%016lx\n"
|
||||
"r9 =%016lx r8 =%016lx rbp=%016lx\n"
|
||||
"rdi=%016lx rsi=%016lx rdx=%016lx\n"
|
||||
"rcx=%016lx rax=%016lx trp=%016lx\n"
|
||||
"err=%016lx rip=%016lx cs =%016lx\n"
|
||||
"rfl=%016lx rsp=%016lx ss =%016lx\n"
|
||||
"cr2=%016lx cr3=%016lx rbx=%016lx\n",
|
||||
regs->r15, regs->r14, regs->r13, regs->r12, regs->r11, regs->r10, regs->r9, regs->r8,
|
||||
regs->rbp, regs->rdi, regs->rsi, regs->rdx, regs->rcx, regs->rax, regs->trap,
|
||||
regs->error, regs->rip, regs->cs, regs->rflags, regs->rsp, regs->ss, cr2, cr3,
|
||||
regs->rbx);
|
||||
debugprintf_nolock ("r15=%016lx r14=%016lx r13=%016lx\n"
|
||||
"r12=%016lx r11=%016lx r10=%016lx\n"
|
||||
"r9 =%016lx r8 =%016lx rbp=%016lx\n"
|
||||
"rdi=%016lx rsi=%016lx rdx=%016lx\n"
|
||||
"rcx=%016lx rax=%016lx trp=%016lx\n"
|
||||
"err=%016lx rip=%016lx cs =%016lx\n"
|
||||
"rfl=%016lx rsp=%016lx ss =%016lx\n"
|
||||
"cr2=%016lx cr3=%016lx rbx=%016lx\n",
|
||||
regs->r15, regs->r14, regs->r13, regs->r12, regs->r11, regs->r10, regs->r9,
|
||||
regs->r8, regs->rbp, regs->rdi, regs->rsi, regs->rdx, regs->rcx, regs->rax,
|
||||
regs->trap, regs->error, regs->rip, regs->cs, regs->rflags, regs->rsp,
|
||||
regs->ss, cr2, cr3, regs->rbx);
|
||||
|
||||
if (regs->cs == (GDT_UCODE | 0x03)) {
|
||||
struct reschedule_ctx rctx;
|
||||
@@ -177,7 +176,6 @@ static void intr_exception (struct saved_regs* regs) {
|
||||
if (do_thiscpu)
|
||||
cpu_request_sched (thiscpu);
|
||||
} else {
|
||||
__asm__ volatile ("cli");
|
||||
spin ();
|
||||
}
|
||||
}
|
||||
@@ -193,21 +191,27 @@ void intr_handler (void* stack_ptr) {
|
||||
} else {
|
||||
uint64_t ftc, fpc;
|
||||
|
||||
spin_lock (&thiscpu->lock, &ftc);
|
||||
bool user = false;
|
||||
|
||||
struct proc* proc_current = thiscpu->proc_current;
|
||||
if (regs->cs == (GDT_UCODE | 0x3)) {
|
||||
user = true;
|
||||
|
||||
if (proc_current != NULL) {
|
||||
spin_lock (&proc_current->lock, &fpc);
|
||||
memcpy (&proc_current->pdata.regs, regs, sizeof (struct saved_regs));
|
||||
spin_lock (&thiscpu->lock, &ftc);
|
||||
|
||||
fx_save (proc_current->pdata.fx_env);
|
||||
struct proc* proc_current = thiscpu->proc_current;
|
||||
|
||||
spin_unlock (&proc_current->lock, fpc);
|
||||
if (proc_current != NULL) {
|
||||
spin_lock (&proc_current->lock, &fpc);
|
||||
memcpy (&proc_current->pdata.regs, regs, sizeof (struct saved_regs));
|
||||
|
||||
fx_save (proc_current->pdata.fx_env);
|
||||
|
||||
spin_unlock (&proc_current->lock, fpc);
|
||||
}
|
||||
|
||||
spin_unlock (&thiscpu->lock, ftc);
|
||||
}
|
||||
|
||||
spin_unlock (&thiscpu->lock, ftc);
|
||||
|
||||
lapic_eoi ();
|
||||
|
||||
struct irq* irq = irq_find (regs->trap);
|
||||
@@ -217,18 +221,21 @@ void intr_handler (void* stack_ptr) {
|
||||
|
||||
struct reschedule_ctx rctx;
|
||||
memset (&rctx, 0, sizeof (rctx));
|
||||
irq->func (irq->arg, stack_ptr, &rctx);
|
||||
|
||||
bool do_thiscpu = false;
|
||||
for (size_t i = 0; i < lengthof (rctx.cpus); i++) {
|
||||
if (rctx.cpus[i] != NULL && rctx.cpus[i] != thiscpu)
|
||||
cpu_request_sched (rctx.cpus[i]);
|
||||
else
|
||||
do_thiscpu = true;
|
||||
irq->func (irq->arg, stack_ptr, user, &rctx);
|
||||
|
||||
if (user) {
|
||||
bool do_thiscpu = false;
|
||||
for (size_t i = 0; i < lengthof (rctx.cpus); i++) {
|
||||
if (rctx.cpus[i] != NULL && rctx.cpus[i] != thiscpu)
|
||||
cpu_request_sched (rctx.cpus[i]);
|
||||
else
|
||||
do_thiscpu = true;
|
||||
}
|
||||
|
||||
if (do_thiscpu)
|
||||
cpu_request_sched (thiscpu);
|
||||
}
|
||||
|
||||
if (do_thiscpu)
|
||||
cpu_request_sched (thiscpu);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,31 @@ struct saved_regs {
|
||||
uint64_t ss;
|
||||
} PACKED;
|
||||
|
||||
struct ksaved_regs {
|
||||
/* regs */
|
||||
uint64_t r15;
|
||||
uint64_t r14;
|
||||
uint64_t r13;
|
||||
uint64_t r12;
|
||||
uint64_t r11;
|
||||
uint64_t r10;
|
||||
uint64_t r9;
|
||||
uint64_t r8;
|
||||
uint64_t rbx;
|
||||
uint64_t rbp;
|
||||
uint64_t rdi;
|
||||
uint64_t rsi;
|
||||
uint64_t rdx;
|
||||
uint64_t rcx;
|
||||
uint64_t rax;
|
||||
/* interrupt stuff */
|
||||
uint64_t trap;
|
||||
uint64_t error;
|
||||
uint64_t rip;
|
||||
uint64_t cs;
|
||||
uint64_t rflags;
|
||||
} PACKED;
|
||||
|
||||
void idt_load (void);
|
||||
void intr_init (void);
|
||||
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
; \
|
||||
push_regs; \
|
||||
; \
|
||||
movw $0x10, %ax; \
|
||||
movw %ax, %ds; \
|
||||
movw %ax, %es; \
|
||||
; \
|
||||
cld; \
|
||||
; \
|
||||
movq %rsp, %rdi; \
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <libk/std.h>
|
||||
#include <libk/string.h>
|
||||
#include <limine/requests.h>
|
||||
#include <mm/liballoc.h>
|
||||
#include <mm/malloc.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <proc/mutex.h>
|
||||
#include <proc/proc.h>
|
||||
|
||||
@@ -1,55 +1,59 @@
|
||||
#ifndef _KERNEL_AMD64_REGSASM_H
|
||||
#define _KERNEL_AMD64_REGSASM_H
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define push_regs \
|
||||
pushq % rax; \
|
||||
pushq % rcx; \
|
||||
pushq % rdx; \
|
||||
pushq % rsi; \
|
||||
pushq % rdi; \
|
||||
pushq % rbp; \
|
||||
pushq % rbx; \
|
||||
pushq % r8; \
|
||||
pushq % r9; \
|
||||
pushq % r10; \
|
||||
pushq % r11; \
|
||||
pushq % r12; \
|
||||
pushq % r13; \
|
||||
pushq % r14; \
|
||||
pushq % r15;
|
||||
pushq %rax; \
|
||||
pushq %rcx; \
|
||||
pushq %rdx; \
|
||||
pushq %rsi; \
|
||||
pushq %rdi; \
|
||||
pushq %rbp; \
|
||||
pushq %rbx; \
|
||||
pushq %r8; \
|
||||
pushq %r9; \
|
||||
pushq %r10; \
|
||||
pushq %r11; \
|
||||
pushq %r12; \
|
||||
pushq %r13; \
|
||||
pushq %r14; \
|
||||
pushq %r15;
|
||||
|
||||
#define pop_regs \
|
||||
popq % r15; \
|
||||
popq % r14; \
|
||||
popq % r13; \
|
||||
popq % r12; \
|
||||
popq % r11; \
|
||||
popq % r10; \
|
||||
popq % r9; \
|
||||
popq % r8; \
|
||||
popq % rbx; \
|
||||
popq % rbp; \
|
||||
popq % rdi; \
|
||||
popq % rsi; \
|
||||
popq % rdx; \
|
||||
popq % rcx; \
|
||||
popq % rax;
|
||||
popq %r15; \
|
||||
popq %r14; \
|
||||
popq %r13; \
|
||||
popq %r12; \
|
||||
popq %r11; \
|
||||
popq %r10; \
|
||||
popq %r9; \
|
||||
popq %r8; \
|
||||
popq %rbx; \
|
||||
popq %rbp; \
|
||||
popq %rdi; \
|
||||
popq %rsi; \
|
||||
popq %rdx; \
|
||||
popq %rcx; \
|
||||
popq %rax;
|
||||
|
||||
#define pop_regs_skip_rax \
|
||||
popq % r15; \
|
||||
popq % r14; \
|
||||
popq % r13; \
|
||||
popq % r12; \
|
||||
popq % r11; \
|
||||
popq % r10; \
|
||||
popq % r9; \
|
||||
popq % r8; \
|
||||
popq % rbx; \
|
||||
popq % rbp; \
|
||||
popq % rdi; \
|
||||
popq % rsi; \
|
||||
popq % rdx; \
|
||||
popq % rcx; \
|
||||
addq $8, % rsp
|
||||
popq %r15; \
|
||||
popq %r14; \
|
||||
popq %r13; \
|
||||
popq %r12; \
|
||||
popq %r11; \
|
||||
popq %r10; \
|
||||
popq %r9; \
|
||||
popq %r8; \
|
||||
popq %rbx; \
|
||||
popq %rbp; \
|
||||
popq %rdi; \
|
||||
popq %rsi; \
|
||||
popq %rdx; \
|
||||
popq %rcx; \
|
||||
addq $8, %rsp;
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#endif // _KERNEL_AMD64_REGSASM_H
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <sys/smp.h>
|
||||
|
||||
void do_sched (struct proc* proc, spin_lock_t* cpu_lock, uint64_t lockflags) {
|
||||
__asm__ volatile ("cli");
|
||||
|
||||
uint64_t fp;
|
||||
|
||||
spin_lock (&proc->lock, &fp);
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <libk/std.h>
|
||||
#include <libk/string.h>
|
||||
#include <limine/requests.h>
|
||||
#include <mm/liballoc.h>
|
||||
#include <proc/proc.h>
|
||||
#include <proc/reschedule.h>
|
||||
#include <sync/spin_lock.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <amd64/apic.h>
|
||||
#include <amd64/fx.h>
|
||||
#include <amd64/gdt.h>
|
||||
#include <amd64/intr.h>
|
||||
@@ -7,7 +8,7 @@
|
||||
#include <libk/lengthof.h>
|
||||
#include <libk/list.h>
|
||||
#include <libk/string.h>
|
||||
#include <mm/liballoc.h>
|
||||
#include <mm/malloc.h>
|
||||
#include <proc/proc.h>
|
||||
#include <proc/reschedule.h>
|
||||
#include <status.h>
|
||||
@@ -46,9 +47,17 @@ uintptr_t syscall_dispatch (void* stack_ptr) {
|
||||
struct reschedule_ctx rctx;
|
||||
memset (&rctx, 0, sizeof (rctx));
|
||||
|
||||
lapic_timer_mask ();
|
||||
|
||||
__asm__ volatile ("sti");
|
||||
|
||||
uintptr_t r =
|
||||
func (caller, regs, &rctx, regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8, regs->r9);
|
||||
|
||||
__asm__ volatile ("cli");
|
||||
|
||||
lapic_timer_unmask ();
|
||||
|
||||
caller = proc_find_pid (caller_pid);
|
||||
|
||||
if (caller != NULL) {
|
||||
|
||||
@@ -19,11 +19,6 @@ syscall_entry:
|
||||
|
||||
push_regs
|
||||
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %ss
|
||||
|
||||
cld
|
||||
|
||||
movq %rsp, %rdi
|
||||
|
||||
Reference in New Issue
Block a user