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");
|
: "%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 */
|
} /* namespace kernel */
|
||||||
|
|
|
||||||
|
|
@ -9,24 +9,24 @@
|
||||||
|
|
||||||
namespace kernel {
|
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
|
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. */
|
/** A four bit value describing the type of the segment. */
|
||||||
enum class Type {
|
enum class Type {
|
||||||
// Data segment types
|
// Data segment types
|
||||||
|
|
@ -93,4 +93,47 @@ private:
|
||||||
Descriptor table[Size];
|
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 */
|
} /* namespace kernel */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue