From c7cadf52a649e30ec59a89dc7abc5621424c93ad Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 13 Feb 2015 11:16:51 +0100 Subject: [PATCH] hw_x86_64: setup ISR and IDT * Add isr.s assembler file: The file declares an array of Interrupt Service Routines (ISR) to handle the exception vectors from 0 to 19, see Intel SDM Vol. 3A, section 6.3.1. * Add Idt class: * The class Genode::Idt represents an Interrupt Descriptor Table as specified by Intel SDM Vol. 3A, section 6.10. * The setup function initializes the IDT with 20 entries using the ISR array defined in the isr.s assembly file. * Setup and load IDT in Genode::Cpu ctor: The Idt::setup function is only executed once on the BSP. * Declare ISRs for interrupts 20-255 * Set IDT size to 256 --- repos/base-hw/lib/mk/x86_64/core.mk | 2 + repos/base-hw/src/core/include/spec/x86/cpu.h | 11 ++++ .../src/core/include/spec/x86_64/idt.h | 54 ++++++++++++++++++ repos/base-hw/src/core/spec/x86_64/idt.cc | 38 +++++++++++++ repos/base-hw/src/core/spec/x86_64/isr.s | 57 +++++++++++++++++++ 5 files changed, 162 insertions(+) create mode 100644 repos/base-hw/src/core/include/spec/x86_64/idt.h create mode 100644 repos/base-hw/src/core/spec/x86_64/idt.cc create mode 100644 repos/base-hw/src/core/spec/x86_64/isr.s diff --git a/repos/base-hw/lib/mk/x86_64/core.mk b/repos/base-hw/lib/mk/x86_64/core.mk index cde4cb00b..7a390a77b 100644 --- a/repos/base-hw/lib/mk/x86_64/core.mk +++ b/repos/base-hw/lib/mk/x86_64/core.mk @@ -12,9 +12,11 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/x86_64 SRC_S += spec/x86_64/mode_transition.s SRC_S += spec/x86_64/kernel/crt0.s SRC_S += spec/x86_64/crt0.s +SRC_S += spec/x86_64/isr.s # add C++ sources SRC_CC += spec/x86_64/kernel/thread_base.cc +SRC_CC += spec/x86_64/idt.cc # include less specific configuration include $(REP_DIR)/lib/mk/x86/core.inc diff --git a/repos/base-hw/src/core/include/spec/x86/cpu.h b/repos/base-hw/src/core/include/spec/x86/cpu.h index cc65380a2..f828c1f11 100644 --- a/repos/base-hw/src/core/include/spec/x86/cpu.h +++ b/repos/base-hw/src/core/include/spec/x86/cpu.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace Genode { @@ -37,6 +38,16 @@ class Genode::Cpu { public: + Cpu() + { + /* Setup IDT only once */ + if (primary_id() == executing_id()) { + Idt::setup(); + } + + Idt::load(); + } + static constexpr addr_t exception_entry = 0x0; /* XXX */ static constexpr addr_t mtc_size = 1 << 13; diff --git a/repos/base-hw/src/core/include/spec/x86_64/idt.h b/repos/base-hw/src/core/include/spec/x86_64/idt.h new file mode 100644 index 000000000..ac1353a41 --- /dev/null +++ b/repos/base-hw/src/core/include/spec/x86_64/idt.h @@ -0,0 +1,54 @@ +#ifndef _IDT_H_ +#define _IDT_H_ + +#include + +namespace Genode +{ + /** + * Interrupt Descriptor Table (IDT) + * See Intel SDM Vol. 3A, section 6.10 + */ + class Idt; +} + +class Genode::Idt +{ + private: + + enum { + SIZE_IDT = 256, + }; + + /** + * 64-Bit Mode IDT gate, see Intel SDM Vol. 3A, section 6.14.1. + */ + struct gate + { + uint16_t offset_15_00; + uint16_t segment_sel; + uint16_t flags; + uint16_t offset_31_16; + uint32_t offset_63_32; + uint32_t reserved; + }; + + /** + * IDT table + */ + static gate _table[]; + + public: + + /** + * Setup IDT. + */ + static void setup(); + + /** + * Load IDT into IDTR. + */ + static void load(); +}; + +#endif /* _IDT_H_ */ diff --git a/repos/base-hw/src/core/spec/x86_64/idt.cc b/repos/base-hw/src/core/spec/x86_64/idt.cc new file mode 100644 index 000000000..18ab0f93f --- /dev/null +++ b/repos/base-hw/src/core/spec/x86_64/idt.cc @@ -0,0 +1,38 @@ +#include "idt.h" + +using namespace Genode; + +extern uint64_t _isr_array[]; + +class Descriptor +{ + private: + uint16_t _limit; + uint64_t _base; + + public: + Descriptor(uint16_t l, uint64_t b) : _limit(l), _base (b) {}; +} __attribute__((packed)); + +__attribute__((aligned(8))) Idt::gate Idt::_table[SIZE_IDT]; + + +void Idt::setup() +{ + uint64_t *isrs = _isr_array; + + for (unsigned vec = 0; vec < SIZE_IDT; vec++, isrs++) { + _table[vec].offset_15_00 = *isrs & 0xffff; + _table[vec].segment_sel = 8; + _table[vec].flags = 0x8e00; + _table[vec].offset_31_16 = (*isrs >> 16) & 0xffff; + _table[vec].offset_63_32 = (*isrs >> 32) & 0xffff; + } +} + + +void Idt::load() +{ + asm volatile ("lidt %0" : : "m" (Descriptor (sizeof (_table) - 1, + reinterpret_cast(_table)))); +} diff --git a/repos/base-hw/src/core/spec/x86_64/isr.s b/repos/base-hw/src/core/spec/x86_64/isr.s new file mode 100644 index 000000000..d4093e206 --- /dev/null +++ b/repos/base-hw/src/core/spec/x86_64/isr.s @@ -0,0 +1,57 @@ +.data +.global _isr_array +_isr_array: + +.text + +.macro _isr_entry + .align 4, 0x90 +1: .data + .quad 1b + .previous +.endm + +.macro _exception_with_code vector + _isr_entry + push $\vector + jmp _dispatch_interrupt +.endm + +.macro _exception vector + _isr_entry + push $0 + push $\vector + jmp _dispatch_interrupt +.endm + +/* interrupt dispatcher */ +_dispatch_interrupt: +hlt +jmp _dispatch_interrupt + +_exception 0 +_exception 1 +_exception 2 +_exception 3 +_exception 4 +_exception 5 +_exception 6 +_exception 7 +_exception_with_code 8 +_exception 9 +_exception_with_code 10 +_exception_with_code 11 +_exception_with_code 12 +_exception_with_code 13 +_exception_with_code 14 +_exception 15 +_exception 16 +_exception_with_code 17 +_exception 18 +_exception 19 + +.set vec, 20 +.rept 236 +_exception vec +.set vec, vec + 1 +.endr