Add IDT class for managing the interrupt table
This commit is contained in:
parent
d2cfbfd45d
commit
00e961435e
2 changed files with 142 additions and 15 deletions
|
@ -140,4 +140,88 @@ GDT::load()
|
|||
: "%eax");
|
||||
}
|
||||
|
||||
/*
|
||||
* Static
|
||||
*/
|
||||
|
||||
IDT&
|
||||
IDT::systemIDT()
|
||||
{
|
||||
static IDT sIDT;
|
||||
return sIDT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Public
|
||||
*/
|
||||
|
||||
Descriptor
|
||||
IDT::DescriptorSpec::descriptor()
|
||||
const
|
||||
{
|
||||
Descriptor descriptor = 0;
|
||||
|
||||
if (type != Type::Task) {
|
||||
descriptor = offset & 0xFFFF0000;
|
||||
}
|
||||
|
||||
const auto p = uint8_t(isPresent);
|
||||
const auto dpl = uint8_t(privilegeLevel);
|
||||
const auto d = uint8_t((type == Type::Task) ? 0 : is32BitGate);
|
||||
const auto typ = uint8_t(type);
|
||||
|
||||
descriptor |= p << 15;
|
||||
descriptor |= dpl << 13;
|
||||
descriptor |= d << 11;
|
||||
descriptor |= typ << 8;
|
||||
|
||||
// Shift everything up by 32 to make room for the lower 4 bytes
|
||||
descriptor <<= 32;
|
||||
|
||||
descriptor |= segment << 16;
|
||||
|
||||
if (type != Type::Task) {
|
||||
descriptor |= offset & 0x0000FFFF;
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
|
||||
IDT::IDT()
|
||||
: mTable{0}
|
||||
{ }
|
||||
|
||||
|
||||
void
|
||||
IDT::setDescriptor(size_t index,
|
||||
const DescriptorSpec& spec)
|
||||
{
|
||||
if (index >= Size) {
|
||||
return;
|
||||
}
|
||||
mTable[index] = spec.descriptor();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
IDT::setNullDescriptor(size_t index)
|
||||
{
|
||||
if (index >= Size) {
|
||||
return;
|
||||
}
|
||||
mTable[index] = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
IDT::load()
|
||||
const
|
||||
{
|
||||
PseudoDescriptor idt{Size * sizeof(Descriptor) - 1, uint32_t(&mTable)};
|
||||
asm volatile(
|
||||
"lidt %0\n"
|
||||
: : "m" (idt) :);
|
||||
}
|
||||
|
||||
} /* namespace kernel */
|
||||
|
|
|
@ -9,24 +9,24 @@
|
|||
|
||||
namespace kernel {
|
||||
|
||||
void initGDT();
|
||||
/**
|
||||
* SegmentDescriptors are entries in the GDT and LDT that describe memory
|
||||
* segments. Each descriptor is two double-words (8 bytes, 64 bits) long.
|
||||
*/
|
||||
typedef uint64_t Descriptor;
|
||||
|
||||
|
||||
/** Descriptor privilege level. */
|
||||
enum class DPL {
|
||||
Ring0 = 0x0,
|
||||
Ring1 = 0x1,
|
||||
Ring2 = 0x2,
|
||||
Ring3 = 0x3
|
||||
};
|
||||
|
||||
|
||||
struct GDT
|
||||
{
|
||||
/**
|
||||
* SegmentDescriptors are entries in the GDT and LDT that describe memory
|
||||
* segments. Each descriptor is two double-words (8 bytes, 64 bits) long.
|
||||
*/
|
||||
typedef uint64_t Descriptor;
|
||||
|
||||
/** Descriptor privilege level. */
|
||||
enum class DPL {
|
||||
Ring0 = 0x0,
|
||||
Ring1 = 0x1,
|
||||
Ring2 = 0x2,
|
||||
Ring3 = 0x3
|
||||
};
|
||||
|
||||
/** A four bit value describing the type of the segment. */
|
||||
enum class Type {
|
||||
// Data segment types
|
||||
|
@ -93,4 +93,47 @@ private:
|
|||
Descriptor table[Size];
|
||||
};
|
||||
|
||||
|
||||
struct IDT
|
||||
{
|
||||
enum class Type {
|
||||
Task = 0x5,
|
||||
Interrupt = 0x6,
|
||||
Trap = 0x7,
|
||||
};
|
||||
|
||||
struct DescriptorSpec
|
||||
{
|
||||
uint16_t segment;
|
||||
uint32_t offset;
|
||||
bool isPresent;
|
||||
DPL privilegeLevel;
|
||||
bool is32BitGate;
|
||||
Type type;
|
||||
|
||||
Descriptor descriptor() const;
|
||||
};
|
||||
|
||||
static IDT& systemIDT();
|
||||
|
||||
IDT();
|
||||
|
||||
/** Set the descriptor at the given `index` to the value of `spec`. */
|
||||
void setDescriptor(size_t index, const DescriptorSpec& spec);
|
||||
|
||||
/** Set the descriptor at the given `index` to the NULL descriptor. */
|
||||
void setNullDescriptor(size_t index);
|
||||
|
||||
void load() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Size of the table. IDTs shouldn't have any more than this many
|
||||
* descriptors.
|
||||
*/
|
||||
static const size_t Size = 256;
|
||||
|
||||
Descriptor mTable[Size];
|
||||
};
|
||||
|
||||
} /* namespace kernel */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue