aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/arch.c20
-rw-r--r--arch/x86_64/idt.s47
-rw-r--r--core/idt.c76
-rw-r--r--core/kernel.c15
-rw-r--r--include/garmos/arch.h15
-rw-r--r--include/garmos/idt.h25
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