From 957b031689658c1ff67ea8a8a04640be9bec2d7d Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Sun, 1 Feb 2015 16:40:00 -0500 Subject: a lot of kernel work --- kernel/idt-as.S | 6 ++ kernel/idt.c | 23 ++++++ kernel/include/gdt.h | 4 +- kernel/include/idt.h | 23 ++++++ kernel/include/irq.h | 21 +++++ kernel/include/isr.h | 46 +++++++++++ kernel/irq-as.S | 139 +++++++++++++++++++++++++++++++++ kernel/irq.c | 84 ++++++++++++++++++++ kernel/isr-as.S | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/isr.c | 48 ++++++++++++ 10 files changed, 605 insertions(+), 2 deletions(-) create mode 100644 kernel/idt-as.S create mode 100644 kernel/idt.c create mode 100644 kernel/include/idt.h create mode 100644 kernel/include/irq.h create mode 100644 kernel/include/isr.h create mode 100644 kernel/irq-as.S create mode 100644 kernel/irq.c create mode 100644 kernel/isr-as.S create mode 100644 kernel/isr.c (limited to 'kernel') diff --git a/kernel/idt-as.S b/kernel/idt-as.S new file mode 100644 index 0000000..d1ab7e2 --- /dev/null +++ b/kernel/idt-as.S @@ -0,0 +1,6 @@ + .global idt_flush + .type idt_flush, @function +idt_flush: # prototype: void idt_flush(uint32) + movl 4(%esp), %eax + lidt (%eax) + ret diff --git a/kernel/idt.c b/kernel/idt.c new file mode 100644 index 0000000..e1ff72f --- /dev/null +++ b/kernel/idt.c @@ -0,0 +1,23 @@ +#include +#include +#include "idt.h" + +void idt_set_gate(uint8_t idx, uint32_t base, uint16_t sel, uint8_t flags) +{ + idt[idx].base_lo = base & 0xFFFF; + idt[idx].base_hi = base >> 16; + idt[idx].sel = sel; + idt[idx].zero = 0; + idt[idx].flags = flags; +} + +void idt_init(void) +{ + printf("idt_init()"); + idt_pt.limit = sizeof(idt) - 1; + idt_pt.base = (uint32_t)&idt; + + memset(&idt, 0, sizeof(idt)); + + idt_flush((uint32_t)&idt_pt); +} diff --git a/kernel/include/gdt.h b/kernel/include/gdt.h index e93c92a..4cf7c4f 100644 --- a/kernel/include/gdt.h +++ b/kernel/include/gdt.h @@ -10,7 +10,7 @@ struct gdt_entry { } __attribute__((packed)); struct gdt_ptr { - uint8_t limit; + uint16_t limit; uint32_t base; } __attribute__((packed)); @@ -18,6 +18,6 @@ struct gdt_entry gdt[3]; struct gdt_ptr gp; /* assembly */ -extern void gdt_flush(struct gdt_ptr*); +extern void gdt_flush(uint32_t); void gdt_init(void); diff --git a/kernel/include/idt.h b/kernel/include/idt.h new file mode 100644 index 0000000..8041025 --- /dev/null +++ b/kernel/include/idt.h @@ -0,0 +1,23 @@ +#include + +struct idt_entry { + uint16_t base_lo; + uint16_t sel; + uint8_t zero; + uint8_t flags; + uint16_t base_hi; +} __attribute__((packed)); + +struct idt_ptr { + uint16_t limit; + uint32_t base; +}; + +struct idt_entry idt[0x100]; +struct idt_ptr idt_pt; + +void idt_init(void); + +extern void idt_flush(uint32_t); + +void idt_set_gate(uint8_t idx, uint32_t base, uint16_t sel, uint8_t flags); diff --git a/kernel/include/irq.h b/kernel/include/irq.h new file mode 100644 index 0000000..1dcbc17 --- /dev/null +++ b/kernel/include/irq.h @@ -0,0 +1,21 @@ +extern void _irq0(void); +extern void _irq1(void); +extern void _irq2(void); +extern void _irq3(void); +extern void _irq4(void); +extern void _irq5(void); +extern void _irq6(void); +extern void _irq7(void); +extern void _irq8(void); +extern void _irq9(void); +extern void _irq10(void); +extern void _irq11(void); +extern void _irq12(void); +extern void _irq13(void); +extern void _irq14(void); +extern void _irq15(void); + +struct regs_t; + +void irq_set_handler(int irq, void (*handler)(struct regs_t*)); +void irq_init(void); diff --git a/kernel/include/isr.h b/kernel/include/isr.h new file mode 100644 index 0000000..d3543af --- /dev/null +++ b/kernel/include/isr.h @@ -0,0 +1,46 @@ +#include + +/* these are all implemented in isr-as.S */ +extern void _isr0(void); +extern void _isr1(void); +extern void _isr2(void); +extern void _isr3(void); +extern void _isr4(void); +extern void _isr5(void); +extern void _isr6(void); +extern void _isr7(void); +extern void _isr8(void); +extern void _isr9(void); +extern void _isr10(void); +extern void _isr11(void); +extern void _isr12(void); +extern void _isr13(void); +extern void _isr14(void); +extern void _isr15(void); +extern void _isr16(void); +extern void _isr17(void); +extern void _isr18(void); +extern void _isr19(void); +extern void _isr20(void); +extern void _isr21(void); +extern void _isr22(void); +extern void _isr23(void); +extern void _isr24(void); +extern void _isr25(void); +extern void _isr26(void); +extern void _isr27(void); +extern void _isr28(void); +extern void _isr29(void); +extern void _isr30(void); +extern void _isr31(void); + +/* installs all the ISR's */ +void isr_init(void); + +/* This defines what the stack looks like after an ISR was running */ +struct regs_t { + uint32_t gs, fs, es, ds; /* pushed the segs last */ + uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */ + uint32_t int_no, err_code; /* our 'push byte #' and ecodes do this */ + uint32_t eip, cs, eflags, useresp, ss; /* pushed by the processor automatically */ +}; diff --git a/kernel/irq-as.S b/kernel/irq-as.S new file mode 100644 index 0000000..12de4b6 --- /dev/null +++ b/kernel/irq-as.S @@ -0,0 +1,139 @@ + .extern irq_handler + +irq_stub: + + pusha + push %ds + push %es + push %fs + push %gs + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %esp, %eax + push %eax + mov $irq_handler, %eax + call *%eax + pop %eax + pop %gs + pop %fs + pop %es + pop %ds + popa + addl $8, %esp + iret + + .global _irq0 + .global _irq1 + .global _irq2 + .global _irq3 + .global _irq4 + .global _irq5 + .global _irq6 + .global _irq7 + .global _irq8 + .global _irq9 + .global _irq10 + .global _irq11 + .global _irq12 + .global _irq13 + .global _irq14 + .global _irq15 + +_irq0: + cli + push $0 + push $32 + jmp irq_stub + +_irq1: + cli + push $0 + push $33 + jmp irq_stub + +_irq2: + cli + push $0 + push $34 + jmp irq_stub + +_irq3: + cli + push $0 + push $35 + jmp irq_stub + +_irq4: + cli + push $0 + push $36 + jmp irq_stub + +_irq5: + cli + push $0 + push $37 + jmp irq_stub + +_irq6: + cli + push $0 + push $38 + jmp irq_stub + +_irq7: + cli + push $0 + push $39 + jmp irq_stub + +_irq8: + cli + push $0 + push $40 + jmp irq_stub + +_irq9: + cli + push $0 + push $41 + jmp irq_stub + +_irq10: + cli + push $0 + push $42 + jmp irq_stub + +_irq11: + cli + push $0 + push $43 + jmp irq_stub + +_irq12: + cli + push $0 + push $44 + jmp irq_stub + +_irq13: + cli + push $0 + push $45 + jmp irq_stub + +_irq14: + cli + push $0 + push $46 + jmp irq_stub + +_irq15: + cli + push $0 + push $47 + jmp irq_stub diff --git a/kernel/irq.c b/kernel/irq.c new file mode 100644 index 0000000..5f0a3f5 --- /dev/null +++ b/kernel/irq.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include "idt.h" +#include "io.h" +#include "irq.h" +#include "isr.h" + +static void *irq_callbacks[16] = { NULL }; + +void irq_set_handler(int irq, void (*handler)(struct regs_t*)) +{ + if(irq < 16 && irq >= 0) + irq_callbacks[irq] = handler; +} + +void irq_reset_handler(int irq) +{ + if(irq < 16 && irq >= 0) + irq_callbacks[irq] = NULL; +} + +void irq_remap(void) +{ + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0x21, 0x20); + outb(0xA1, 0x28); + outb(0x21, 0x04); + outb(0xA1, 0x02); + outb(0x21, 0x01); + outb(0xA1, 0x01); + outb(0x21, 0x0); + outb(0xA1, 0x0); +} + +void irq_init(void) +{ + irq_remap(); + + printf("irq_init()"); + + idt_set_gate(32, (uint32_t)_irq0, 0x08, 0x8E); + idt_set_gate(33, (uint32_t)_irq1, 0x08, 0x8E); + idt_set_gate(34, (uint32_t)_irq2, 0x08, 0x8E); + idt_set_gate(35, (uint32_t)_irq3, 0x08, 0x8E); + idt_set_gate(36, (uint32_t)_irq4, 0x08, 0x8E); + idt_set_gate(37, (uint32_t)_irq5, 0x08, 0x8E); + idt_set_gate(38, (uint32_t)_irq6, 0x08, 0x8E); + idt_set_gate(39, (uint32_t)_irq7, 0x08, 0x8E); + idt_set_gate(40, (uint32_t)_irq8, 0x08, 0x8E); + idt_set_gate(41, (uint32_t)_irq9, 0x08, 0x8E); + idt_set_gate(42, (uint32_t)_irq10, 0x08, 0x8E); + idt_set_gate(43, (uint32_t)_irq11, 0x08, 0x8E); + idt_set_gate(44, (uint32_t)_irq12, 0x08, 0x8E); + idt_set_gate(45, (uint32_t)_irq13, 0x08, 0x8E); + idt_set_gate(46, (uint32_t)_irq14, 0x08, 0x8E); + idt_set_gate(47, (uint32_t)_irq15, 0x08, 0x8E); +} + +void irq_handler(struct regs_t *regs) +{ + void (*handler)(struct regs_t *r); + + handler = irq_callbacks[regs->int_no - 32]; + + printf("IRQ called\n"); + + if(handler) + { + handler(regs); + } + + /* If the IDT entry that was invoked was greater than 40 + * (meaning IRQ8 - 15), then we need to send an EOI to + * the slave controller */ + if (regs->int_no >= 40) + { + outb(0xA0, 0x20); + } + + /* send an EOI to the master controller */ + outb(0x20, 0x20); +} diff --git a/kernel/isr-as.S b/kernel/isr-as.S new file mode 100644 index 0000000..53e15b4 --- /dev/null +++ b/kernel/isr-as.S @@ -0,0 +1,213 @@ +isr_handler: + pusha + push %ds + push %es + push %fs + push %gs + mov $0x10, %ax # Load the Kernel Data Segment descriptor! + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %esp, %eax # Push us the stack + push %eax + mov $isr_handler, %eax + call *%eax + pop %eax + pop %gs + pop %fs + pop %es + pop %ds + popa + add $8, %esp + iret + + # stub ISR's: + .global _isr0 + .global _isr1 + .global _isr2 + .global _isr3 + .global _isr4 + .global _isr5 + .global _isr6 + .global _isr7 + .global _isr8 + .global _isr9 + .global _isr10 + .global _isr11 + .global _isr12 + .global _isr13 + .global _isr14 + .global _isr15 + .global _isr16 + .global _isr17 + .global _isr18 + .global _isr19 + .global _isr20 + .global _isr21 + .global _isr22 + .global _isr23 + .global _isr24 + .global _isr25 + .global _isr26 + .global _isr27 + .global _isr28 + .global _isr29 + .global _isr30 + .global _isr31 +# Interrupts 8, 10, 11, 12, 13, and 14 push error codes onto the stack + +_isr0: + cli + push $0 + push $0 + jmp isr_handler +_isr1: + cli + push $0 + push $1 + jmp isr_handler +_isr2: + cli + push $0 + push $2 + jmp isr_handler +_isr3: + cli + push $0 + push $3 + jmp isr_handler +_isr4: + cli + push $0 + push $4 + jmp isr_handler +_isr5: + cli + push $0 + push $5 + jmp isr_handler +_isr6: + cli + push $0 + push $6 + jmp isr_handler +_isr7: + cli + push $0 + push $7 + jmp isr_handler +_isr8: + cli + push $8 + jmp isr_handler +_isr9: + cli + push $0 + push $9 + jmp isr_handler +_isr10: + cli + push $10 + jmp isr_handler +_isr11: + cli + push $11 + jmp isr_handler +_isr12: + cli + push $12 + jmp isr_handler +_isr13: + cli + push $13 + jmp isr_handler +_isr14: + cli + push $14 + jmp isr_handler +_isr15: + cli + push $0 + push $15 + jmp isr_handler +_isr16: + cli + push $0 + push $16 + jmp isr_handler +_isr17: + cli + push $0 + push $17 + jmp isr_handler +_isr18: + cli + push $0 + push $18 + jmp isr_handler +_isr19: + cli + push $0 + push $19 + jmp isr_handler +_isr20: + cli + push $0 + push $20 + jmp isr_handler +_isr21: + cli + push $0 + push $21 + jmp isr_handler +_isr22: + cli + push $0 + push $22 + jmp isr_handler +_isr23: + cli + push $0 + push $23 + jmp isr_handler +_isr24: + cli + push $0 + push $24 + jmp isr_handler +_isr25: + cli + push $0 + push $25 + jmp isr_handler +_isr26: + cli + push $0 + push $26 + jmp isr_handler +_isr27: + cli + push $0 + push $27 + jmp isr_handler +_isr28: + cli + push $0 + push $28 + jmp isr_handler +_isr29: + cli + push $0 + push $29 + jmp isr_handler +_isr30: + cli + push $0 + push $30 + jmp isr_handler +_isr31: + cli + push $0 + push $31 + jmp isr_handler diff --git a/kernel/isr.c b/kernel/isr.c new file mode 100644 index 0000000..fabbf80 --- /dev/null +++ b/kernel/isr.c @@ -0,0 +1,48 @@ +#include +#include "isr.h" +#include "idt.h" + +void isr_handle(struct regs_t *regs) +{ + if(regs->int_no < 32) + { + printf("received exception!\n"); + } +} + +void isr_init(void) +{ + printf("ISR init"); + idt_set_gate(0, (uint32_t)_isr0, 0x08, 0x8E); + idt_set_gate(1, (uint32_t)_isr1, 0x08, 0x8E); + idt_set_gate(2, (uint32_t)_isr2, 0x08, 0x8E); + idt_set_gate(3, (uint32_t)_isr3, 0x08, 0x8E); + idt_set_gate(4, (uint32_t)_isr4, 0x08, 0x8E); + idt_set_gate(5, (uint32_t)_isr5, 0x08, 0x8E); + idt_set_gate(6, (uint32_t)_isr6, 0x08, 0x8E); + idt_set_gate(7, (uint32_t)_isr7, 0x08, 0x8E); + idt_set_gate(8, (uint32_t)_isr8, 0x08, 0x8E); + idt_set_gate(9, (uint32_t)_isr9, 0x08, 0x8E); + idt_set_gate(10, (uint32_t)_isr10, 0x08, 0x8E); + idt_set_gate(11, (uint32_t)_isr11, 0x08, 0x8E); + idt_set_gate(12, (uint32_t)_isr12, 0x08, 0x8E); + idt_set_gate(13, (uint32_t)_isr13, 0x08, 0x8E); + idt_set_gate(14, (uint32_t)_isr14, 0x08, 0x8E); + idt_set_gate(15, (uint32_t)_isr15, 0x08, 0x8E); + idt_set_gate(16, (uint32_t)_isr16, 0x08, 0x8E); + idt_set_gate(17, (uint32_t)_isr17, 0x08, 0x8E); + idt_set_gate(18, (uint32_t)_isr18, 0x08, 0x8E); + idt_set_gate(19, (uint32_t)_isr19, 0x08, 0x8E); + idt_set_gate(20, (uint32_t)_isr20, 0x08, 0x8E); + idt_set_gate(21, (uint32_t)_isr21, 0x08, 0x8E); + idt_set_gate(22, (uint32_t)_isr22, 0x08, 0x8E); + idt_set_gate(23, (uint32_t)_isr23, 0x08, 0x8E); + idt_set_gate(24, (uint32_t)_isr24, 0x08, 0x8E); + idt_set_gate(25, (uint32_t)_isr25, 0x08, 0x8E); + idt_set_gate(26, (uint32_t)_isr26, 0x08, 0x8E); + idt_set_gate(27, (uint32_t)_isr27, 0x08, 0x8E); + idt_set_gate(28, (uint32_t)_isr28, 0x08, 0x8E); + idt_set_gate(29, (uint32_t)_isr29, 0x08, 0x8E); + idt_set_gate(30, (uint32_t)_isr30, 0x08, 0x8E); + idt_set_gate(31, (uint32_t)_isr31, 0x08, 0x8E); +} -- cgit v1.1