kernel: x86-64 idt

This commit is contained in:
Matheus
2023-04-08 21:13:43 -03:00
parent ef2d0fc874
commit 7b58504b01
6 changed files with 151 additions and 10 deletions
+41
View File
@@ -0,0 +1,41 @@
#include <arch/idt.h>
#include <stdint.h>
#include <stddef.h>
typedef struct {
uint16_t size;
uint64_t offset;
} __attribute__((packed)) idtr_t;
typedef struct {
uint16_t offset;
uint16_t segment;
uint8_t ist;
uint8_t flags;
uint16_t offset2;
uint32_t offset3;
} __attribute__((packed)) idtentry_t;
static idtentry_t idt[256];
static idtr_t idtr = {
.size = sizeof(idt) - 1,
.offset = (uint64_t)idt
};
extern const uint64_t isr_table[256];
void arch_idt_setup() {
for (int i = 0; i < 256; ++i) {
idt[i].offset = isr_table[i] & 0xffff;
idt[i].segment = 0x8;
idt[i].ist = 0;
idt[i].flags = 0x8e;
idt[i].offset2 = (isr_table[i] >> 16) & 0xffff;
idt[i].offset3 = (isr_table[i] >> 32) & 0xffffffff;
}
}
void arch_idt_reload() {
asm volatile("lidt (%%rax)" : : "a"(&idtr));
}
+89
View File
@@ -0,0 +1,89 @@
section .text
%assign i 0
%rep 256
isr_%+ i:
; push an error code if the cpu did not
%if (i == 8 || i == 10 || i == 11 || i == 12 || i == 13 || i == 14) == 0
push qword 0
%endif
; check if swapgs is needed
cmp qword [rsp+16], 0x18
jne .notneeded1
swapgs
.notneeded1:
; push context
push rsi
push rdi
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rdx
push rcx
push rbx
push rax
mov rax, ds
push rax
mov rax, es
push rax
mov rax, fs
push rax
mov rax, gs
push rax
mov rdi,cr2
push rdi
; save ctx pointer and interrupt vector number
mov rdi, i
mov rsi, rsp
cld
extern interrupt_isr
call interrupt_isr
; pop context
add rsp, 24 ; cr2 gs and fs are not popped.
pop rax
mov es,rax
pop rax
mov ds,rax
pop rax
pop rbx
pop rcx
pop rdx
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
pop rdi
pop rsi
pop rbp
add rsp,8 ; remove error code
; check if swapgs is needed
cmp qword [rsp+8], 0x18
jne .notneeded2
swapgs
.notneeded2:
iret
%assign i i+1
%endrep
section .rodata
global isr_table
isr_table:
%assign i 0
%rep 256
dq isr_%+ i
%endrep
+3
View File
@@ -2,6 +2,7 @@
#include <logging.h>
#include <arch/cpu.h>
#include <arch/gdt.h>
#include <arch/idt.h>
static cpu_t bsp_cpu;
@@ -9,5 +10,7 @@ void kernel_entry() {
cpu_set(&bsp_cpu);
logging_sethook(arch_e9_putc);
arch_gdt_reload();
arch_idt_setup();
arch_idt_reload();
__assert(!"kernel entry end");
}
+5 -3
View File
@@ -3,6 +3,8 @@
#include <stdbool.h>
#include <arch/context.h>
#ifdef __x86_64__
#define MAX_ISR_COUNT 256
#else
@@ -11,15 +13,15 @@
struct _isr_t;
typedef struct _isr_t {
void (*func)(struct _isr_t *self); // TODO pass register context as argument as well.
void (*func)(struct _isr_t *self, context_t *ctx);
void (*eoi)(struct _isr_t *self);
long id;
long priority;
bool pending;
} isr_t;
void interrupt_register(int vector, void (*func)(isr_t *self), void (*eoi)(isr_t *self), long priority); // TODO pass register context as well.
isr_t *interrupt_allocate(void (*func)(isr_t *self), void (*eoi)(isr_t *self), long priority); // TODO pass register context as well.
void interrupt_register(int vector, void (*func)(isr_t *self, context_t *ctx), void (*eoi)(isr_t *self), long priority);
isr_t *interrupt_allocate(void (*func)(isr_t *self, context_t *ctx), void (*eoi)(isr_t *self), long priority);
void interrupt_raiseipl(long newipl);
void interrupt_loweripl(long newipl);
+7
View File
@@ -0,0 +1,7 @@
#ifndef _IDT_H
#define _IDT_h
void arch_idt_reload();
void arch_idt_setup();
#endif
+6 -7
View File
@@ -1,19 +1,19 @@
#include <kernel/interrupt.h>
#include <logging.h>
#include <arch/cpu.h>
#include <arch/context.h>
// TODO pass register context as well
void interrupt_isr(int vec) {
void interrupt_isr(int vec, context_t *ctx) {
isr_t *isr = &_cpu()->isr[vec];
__assert(isr->func);
// TODO ipl check
isr->func(isr); // TODO pass context
isr->func(isr, ctx);
if (isr->eoi)
isr->eoi(isr);
}
// TODO pass register context as well.
void interrupt_register(int vector, void (*func)(isr_t *self), void (*eoi)(isr_t *self), long priority) {
void interrupt_register(int vector, void (*func)(isr_t *self, context_t *ctx), void (*eoi)(isr_t *self), long priority) {
isr_t *isr = &_cpu()->isr[vector];
isr->func = func;
isr->eoi = eoi;
@@ -21,8 +21,7 @@ void interrupt_register(int vector, void (*func)(isr_t *self), void (*eoi)(isr_t
isr->priority = priority;
}
// TODO pass register context as well.
isr_t *interrupt_allocate(void (*func)(isr_t *self), void (*eoi)(isr_t *self), long priority) {
isr_t *interrupt_allocate(void (*func)(isr_t *self, context_t *ctx), void (*eoi)(isr_t *self), long priority) {
isr_t *isr = NULL;
for (int i = 0; i < MAX_ISR_COUNT; ++i) {