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
This commit is contained in:
Reto Buerki 2015-02-13 11:16:51 +01:00 committed by Christian Helmuth
parent 6e0f1a4466
commit c7cadf52a6
5 changed files with 162 additions and 0 deletions

View File

@ -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

View File

@ -17,6 +17,7 @@
#include <util/register.h>
#include <kernel/interface_support.h>
#include <cpu/cpu_state.h>
#include <idt.h>
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;

View File

@ -0,0 +1,54 @@
#ifndef _IDT_H_
#define _IDT_H_
#include <base/stdint.h>
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_ */

View File

@ -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<uint64_t>(_table))));
}

View File

@ -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