mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-28 19:37:12 +00:00
Add notes to self on exceptions.
This commit is contained in:
parent
cfba8aeb89
commit
4247da9118
@ -30,40 +30,38 @@ struct Descriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void set(const uint16_t descriptor[4]) {
|
void set(const uint16_t descriptor[4]) {
|
||||||
// TODO: something.
|
|
||||||
|
|
||||||
base_ = uint32_t(descriptor[1] | ((descriptor[2] & 0xff) << 16));
|
base_ = uint32_t(descriptor[1] | ((descriptor[2] & 0xff) << 16));
|
||||||
limit_ = descriptor[0];
|
limit_ = descriptor[0];
|
||||||
|
|
||||||
printf("%04x %04x %04x %04x\n", descriptor[0], descriptor[1], descriptor[2], descriptor[3]);
|
printf("%04x %04x %04x %04x\n", descriptor[0], descriptor[1], descriptor[2], descriptor[3]);
|
||||||
|
|
||||||
|
present_ = descriptor[2] & 0x8000;
|
||||||
|
privilege_level_ = (descriptor[2] >> 13) & 3;
|
||||||
|
|
||||||
|
// TODO: need to know more about the below.
|
||||||
if(descriptor[2] & 0x1000) {
|
if(descriptor[2] & 0x1000) {
|
||||||
// Is segment descriptor.
|
|
||||||
present_ = descriptor[2] & 0x8000;
|
|
||||||
privilege_level_ = (descriptor[2] >> 13) & 3;
|
|
||||||
accessed_ = descriptor[2] & 0x100;
|
|
||||||
readable_ = descriptor[2] & 0x200;
|
|
||||||
conforming_ = descriptor[2] & 0x400;
|
|
||||||
executable_ = descriptor[2] & 0x800;
|
executable_ = descriptor[2] & 0x800;
|
||||||
|
|
||||||
|
if(executable_) {
|
||||||
|
conforming_ = descriptor[2] & 0x400;
|
||||||
|
readable_ = descriptor[2] & 0x200;
|
||||||
|
} else {
|
||||||
|
// expand down = descriptor[2] & 0x400;
|
||||||
|
// writeable_ = descriptor[2] & 0x200;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 286:
|
|
||||||
// 47...32 = 16-bit limit;
|
|
||||||
// 31 = P
|
|
||||||
// 30...29 = DPL
|
|
||||||
// 28 = S
|
|
||||||
// 27...24 = type;
|
|
||||||
// 23...00 = 4-bit base.
|
|
||||||
|
|
||||||
uint32_t to_linear(const uint32_t address) const {
|
uint32_t to_linear(const uint32_t address) const {
|
||||||
return base_ + address;
|
return base_ + address;
|
||||||
}
|
}
|
||||||
|
uint32_t base() const { return base_; }
|
||||||
|
uint32_t limit() const { return limit_; }
|
||||||
|
|
||||||
uint32_t base() const {
|
int privilege_level() const {
|
||||||
return base_;
|
return privilege_level_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -71,8 +69,7 @@ private:
|
|||||||
uint32_t limit_;
|
uint32_t limit_;
|
||||||
// TODO: permissions, type, etc.
|
// TODO: permissions, type, etc.
|
||||||
|
|
||||||
bool present_;
|
int privilege_level_;
|
||||||
uint8_t privilege_level_;
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
AvailableTaskStateSegment = 1,
|
AvailableTaskStateSegment = 1,
|
||||||
LDTDescriptor = 2,
|
LDTDescriptor = 2,
|
||||||
@ -85,7 +82,8 @@ private:
|
|||||||
Reserved9 = 9, ReservedA = 10, ReservedB = 11, ReservedC = 12,
|
Reserved9 = 9, ReservedA = 10, ReservedB = 11, ReservedC = 12,
|
||||||
ReservedD = 13, ReservedE = 14, ReservedF = 15,
|
ReservedD = 13, ReservedE = 14, ReservedF = 15,
|
||||||
} type_;
|
} type_;
|
||||||
bool accessed_;
|
|
||||||
|
bool present_;
|
||||||
bool readable_;
|
bool readable_;
|
||||||
bool conforming_;
|
bool conforming_;
|
||||||
bool executable_;
|
bool executable_;
|
||||||
|
@ -33,4 +33,17 @@ enum Interrupt {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ProtectedException {
|
||||||
|
Interrupt cause;
|
||||||
|
uint16_t code;
|
||||||
|
|
||||||
|
// Code:
|
||||||
|
// b3–b15: IDT/GDT/LDT entry
|
||||||
|
// b2: 1 => in LDT; 0 => in GDT;
|
||||||
|
// b1: 1 => in IDT, ignore b2; 0 => use b2;
|
||||||
|
// b0:
|
||||||
|
// 1 => trigger was external to program code;
|
||||||
|
// 0 => trigger was caused by the instruction described by the CS:IP that is on the stack.
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
namespace PCCompatible {
|
namespace PCCompatible {
|
||||||
|
|
||||||
|
// TODO: the following need to apply linear memory semantics, including potential A20 wrapping.
|
||||||
template <InstructionSet::x86::Model model> struct ProgramFetcher {
|
template <InstructionSet::x86::Model model> struct ProgramFetcher {
|
||||||
std::pair<const uint8_t *, size_t> next_code(
|
std::pair<const uint8_t *, size_t> next_code(
|
||||||
const Registers<model> ®isters,
|
const Registers<model> ®isters,
|
||||||
@ -26,11 +27,11 @@ template <InstructionSet::x86::Model model> struct ProgramFetcher {
|
|||||||
LinearMemory<model> &linear_memory
|
LinearMemory<model> &linear_memory
|
||||||
) const {
|
) const {
|
||||||
const uint16_t ip = registers.ip();
|
const uint16_t ip = registers.ip();
|
||||||
const uint32_t start =
|
const auto &descriptor = segments.descriptors[InstructionSet::x86::Source::CS];
|
||||||
segments.descriptors[InstructionSet::x86::Source::CS].to_linear(ip) & (linear_memory.MaxAddress - 1);
|
const uint32_t start = descriptor.to_linear(ip) & (linear_memory.MaxAddress - 1);
|
||||||
return std::make_pair(
|
return std::make_pair(
|
||||||
linear_memory.at(start),
|
linear_memory.at(start),
|
||||||
std::min<size_t>(linear_memory.MaxAddress - start, 0x10000 - ip)
|
std::min<size_t>(linear_memory.MaxAddress - start, 1 + descriptor.limit() - ip)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,10 +39,11 @@ template <InstructionSet::x86::Model model> struct ProgramFetcher {
|
|||||||
const Segments<model> &segments,
|
const Segments<model> &segments,
|
||||||
LinearMemory<model> &linear_memory
|
LinearMemory<model> &linear_memory
|
||||||
) const {
|
) const {
|
||||||
const auto base = segments.descriptors[InstructionSet::x86::Source::CS].base();
|
const auto &descriptor = segments.descriptors[InstructionSet::x86::Source::CS];
|
||||||
|
const auto base = descriptor.base() & (linear_memory.MaxAddress - 1);
|
||||||
return std::make_pair(
|
return std::make_pair(
|
||||||
linear_memory.at(base),
|
linear_memory.at(base),
|
||||||
std::min<size_t>(0x1'0000, linear_memory.MaxAddress - base)
|
std::min<size_t>(0x1'0000, 1 + descriptor.limit() - base)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,12 +43,23 @@ public:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Mode::Protected286: {
|
case Mode::Protected286: {
|
||||||
// TODO: when to use the local table? Is this right?
|
// Check privilege level.
|
||||||
assert(!(value & 0x8000));
|
const auto requested_privilege_level = value & 3;
|
||||||
const auto &table = registers_.template get<DescriptorTable::Global>();
|
if(requested_privilege_level < descriptors[Source::CS].privilege_level()) {
|
||||||
const uint32_t table_address = table.base + value;
|
printf("TODO: privilege exception.");
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: authorisation required, possibly.
|
// Check segment range.
|
||||||
|
const auto &table =
|
||||||
|
(value & 4) ?
|
||||||
|
registers_.template get<DescriptorTable::Local>() :
|
||||||
|
registers_.template get<DescriptorTable::Global>();
|
||||||
|
const uint32_t table_address = table.base + (value & ~7);
|
||||||
|
if(table_address > table.base + table.limit - 8) {
|
||||||
|
printf("TODO: descriptor table overrun exception.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get descriptor contents.
|
||||||
using AccessType = InstructionSet::x86::AccessType;
|
using AccessType = InstructionSet::x86::AccessType;
|
||||||
const uint32_t table_end = table.base + table.limit;
|
const uint32_t table_end = table.base + table.limit;
|
||||||
const uint16_t entry[] = {
|
const uint16_t entry[] = {
|
||||||
@ -57,7 +68,20 @@ public:
|
|||||||
memory_.template access<uint16_t, AccessType::Read>(table_address + 4, table_end),
|
memory_.template access<uint16_t, AccessType::Read>(table_address + 4, table_end),
|
||||||
memory_.template access<uint16_t, AccessType::Read>(table_address + 6, table_end)
|
memory_.template access<uint16_t, AccessType::Read>(table_address + 6, table_end)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: is this descriptor privilege within reach?
|
||||||
|
// TODO: is this an empty descriptor*? If so: exception!
|
||||||
|
// (* other than the 0 descriptor, which can be loaded to DS or ES)
|
||||||
|
// TODO:
|
||||||
|
// bool is_compatible(const Source reg) const {
|
||||||
|
// switch(reg)
|
||||||
|
// DS/ES: either readable code, or any sort of data
|
||||||
|
// SS: writeable data
|
||||||
|
// CS: any sort of code
|
||||||
|
// }
|
||||||
|
|
||||||
descriptors[segment].set(entry);
|
descriptors[segment].set(entry);
|
||||||
|
// TODO: set descriptor accessed bit in memory if it's a segment.
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user