diff options
-rw-r--r-- | arch/x86_64/arch.c | 20 | ||||
-rw-r--r-- | arch/x86_64/idt.s | 47 | ||||
-rw-r--r-- | core/idt.c | 76 | ||||
-rw-r--r-- | core/kernel.c | 15 | ||||
-rw-r--r-- | include/garmos/arch.h | 15 | ||||
-rw-r--r-- | include/garmos/idt.h | 25 |
6 files changed, 195 insertions, 3 deletions
diff --git a/arch/x86_64/arch.c b/arch/x86_64/arch.c index d7762c2..a8c1417 100644 --- a/arch/x86_64/arch.c +++ b/arch/x86_64/arch.c @@ -15,6 +15,16 @@ #include <garmos/arch.h> #include <garmos/types.h> +void irqhdl0x00(void); +void irqhdl0x01(void); + +uint8_t irqnos[3] = { 0x20, 0x21, 0 }; +uint32_t irqhdls[3] = { + (uint32_t) &irqhdl0x00, + (uint32_t) &irqhdl0x01, + 0 +}; + void prtset8(const uint16_t port, const uint8_t val) { asm volatile("outb %0, %1" : : "a" (val), "Nd" (port)); @@ -79,3 +89,13 @@ void gdtset(struct gdtp gdtp) { asm volatile("lgdt %0" : : "m" (gdtp)); } + +void idtset(struct idtp idtp) +{ + asm volatile("lidt %0" : : "m" (idtp)); +} + +void idtact(void) +{ + asm("sti"); +} diff --git a/arch/x86_64/idt.s b/arch/x86_64/idt.s new file mode 100644 index 0000000..ead5b20 --- /dev/null +++ b/arch/x86_64/idt.s @@ -0,0 +1,47 @@ +.set IRQ_BASE, 0x20 + +.section .text +.extern handle_interrput +.global irqign + +.macro gen_irq_handler num +.global irqhdl\num\() +irqhdl\num\(): +movb $\num + IRQ_BASE, (intrptno) +jmp _bot +.endm + +gen_irq_handler 0x00 +gen_irq_handler 0x01 + +_bot: +/* store current data */ +push %ebp +push %edi +push %esi +push %edx +push %ecx +push %ebx +push %eax + +/* call interrupt handler */ +push %esp +push (intrptno) +call kernel_handle_interrupt +movl %eax, %esp + +/* restore previous data */ +pop %eax +pop %ebx +pop %ecx +pop %edx +pop %esi +pop %edi +pop %ebp + +irqign: +/* continue */ +iret + +.data +intrptno: .byte 0 diff --git a/core/idt.c b/core/idt.c new file mode 100644 index 0000000..a20eb69 --- /dev/null +++ b/core/idt.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 Robin Krahl <robin.krahl@ireas.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <garmos/arch.h> +#include <garmos/gdt.h> +#include <garmos/idt.h> +#include <garmos/kernel.h> +#include <garmos/types.h> + +#define IDT_GATE_COUNT 256 + +struct idt_gate { + uint16_t handler_lo; + uint16_t gdt_offset; + uint8_t reserved; + uint8_t access; + uint16_t handler_hi; +} __attribute__((packed)); + +struct idt_gate idt[IDT_GATE_COUNT]; + +struct idtp idtp = { + .limit = IDT_GATE_COUNT * sizeof(*idt) - 1, + .pointer = idt, +}; + +static void idt_set(uint8_t no, uint16_t offset, uint32_t handler, + uint8_t access, uint8_t flags); + +void idt_init(void) +{ + uint32_t offset = gdt_get_code_offset(); + uint32_t i; + uint8_t *no = irqnos; + uint32_t *addr = irqhdls; + + ker_dbg("Initializing IDT ..."); + + for (i = 0; i < IDT_GATE_COUNT; i++) + idt_set(i, offset, (uint32_t) &irqign, 0, 0xE); + + for (; *no; no++, addr++) { + if (!*addr) + continue; + ker_dbg("Registerung IRQ handler ..."); + idt_set(*no, offset, *addr, 0, 0xE); + } + + idtset(idtp); +} + +void idt_activate(void) +{ + idtact(); +} + +static void idt_set(uint8_t no, uint16_t offset, uint32_t handler, + uint8_t access, uint8_t flags) +{ + idt[no].handler_lo = handler & 0xFFFF; + idt[no].handler_hi = (handler >> 16) & 0xFFFF; + idt[no].gdt_offset = offset; + idt[no].reserved = 0; + idt[no].access = 0x80 | flags | ((access & 0x3) << 5); +} diff --git a/core/kernel.c b/core/kernel.c index c159aef..098db12 100644 --- a/core/kernel.c +++ b/core/kernel.c @@ -12,24 +12,33 @@ * more details. */ +#include <garmos/idt.h> #include <garmos/gdt.h> #include <garmos/kernel.h> #include <garmos/term.h> #include <garmos/types.h> - void ker_dbg(char *s) { term_print(s); term_print("\n"); } +uint32_t kernel_handle_interrupt(uint8_t no, uint32_t esp) +{ + return esp; +} + void kernel_main(uint32_t multiboot, unsigned int *magicno) { + term_clear(); + gdt_init(); + idt_init(); + + idt_activate(); - term_clear(); term_print("garmos 0.1.0\n\n"); - while(1); + while (1); } diff --git a/include/garmos/arch.h b/include/garmos/arch.h index 6d0f54d..ff1627e 100644 --- a/include/garmos/arch.h +++ b/include/garmos/arch.h @@ -44,4 +44,19 @@ struct gdtp { } __attribute__((packed)); void gdtset(struct gdtp gdtp); +/* interrupt description table initialization and activation */ +struct idtp { + uint16_t limit; + void *pointer; +} __attribute((packed)); +void idtset(struct idtp idtp); +void idtact(void); + +/* interrupt handler for ignores and a list of handlers to register */ +extern uint8_t irqnos[]; +extern uint32_t irqhdls[]; +void irqign(void); +void irqhdl0x00(void); +void irqhdl0x01(void); + #endif diff --git a/include/garmos/idt.h b/include/garmos/idt.h new file mode 100644 index 0000000..05fb1bd --- /dev/null +++ b/include/garmos/idt.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2017 Robin Krahl <robin.krahl@ireas.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef GARMOS_IDT_H +#define GARMOS_IDT_H + +#include <garmos/types.h> + +void idt_init(void); +void idt_activate(void); + +uint32_t idt_handle_interrupt(uint8_t no, uint32_t esp); + +#endif |