Обработчик прерываний снова работает

This commit is contained in:
Aren Elchinyan 2023-12-14 11:24:22 +03:00
parent b337fa32f6
commit ffe5b07d83
4 changed files with 1445 additions and 1459 deletions

View File

@ -13,104 +13,72 @@
#include <stdint.h>
#include <tool.h>
static struct idt_desc IDT[IDT_SIZE] __attribute__((aligned(16)));
struct idt_ptr IDT_POINT = { .limit = sizeof(IDT) - 1, .base = (uint64_t)IDT };
static inline void idt_load( ) {
asm volatile("lidt %0" : : "m"(idtr));
}
const char *exception_names[] = { "Деление на ноль",
"Отладка",
"NMI",
"Точка останова",
"Переполнение",
"Выход за границы",
"Недопустимая операция",
"Устройство недоступно",
"Двойное исключение",
NO_NAME,
"Недопустимый TSS",
"Сегмент не присутствует",
"Ошибка сегмента стека",
"Общая защитная ошибка",
"Ошибка страницы",
NO_NAME,
"x87 исключение",
"Проверка выравнивания",
"Ошибка машины",
"SIMD исключение",
"Виртуализация",
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
"Безопасность" };
static void encode_idt_entry(uint8_t vector, void *handler, uint8_t flags) {
uint64_t ptr = (uint64_t)handler;
void exception_handler(struct frame state) {
LOG("\nПОЛУЧЕНО ИСКЛЮЧЕНИЕ: %s\n", exception_names[state.int_number]);
idt[vector].offset_16 = (uint16_t)ptr;
idt[vector].selector = 0x28;
idt[vector].ist = 0;
idt[vector].flags = flags;
idt[vector].offset_middle_16 = (uint16_t)(ptr >> 16);
idt[vector].offset_high_32 = (uint32_t)(ptr >> 32);
idt[vector].reserved = 0;
}
uintptr_t rsp = state.rsp;
static void exception_handler(struct frame state) {
fb_printf("\nПОЛУЧЕНО ИСКЛЮЧЕНИЕ: %s\n", exception_names[state.int_number]);
const uintptr_t stack_bottom = rsp & ~((uintptr_t)4096 - 1);
const uintptr_t stack_top = stack_bottom + 4096;
LOG(" RAX=%x RBX=%x\n"
" RCX=%x RDX=%x\n"
" RSI=%x RDI=%x\n"
" RBP=%x RSP=%x\n"
" R08=%x R09=%x\n"
" R10=%x R11=%x\n"
" R12=%x R13=%x\n"
" R14=%x R15=%x\n"
" RIP=%x RFLAGS=%x\n"
" CS=%x SS=%x\n"
" ERR=%x INT=%u",
state.rax, state.rbx, state.rcx, state.rdx, state.rsi, state.rdi, state.rbp, state.rsp, state.r8, state.r9,
state.r10, state.r11, state.r12, state.r13, state.r14, state.r15, state.rip, state.rflags, state.cs, state.ss,
state.err, state.int_number);
LOG("stack_top = %x\n", stack_top);
fb_printf(" RAX=%x RBX=%x\n"
" RCX=%x RDX=%x\n"
" RSI=%x RDI=%x\n"
" RBP=%x RSP=%x\n"
" R08=%x R09=%x\n"
" R10=%x R11=%x\n"
" R12=%x R13=%x\n"
" R14=%x R15=%x\n"
" RIP=%x RFLAGS=%x\n"
" CS=%x SS=%x\n"
" ERR=%x INT=%u",
state.rax, state.rbx, state.rcx, state.rdx, state.rsi, state.rdi, state.rbp, state.rsp, state.r8,
state.r9, state.r10, state.r11, state.r12, state.r13, state.r14, state.r15, state.rip, state.rflags,
state.cs, state.ss, state.err, state.int_number);
asm volatile("cli; hlt");
}
static void idt_desc_setup(struct idt_desc *desc, unsigned sel, uintptr_t offs, unsigned flags) {
desc->offs0 = offs & 0xfffful;
desc->offs1 = (offs >> 16) & 0xfffful;
desc->offs2 = (offs >> 32) & 0xfffffffful;
desc->sel = sel;
desc->flags = flags;
desc->_reserved = 0;
}
static void idt_load( ) {
struct idt_ptr *ptr = &IDT_POINT;
asm volatile("lidt %0" : : "m"(*ptr));
}
void idt_set_int(uint8_t vector, void *int_handler) {
idt_desc_setup(&IDT[vector], KERNEL_CS, (uintptr_t)int_handler, IDT_INTERRUPT_FLAGS);
idt_load( );
void isr_generic(struct frame state) {
if (state.int_number < 32) {
exception_handler(state);
} else {
// LOG("Обработка прерывания %u\n", state.int_number);
isr[state.int_number](&state);
outb(0x20, 0x20);
}
}
void idt_init( ) {
asm volatile("sti");
asm volatile("cli");
idtr = (idt_ptr_t){ .limit = sizeof(idt) - 1, .base = (uint64_t)idt };
for (int i = 0; i != IDT_EXCEPTIONS; ++i) {
const uintptr_t handler = (uintptr_t)isr_stubs[i];
idt_desc_setup(&IDT[i], KERNEL_CS, handler, IDT_EXCEPTION_FLAGS);
for (uint64_t i = 0; i < 256; i++) {
if (i < 32) {
encode_idt_entry(i, isr_stubs[i], 0x8E);
isr[i] = (void *)exception_handler;
} else {
encode_idt_entry(i, isr_stubs[i], 0x8F);
isr[i] = (void *)isr_generic;
}
}
for (int i = IDT_EXCEPTIONS; i != IDT_SIZE; ++i) {
const uintptr_t handler = (uintptr_t)isr_stubs[i];
idt_desc_setup(&IDT[i], KERNEL_CS, handler, IDT_INTERRUPT_FLAGS);
}
idt_desc_setup(&IDT[255], KERNEL_CS, (uintptr_t)isr_stubs[255], IDT_SPURIOUS_FLAGS);
idt_load( );
LOG("IDT инициализирован\n");
}
void idt_set_int(uint8_t vector, int_entry_t handler) {
isr[vector] = handler;
idt_load( );
}

View File

@ -1,72 +1,61 @@
#include <arch.h>
#include <stdint.h>
#define NO_NAME "Не задано название"
#define KERNEL_CS 0x08
#define KERNEL_DS 0x10
#define KERNEL_CODE_SEG 0x08 // Сегмент кода
#define KERNEL_DATA_SEG 0x10 // Сегмент данных
#define IDT_SIZE 256
#define IDT_SIZE 256 // Количество обработчиков прерываний
#define IDT_EXCEPTIONS 32
#define IDT_DPL(x) (((unsigned)(x)&0x3u) << 13)
#define IDT_KERNEL IDT_DPL(0)
#define IDT_TYPE(x) (((unsigned)(x)&0xfu) << 8)
#define IDT_INT_GATE IDT_TYPE(0xeu)
#define IDT_TRP_FATE IDT_TYPE(0xfu)
#define IDT_PRESENT (1u << 15)
#define IDT_EXCEPTION_FLAGS (IDT_KERNEL | IDT_INT_GATE | IDT_PRESENT)
#define IDT_INTERRUPT_FLAGS (IDT_KERNEL | IDT_INT_GATE | IDT_PRESENT)
#define IDT_SPURIOUS_FLAGS (IDT_KERNEL | IDT_INT_GATE | IDT_PRESENT)
struct frame {
uint64_t rbp;
uint64_t rbx;
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 rax;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
uint64_t int_number;
uint64_t err;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((packed));
typedef void (*exception_handler_t)(void);
typedef void (*interrupt_handler_t)(void);
struct idt_desc {
uint16_t offs0;
uint16_t sel;
uint16_t flags;
uint16_t offs1;
uint32_t offs2;
uint32_t _reserved;
} __attribute__((packed));
struct idt_ptr {
typedef struct __attribute__((packed)) {
uint16_t limit;
uint64_t base;
} __attribute__((packed));
} idt_ptr_t;
struct int_desc {
interrupt_handler_t handler;
int busy;
};
typedef struct __attribute__((packed)) {
uint16_t offset_16;
uint16_t selector;
uint8_t ist;
uint8_t flags;
uint16_t offset_middle_16;
uint32_t offset_high_32;
uint32_t reserved;
} idt_gate_t;
typedef void (*int_entry_t)(void);
extern int_entry_t isr_stubs[];
static idt_gate_t idt[256];
int_entry_t isr[256];
extern void *isr_stubs[];
static idt_ptr_t idtr;
const char *exception_names[] = { "Деление на ноль",
"Отладка",
"NMI",
"Точка останова",
"Переполнение",
"Выход за границы",
"Недопустимая операция",
"Устройство недоступно",
"Двойное исключение",
NO_NAME,
"Недопустимый TSS",
"Сегмент не присутствует",
"Ошибка сегмента стека",
"Общая защитная ошибка",
"Ошибка страницы",
NO_NAME,
"x87 исключение",
"Проверка выравнивания",
"Ошибка машины",
"SIMD исключение",
"Виртуализация",
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
"Безопасность" };

File diff suppressed because it is too large Load Diff

28
kernel/arch/pic.c Normal file
View File

@ -0,0 +1,28 @@
/**
* pic.c
* Программируемый контроллер прерываний
*
* Настройка PIC (Программируемый контроллер прерываний)
*
*/
#include <arch.h>
#include <fb.h>
void pic_init( ) {
outb(0x20, 0x11);
outb(0xA0, 0x11);
io_wait( );
outb(0x21, 0x20);
outb(0xA1, 0x28);
io_wait( );
outb(0x21, 0x04);
outb(0xA1, 0x02);
io_wait( );
outb(0x21, 0x01);
outb(0xA1, 0x01);
io_wait( );
outb(0x21, 0x00);
outb(0xA1, 0x00);
LOG("Программируемый контроллер прерываний инициализирован\n");
}