Load IDT.

This commit is contained in:
Alexander Myltsev 2022-11-20 18:59:53 +03:00
parent f29ddf75d4
commit f860ec1ef0
7 changed files with 250 additions and 2 deletions

View File

@ -25,7 +25,7 @@ fs.img: kernel.bin tools/mkfs
image.bin: mbr.bin fs.img image.bin: mbr.bin fs.img
cat $^ >$@ cat $^ >$@
kernel.bin: kernel.o drivers/vga.o string.o drivers/ata.o kernel.bin: kernel.o console.o drivers/vga.o string.o drivers/ata.o cpu/vectors.o cpu/idt.o
$(LD) -m elf_i386 -o $@ -Ttext 0x1000 $^ $(LD) -m elf_i386 -o $@ -Ttext 0x1000 $^
%.o: %.c %.o: %.c
@ -41,7 +41,7 @@ mbr.elf: mbr.o
$(LD) -m elf_i386 -Ttext=0x7c00 $^ -o $@ $(LD) -m elf_i386 -Ttext=0x7c00 $^ -o $@
clean: clean:
rm -f *.elf *.bin *.o tools/mkfs rm -f *.elf *.bin *.o */*.o tools/mkfs
tools/%: tools/%.c tools/%: tools/%.c
gcc -Wall -Werror -g $^ -o $@ gcc -Wall -Werror -g $^ -o $@

6
console.c Normal file
View File

@ -0,0 +1,6 @@
#include "console.h"
#include "drivers/vga.h"
void printk(const char* msg) {
vga_print_string(msg);
}

3
console.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void printk(const char* msg);

138
cpu/idt.c Normal file
View File

@ -0,0 +1,138 @@
#include "isr.h"
#include "../drivers/port.h"
#include "../console.h"
enum {
IDT_HANDLERS = 256,
};
typedef struct {
uint16_t low_offset;
uint16_t selector;
uint8_t always0;
uint8_t flags;
uint16_t high_offset;
} __attribute__((packed)) idt_gate_t;
idt_gate_t idt[IDT_HANDLERS];
#define low_16(address) (uint16_t)((address) & 0xFFFF)
#define high_16(address) (uint16_t)(((address) >> 16) & 0xFFFF)
void set_idt_gate(int n, uint32_t handler) {
idt[n].low_offset = low_16(handler);
idt[n].selector = 0x08; // see GDT
idt[n].always0 = 0;
// 0x8E = 1 00 0 1 110
// P DPL 0 D Type
idt[n].flags = 0x8E;
idt[n].high_offset = high_16(handler);
}
// defined in vectors.S
extern uint32_t default_handlers[IDT_HANDLERS];
void init_idt() {
for (int i = 0; i < IDT_HANDLERS; i++) {
set_idt_gate(i, default_handlers[i]);
}
}
const char *exception_messages[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
};
#define ARRLEN(a) (sizeof(a) / sizeof(a[0]))
isr_t interrupt_handlers[IDT_HANDLERS];
void trap(registers_t *r) {
if (r->int_no < 32) {
const char* msg = "Reserved";
if (r->int_no < ARRLEN(exception_messages)) {
msg = exception_messages[r->int_no];
}
printk(msg);
printk("\n");
}
/* Handle the interrupt in a more modular way */
if (interrupt_handlers[r->int_no] != 0) {
isr_t handler = interrupt_handlers[r->int_no];
handler(r);
}
// EOI
if (r->int_no >= 40) {
port_byte_out(0xA0, 0x20); /* follower */
}
if (r->int_no >= 32) {
port_byte_out(0x20, 0x20); /* leader */
}
}
static void init_pic() {
// ICW1
port_byte_out(0x20, 0x11);
port_byte_out(0xA0, 0x11);
// ICW2
port_byte_out(0x21, 0x20);
port_byte_out(0xA1, 0x28);
// ICW3
port_byte_out(0x21, 0x04);
port_byte_out(0xA1, 0x02);
// ICW4
port_byte_out(0x21, 0x01);
port_byte_out(0xA1, 0x01);
// OCW1
port_byte_out(0x21, 0x0);
port_byte_out(0xA1, 0x0);
}
typedef struct {
uint16_t limit;
void* base;
} __attribute__((packed)) idt_register_t;
static idt_register_t idt_reg;
void load_idt() {
init_idt();
init_pic();
idt_reg.base = &idt;
idt_reg.limit = sizeof(idt) - 1;
asm("lidt %0" : : "m"(idt_reg));
}
void cli() {
asm("cli");
}
void sti() {
asm("sti");
}

47
cpu/isr.h Normal file
View File

@ -0,0 +1,47 @@
#pragma once
#include <stdint.h>
enum {
IRQ0 = 32,
IRQ1,
IRQ2,
IRQ3,
IRQ4,
IRQ5,
IRQ6,
IRQ7,
IRQ8,
IRQ9,
IRQ10,
IRQ11,
IRQ12,
IRQ13,
IRQ14,
IRQ15,
};
/* Struct which aggregates many registers.
* It matches exactly the pushes on interrupt.asm. From the bottom:
* - Pushed by the processor automatically
* - `push byte`s on the isr-specific code: error code, then int number
* - All the registers by pusha
* - `push eax` whose lower 16-bits contain DS
*/
typedef struct {
uint32_t ds; /* Data segment selector */
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */
uint32_t int_no, err_code; /* Interrupt number and error code (if applicable) */
uint32_t eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */
} registers_t;
void isr_install();
void isr_handler(registers_t *r);
typedef void (*isr_t)(registers_t *);
void register_interrupt_handler(uint8_t n, isr_t handler);
void load_idt();
void cli();
void sti();

51
cpu/vectors.S Normal file
View File

@ -0,0 +1,51 @@
alltraps:
# Build trap frame.
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushal
mov $10, %ax
mov %ax, %ds
# Call trap(tf), where tf=%esp
pushl %esp
call trap
add $4, %esp
popal
popl %gs
popl %fs
popl %es
popl %ds
addl $0x8, %esp # trapno and errcode
iret
.macro handler i
vector\i :
.if (!(\i == 8 || (\i >= 10 && \i <= 14) || \i == 17))
pushl $0
.endif
pushl $\i
jmp alltraps
.endm
.altmacro
.macro irq_insertX number
.section .text
handler \number
.section .data
.long vector\number
.endm
.section .data
.global default_handlers
default_handlers:
.set i,0
.rept 256
irq_insertX %i
.set i, i+1
.endr

View File

@ -1,10 +1,13 @@
asm(".asciz \"kernel start\""); asm(".asciz \"kernel start\"");
#include "cpu/isr.h"
#include "drivers/vga.h" #include "drivers/vga.h"
#include "drivers/ata.h" #include "drivers/ata.h"
#include "drivers/misc.h" #include "drivers/misc.h"
void _start() { void _start() {
load_idt();
sti();
char buf[512]; char buf[512];
vga_clear_screen(); vga_clear_screen();