From cbab36dd2b3aae169f21839984463b2bf41b9531 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 25 Mar 2019 17:04:33 +0200 Subject: [PATCH] [amd64] timer irq --- conf/make/amd64.mk | 4 ++- src/arch/amd64/hw/idt.c | 6 ++++ src/arch/amd64/hw/int_macros.inc | 36 +++++++++++++++++++ src/arch/amd64/hw/irq0.S | 17 +++++++++ src/arch/amd64/hw/pic8259.c | 62 ++++++++++++++++++++++++++++++++ src/arch/amd64/hw/pic8259.h | 4 +++ src/arch/amd64/kernel.c | 9 +++++ 7 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 src/arch/amd64/hw/irq0.S create mode 100644 src/arch/amd64/hw/pic8259.c create mode 100644 src/arch/amd64/hw/pic8259.h diff --git a/conf/make/amd64.mk b/conf/make/amd64.mk index 10e17d5..a76e74b 100644 --- a/conf/make/amd64.mk +++ b/conf/make/amd64.mk @@ -10,7 +10,9 @@ OBJS+=$(O)/arch/amd64/kernel.o \ $(O)/arch/amd64/hw/idt.o \ $(O)/arch/amd64/hw/ints.o \ $(O)/arch/amd64/hw/exc.o \ - $(O)/arch/amd64/hw/regs.o + $(O)/arch/amd64/hw/regs.o \ + $(O)/arch/amd64/hw/irq0.o \ + $(O)/arch/amd64/hw/pic8259.o kernel_OBJS=$(O)/arch/amd64/entry.o \ $(OBJS) kernel_LINKER=$(S)/arch/amd64/link.ld diff --git a/src/arch/amd64/hw/idt.c b/src/arch/amd64/hw/idt.c index cabaff7..11d6c51 100644 --- a/src/arch/amd64/hw/idt.c +++ b/src/arch/amd64/hw/idt.c @@ -1,4 +1,5 @@ #include "ints.h" +#include "pic8259.h" #include "sys/mem.h" #include #include @@ -52,6 +53,9 @@ extern void amd64_isr_29(); extern void amd64_isr_30(); extern void amd64_isr_31(); +// 8259 PIC IRQs +extern void amd64_irq_0(); + typedef struct { uint16_t base_lo; uint16_t selector; @@ -119,5 +123,7 @@ void amd64_idt_init(void) { amd64_idt_set(30, (uintptr_t) amd64_isr_30, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32); amd64_idt_set(31, (uintptr_t) amd64_isr_31, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32); + amd64_idt_set(IRQ_BASE + 0, (uintptr_t) amd64_irq_0, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32); + asm volatile ("lea idtr(%%rip), %%rax; lidt (%%rax)":::"memory"); } diff --git a/src/arch/amd64/hw/int_macros.inc b/src/arch/amd64/hw/int_macros.inc index b8121e8..1611b73 100644 --- a/src/arch/amd64/hw/int_macros.inc +++ b/src/arch/amd64/hw/int_macros.inc @@ -35,3 +35,39 @@ mov %ds, %rax pushq %rax .endm + +.macro __int_pop_ctx + // segments + pop %rax + mov %rax, %ds + pop %rax + mov %rax, %es + pop %rax + mov %rax, %fs + pop %rax + mov %rax, %gs + + // cr3 + pop %rax + mov %rax, %cr3 + + // r15-r8 + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + + // popal + pop %rdi + pop %rsi + pop %rbp + pop %rax // Ignore rsp + pop %rbx + pop %rdx + pop %rcx + pop %rax +.endm diff --git a/src/arch/amd64/hw/irq0.S b/src/arch/amd64/hw/irq0.S new file mode 100644 index 0000000..f29954f --- /dev/null +++ b/src/arch/amd64/hw/irq0.S @@ -0,0 +1,17 @@ +#include "int_macros.inc" + +.section .text +.global amd64_irq_0 +amd64_irq_0: + cli + + __int_push_ctx + + // EOI + mov $0x20, %dx + mov $0x20, %al + outb %al, %dx + + __int_pop_ctx + + iretq diff --git a/src/arch/amd64/hw/pic8259.c b/src/arch/amd64/hw/pic8259.c new file mode 100644 index 0000000..a431d94 --- /dev/null +++ b/src/arch/amd64/hw/pic8259.c @@ -0,0 +1,62 @@ +#include "pic8259.h" +#include "io.h" + +#define PIC_MCMD 0x20 +#define PIC_MDAT 0x21 +#define PIC_SCMD 0xA0 +#define PIC_SDAT 0xA1 +#define PIC_EOI 0x20 + +#define PIC_ICW1_ICW4 0x01 +#define PIC_ICW1_SINGLE 0x02 +#define PIC_ICW1_INTERVAL4 0x04 +#define PIC_ICW1_LEVEL 0x08 +#define PIC_ICW1_INIT 0x10 + +#define PIC_ICW4_8086 0x01 +#define PIC_ICW4_AUTO 0x02 +#define PIC_ICW4_BUF_SLAVE 0x08 +#define PIC_ICW4_BUF_MASTER 0x0C +#define PIC_ICW4_SFNM 0x10 + +void pic8259_clear_mask(uint8_t line) { + uint16_t port; + uint8_t value; + + if (line < 8) { + port = PIC_MDAT; + } else { + port = PIC_SDAT; + line -= 8; + } + value = inb(port) & ~(1 << line); + outb(port, value); +} + +void pic8259_init(void) { + uint8_t a1, a2; + a1 = inb(PIC_MDAT); + a2 = inb(PIC_SDAT); + + outb(PIC_MCMD, PIC_ICW1_INIT | PIC_ICW1_ICW4); + io_wait(); + outb(PIC_SCMD, PIC_ICW1_INIT | PIC_ICW1_ICW4); + io_wait(); + outb(PIC_MDAT, IRQ_BASE); + io_wait(); + outb(PIC_SDAT, IRQ_BASE + 8); + io_wait(); + outb(PIC_MDAT, 4); + io_wait(); + outb(PIC_SDAT, 2); + io_wait(); + + outb(PIC_MDAT, PIC_ICW4_8086); + io_wait(); + outb(PIC_SDAT, PIC_ICW4_8086); + io_wait(); + + outb(PIC_MDAT, a1); + outb(PIC_SDAT, a2); +} + diff --git a/src/arch/amd64/hw/pic8259.h b/src/arch/amd64/hw/pic8259.h new file mode 100644 index 0000000..9d1aba0 --- /dev/null +++ b/src/arch/amd64/hw/pic8259.h @@ -0,0 +1,4 @@ +#pragma once +#define IRQ_BASE 32 + +void pic8259_init(void); diff --git a/src/arch/amd64/kernel.c b/src/arch/amd64/kernel.c index e4eb634..d72aef0 100644 --- a/src/arch/amd64/kernel.c +++ b/src/arch/amd64/kernel.c @@ -1,13 +1,22 @@ #include "sys/mm.h" #include "sys/debug.h" #include "arch/amd64/hw/gdt.h" +#include "arch/amd64/hw/pic8259.h" #include "arch/amd64/hw/ints.h" +// TODO: move to some util header +#define __wfe() asm volatile ("sti; hlt") + void kernel_main(void) { kdebug("Booting\n"); // Memory management amd64_mm_init(); amd64_gdt_init(); + pic8259_init(); amd64_idt_init(); + + while (1) { + __wfe(); + } }