started on isr/idt stuff
This commit is contained in:
58
kernel/idt.c
Normal file
58
kernel/idt.c
Normal file
@@ -0,0 +1,58 @@
|
||||
#include <stdint.h>
|
||||
#include <idt.h>
|
||||
|
||||
#define IDT_MAX_DESCRIPTORS 256
|
||||
|
||||
#define ATTR_KERN_32 0x8E // active(1), ring 0 (00), interrupt gate(0), 32 bit (1110)
|
||||
|
||||
#define SEGMENT_KERN 0x08
|
||||
|
||||
extern void load_idt(void);
|
||||
extern void enable_int(void);
|
||||
|
||||
extern void isr0();
|
||||
extern void isr1();
|
||||
extern void isr8();
|
||||
extern void isr13();
|
||||
extern void isr14();
|
||||
extern void isr32();
|
||||
extern void isr33();
|
||||
|
||||
void* isr_stub_table[256] = {
|
||||
[0] = isr0,
|
||||
[1] = isr1,
|
||||
[8] = isr8,
|
||||
[13] = isr13,
|
||||
[14] = isr14,
|
||||
[32] = isr32,
|
||||
[33] = isr33,
|
||||
};
|
||||
|
||||
idt_entry idt[IDT_MAX_DESCRIPTORS];
|
||||
idt_ptr idtr;
|
||||
|
||||
void set_idtr(uint8_t vector, void* isr, uint8_t attributes) {
|
||||
idt_entry* desc = &idt[vector];
|
||||
|
||||
desc->isr_low = (uint32_t)isr & 0xFFFF;
|
||||
desc->kernel_cs = SEGMENT_KERN;
|
||||
desc->reserved = 0;
|
||||
desc->attributes = attributes;
|
||||
desc->isr_high = ((uint32_t)isr >> 16) & 0xFFFF;
|
||||
}
|
||||
|
||||
void init_idt() {
|
||||
idtr.limit = (sizeof(idt_entry) * IDT_MAX_DESCRIPTORS) - 1;
|
||||
idtr.base = (uint32_t)&idt;
|
||||
|
||||
for (int i = 0; i < IDT_MAX_DESCRIPTORS; i++) {
|
||||
if (isr_stub_table[i] != 0) {
|
||||
set_idtr(i, isr_stub_table[i], ATTR_KERN_32);
|
||||
} else {
|
||||
set_idtr(i, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
load_idt();
|
||||
enable_int();
|
||||
}
|
||||
19
kernel/idt.h
Normal file
19
kernel/idt.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef KIDT_H
|
||||
#define KIDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
||||
uint16_t kernel_cs; // The GDT segment selector the CPU will load into CS
|
||||
uint8_t reserved; // Set to 0
|
||||
uint8_t attributes;// Type and attributes flags
|
||||
uint16_t isr_high; // The higher 16 bits of the ISR's address
|
||||
} idt_entry __attribute__((packed));
|
||||
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint32_t base;
|
||||
} idt_ptr __attribute__((packed));
|
||||
|
||||
#endif
|
||||
54
kernel/idt_stubs.s
Normal file
54
kernel/idt_stubs.s
Normal file
@@ -0,0 +1,54 @@
|
||||
.code32
|
||||
|
||||
.macro ISR_NOERRCODE num
|
||||
.global isr\num
|
||||
isr\num:
|
||||
pushl $0
|
||||
pushl $\num
|
||||
jmp isr_common_stub
|
||||
.endm
|
||||
|
||||
.macro ISR_ERRCODE num
|
||||
.global isr\num
|
||||
isr\num:
|
||||
pushl $\num
|
||||
jmp isr_common_stub
|
||||
.endm
|
||||
|
||||
.extern common_interrupt_handler
|
||||
isr_common_stub:
|
||||
pushal
|
||||
|
||||
pushl %esp
|
||||
call common_interrupt_handler
|
||||
addl $4, %esp
|
||||
|
||||
popal
|
||||
addl $8, %esp
|
||||
iret
|
||||
|
||||
.global master_eoi
|
||||
master_eoi:
|
||||
movb $0x20, %al
|
||||
outb %al, $0x20
|
||||
ret
|
||||
|
||||
.extern idtr
|
||||
.global load_idt
|
||||
load_idt:
|
||||
lidt idtr
|
||||
ret
|
||||
|
||||
.global enable_int
|
||||
enable_int:
|
||||
sti
|
||||
ret
|
||||
|
||||
ISR_NOERRCODE 0 # Divide by Zero
|
||||
ISR_NOERRCODE 1 # Debug
|
||||
ISR_ERRCODE 8 # Double Fault (Has Error Code!)
|
||||
ISR_ERRCODE 13 # General Protection Fault (Has Error Code!)
|
||||
ISR_ERRCODE 14 # Page Fault (Has Error Code!)
|
||||
|
||||
ISR_NOERRCODE 32 # IRQ0 - Timer
|
||||
ISR_NOERRCODE 33 # IRQ1 - Keyboard
|
||||
46
kernel/interrupts.c
Normal file
46
kernel/interrupts.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "lib/print.h"
|
||||
#include <stdint.h>
|
||||
|
||||
extern void master_eoi(void);
|
||||
|
||||
struct registers {
|
||||
uint32_t edi, esi, ebp, esp_dummy, ebx, edx, ecx, eax;
|
||||
|
||||
uint32_t int_no;
|
||||
uint32_t error_code;
|
||||
|
||||
uint32_t eip, cs, eflags, useresp, ss;
|
||||
};
|
||||
|
||||
const char* err_messages[32] = {
|
||||
[0] = "Divide by 0",
|
||||
[1] = "",
|
||||
[8] = "",
|
||||
[13] = "General Protection Fault",
|
||||
[14] = "Page Fault",
|
||||
};
|
||||
|
||||
void common_interrupt_handler(struct registers *regs) {
|
||||
switch (regs->int_no) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 8:
|
||||
case 13:
|
||||
case 14:
|
||||
kprint("CPU Error: ");
|
||||
kprint(err_messages[regs->int_no]);
|
||||
kprint("\n");
|
||||
break;
|
||||
case 32:
|
||||
// wake the PIC timer driver
|
||||
master_eoi();
|
||||
break;
|
||||
case 33:
|
||||
// wake the keyboard driver
|
||||
master_eoi();
|
||||
break;
|
||||
default:
|
||||
kprint("Received unhandled interrupt\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,13 @@
|
||||
#include <lib/print.h>
|
||||
#include <lib/stream.h>
|
||||
|
||||
#include <idt.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern void init_idt();
|
||||
extern idt_entry create_idt_entry(uint32_t addr, uint16_t segment, uint8_t attributes);
|
||||
|
||||
void kernel_main(void)
|
||||
{
|
||||
extern print_stream_t vga_print_stream;
|
||||
@@ -9,4 +16,6 @@ void kernel_main(void)
|
||||
kout->trunc();
|
||||
|
||||
kprint("RockOS booting...");
|
||||
|
||||
init_idt();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user