Load IDT.
This commit is contained in:
parent
f29ddf75d4
commit
f860ec1ef0
4
Makefile
4
Makefile
@ -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
6
console.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console.h"
|
||||||
|
#include "drivers/vga.h"
|
||||||
|
|
||||||
|
void printk(const char* msg) {
|
||||||
|
vga_print_string(msg);
|
||||||
|
}
|
||||||
138
cpu/idt.c
Normal file
138
cpu/idt.c
Normal 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
47
cpu/isr.h
Normal 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
51
cpu/vectors.S
Normal 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
|
||||||
3
kernel.c
3
kernel.c
@ -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();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user