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:
parent
6e0f1a4466
commit
c7cadf52a6
|
@ -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/mode_transition.s
|
||||||
SRC_S += spec/x86_64/kernel/crt0.s
|
SRC_S += spec/x86_64/kernel/crt0.s
|
||||||
SRC_S += spec/x86_64/crt0.s
|
SRC_S += spec/x86_64/crt0.s
|
||||||
|
SRC_S += spec/x86_64/isr.s
|
||||||
|
|
||||||
# add C++ sources
|
# add C++ sources
|
||||||
SRC_CC += spec/x86_64/kernel/thread_base.cc
|
SRC_CC += spec/x86_64/kernel/thread_base.cc
|
||||||
|
SRC_CC += spec/x86_64/idt.cc
|
||||||
|
|
||||||
# include less specific configuration
|
# include less specific configuration
|
||||||
include $(REP_DIR)/lib/mk/x86/core.inc
|
include $(REP_DIR)/lib/mk/x86/core.inc
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <util/register.h>
|
#include <util/register.h>
|
||||||
#include <kernel/interface_support.h>
|
#include <kernel/interface_support.h>
|
||||||
#include <cpu/cpu_state.h>
|
#include <cpu/cpu_state.h>
|
||||||
|
#include <idt.h>
|
||||||
|
|
||||||
namespace Genode
|
namespace Genode
|
||||||
{
|
{
|
||||||
|
@ -37,6 +38,16 @@ class Genode::Cpu
|
||||||
{
|
{
|
||||||
public:
|
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 exception_entry = 0x0; /* XXX */
|
||||||
static constexpr addr_t mtc_size = 1 << 13;
|
static constexpr addr_t mtc_size = 1 << 13;
|
||||||
|
|
||||||
|
|
|
@ -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_ */
|
|
@ -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))));
|
||||||
|
}
|
|
@ -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
|
Loading…
Reference in New Issue