mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
GDT and GPF changes to track down Vbox bugs
This commit is contained in:
@@ -9,28 +9,27 @@
|
|||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
enum class gdt_flags : uint8_t
|
enum class gdt_type : uint8_t
|
||||||
{
|
{
|
||||||
ac = 0x01,
|
accessed = 0x01,
|
||||||
rw = 0x02,
|
read_write = 0x02,
|
||||||
dc = 0x04,
|
conforming = 0x04,
|
||||||
ex = 0x08,
|
execute = 0x08,
|
||||||
r1 = 0x20,
|
system = 0x10,
|
||||||
r2 = 0x40,
|
ring1 = 0x20,
|
||||||
r3 = 0x60,
|
ring2 = 0x40,
|
||||||
pr = 0x80,
|
ring3 = 0x60,
|
||||||
|
present = 0x80
|
||||||
res_1 = 0x10
|
|
||||||
};
|
};
|
||||||
IS_BITFIELD(gdt_flags);
|
IS_BITFIELD(gdt_type);
|
||||||
|
|
||||||
struct gdt_descriptor
|
struct gdt_descriptor
|
||||||
{
|
{
|
||||||
uint16_t limit_low;
|
uint16_t limit_low;
|
||||||
uint16_t base_low;
|
uint16_t base_low;
|
||||||
uint8_t base_mid;
|
uint8_t base_mid;
|
||||||
uint8_t flags;
|
gdt_type type;
|
||||||
uint8_t granularity;
|
uint8_t size;
|
||||||
uint8_t base_high;
|
uint8_t base_high;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
@@ -104,18 +103,17 @@ get_irq(unsigned vector)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_gdt_entry(uint8_t i, uint32_t base, uint32_t limit, bool is64, gdt_flags flags)
|
set_gdt_entry(uint8_t i, uint32_t base, uint64_t limit, bool is64, gdt_type type)
|
||||||
{
|
{
|
||||||
g_gdt_table[i].limit_low = limit & 0xffff;
|
g_gdt_table[i].limit_low = limit & 0xffff;
|
||||||
|
g_gdt_table[i].size = (limit >> 16) & 0xf;
|
||||||
|
g_gdt_table[i].size |= (is64 ? 0xa0 : 0xc0);
|
||||||
|
|
||||||
g_gdt_table[i].base_low = base & 0xffff;
|
g_gdt_table[i].base_low = base & 0xffff;
|
||||||
g_gdt_table[i].base_mid = (base >> 16) & 0xff;
|
g_gdt_table[i].base_mid = (base >> 16) & 0xff;
|
||||||
g_gdt_table[i].base_high = (base >> 24) & 0xff;
|
g_gdt_table[i].base_high = (base >> 24) & 0xff;
|
||||||
|
|
||||||
g_gdt_table[i].granularity =
|
g_gdt_table[i].type = type | gdt_type::system | gdt_type::present;
|
||||||
((limit >> 16) & 0xf) | (is64 ? 0xa0 : 0xc0);
|
|
||||||
|
|
||||||
g_gdt_table[i].flags = static_cast<uint8_t>(flags | gdt_flags::res_1 | gdt_flags::pr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -170,13 +168,13 @@ interrupts_init()
|
|||||||
g_gdtr.limit = sizeof(g_gdt_table) - 1;
|
g_gdtr.limit = sizeof(g_gdt_table) - 1;
|
||||||
g_gdtr.base = reinterpret_cast<uint64_t>(&g_gdt_table);
|
g_gdtr.base = reinterpret_cast<uint64_t>(&g_gdt_table);
|
||||||
|
|
||||||
set_gdt_entry(1, 0, 0xfffff, false, gdt_flags::rw);
|
set_gdt_entry(1, 0, 0xfffff, false, gdt_type::read_write);
|
||||||
set_gdt_entry(2, 0, 0xfffff, false, gdt_flags::rw | gdt_flags::ex | gdt_flags::dc);
|
set_gdt_entry(2, 0, 0xfffff, false, gdt_type::read_write | gdt_type::execute | gdt_type::conforming);
|
||||||
set_gdt_entry(3, 0, 0xfffff, false, gdt_flags::rw);
|
set_gdt_entry(3, 0, 0xfffff, false, gdt_type::read_write);
|
||||||
set_gdt_entry(4, 0, 0xfffff, false, gdt_flags::rw | gdt_flags::ex);
|
set_gdt_entry(4, 0, 0xfffff, false, gdt_type::read_write | gdt_type::execute);
|
||||||
|
|
||||||
set_gdt_entry(6, 0, 0xfffff, false, gdt_flags::rw);
|
set_gdt_entry(6, 0, 0xfffff, false, gdt_type::read_write);
|
||||||
set_gdt_entry(7, 0, 0xfffff, true, gdt_flags::rw | gdt_flags::ex);
|
set_gdt_entry(7, 0, 0xfffff, true, gdt_type::read_write | gdt_type::execute);
|
||||||
|
|
||||||
gdt_write();
|
gdt_write();
|
||||||
|
|
||||||
@@ -196,6 +194,7 @@ interrupts_init()
|
|||||||
enable_serial_interrupts();
|
enable_serial_interrupts();
|
||||||
|
|
||||||
log::info(logs::boot, "Interrupts enabled.");
|
log::info(logs::boot, "Interrupts enabled.");
|
||||||
|
gdt_dump(g_gdtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct registers
|
struct registers
|
||||||
@@ -255,6 +254,43 @@ isr_handler(registers regs)
|
|||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case isr::isrGPFault: {
|
||||||
|
cons->set_color(9);
|
||||||
|
cons->puts("\nGeneral Protection Fault:\n");
|
||||||
|
cons->set_color();
|
||||||
|
|
||||||
|
cons->puts(" flags:");
|
||||||
|
if (regs.errorcode & 0x01) cons->puts(" external");
|
||||||
|
|
||||||
|
int index = (regs.errorcode & 0xf8) >> 3;
|
||||||
|
if (index) {
|
||||||
|
switch (regs.errorcode & 0x06) {
|
||||||
|
case 0:
|
||||||
|
cons->printf(" GDT[%d]\n", index);
|
||||||
|
gdt_dump(g_gdtr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
case 3:
|
||||||
|
cons->printf(" IDT[%d]\n", index);
|
||||||
|
idt_dump(g_idtr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
cons->printf(" LDT[%d]??\n", index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cons->putc('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
cons->puts("\n");
|
||||||
|
print_reg("rip", regs.rip);
|
||||||
|
print_stacktrace(2);
|
||||||
|
}
|
||||||
|
while(1) asm("hlt");
|
||||||
|
break;
|
||||||
|
|
||||||
case isr::isrPageFault: {
|
case isr::isrPageFault: {
|
||||||
cons->set_color(11);
|
cons->set_color(11);
|
||||||
cons->puts("\nPage Fault:\n");
|
cons->puts("\nPage Fault:\n");
|
||||||
@@ -351,7 +387,8 @@ irq_handler(registers regs)
|
|||||||
void
|
void
|
||||||
gdt_dump(const table_ptr &table)
|
gdt_dump(const table_ptr &table)
|
||||||
{
|
{
|
||||||
log::info(logs::boot, "Loaded GDT at: %lx size: %d bytes", table.base, table.limit+1);
|
console *cons = console::get();
|
||||||
|
cons->printf(" GDT: loc:%lx size:%d\n", table.base, table.limit+1);
|
||||||
|
|
||||||
int count = (table.limit + 1) / sizeof(gdt_descriptor);
|
int count = (table.limit + 1) / sizeof(gdt_descriptor);
|
||||||
const gdt_descriptor *gdt =
|
const gdt_descriptor *gdt =
|
||||||
@@ -364,24 +401,33 @@ gdt_dump(const table_ptr &table)
|
|||||||
gdt[i].base_low;
|
gdt[i].base_low;
|
||||||
|
|
||||||
uint32_t limit =
|
uint32_t limit =
|
||||||
static_cast<uint32_t>(gdt[i].granularity & 0x0f) << 16 |
|
static_cast<uint32_t>(gdt[i].size & 0x0f) << 16 |
|
||||||
gdt[i].limit_low;
|
gdt[i].limit_low;
|
||||||
|
|
||||||
if (gdt[i].flags & 0x80) {
|
cons->printf(" %02d:", i);
|
||||||
log::debug(logs::boot,
|
if (! bitfield_has(gdt[i].type, gdt_type::present)) {
|
||||||
" Entry %3d: Base %x limit %x privs %d flags %s%s%s%s%s%s",
|
cons->puts(" Not Present\n");
|
||||||
i, base, limit, ((gdt[i].flags >> 5) & 0x03),
|
continue;
|
||||||
|
|
||||||
(gdt[i].flags & 0x80) ? "P " : " ",
|
|
||||||
(gdt[i].flags & 0x08) ? "ex " : " ",
|
|
||||||
(gdt[i].flags & 0x04) ? "dc " : " ",
|
|
||||||
(gdt[i].flags & 0x02) ? "rw " : " ",
|
|
||||||
|
|
||||||
(gdt[i].granularity & 0x80) ? "kb " : "b ",
|
|
||||||
(gdt[i].granularity & 0x60) == 0x60 ? "64" :
|
|
||||||
(gdt[i].granularity & 0x60) == 0x40 ? "32" : "16"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cons->printf(" Base %08x limit %05x ", base, limit);
|
||||||
|
|
||||||
|
switch (gdt[i].type & gdt_type::ring3) {
|
||||||
|
case gdt_type::ring3: cons->puts("ring3"); break;
|
||||||
|
case gdt_type::ring2: cons->puts("ring2"); break;
|
||||||
|
case gdt_type::ring1: cons->puts("ring1"); break;
|
||||||
|
default: cons->puts("ring0"); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cons->printf(" %s %s %s %s %s %s %s\n",
|
||||||
|
bitfield_has(gdt[i].type, gdt_type::accessed) ? "A" : " ",
|
||||||
|
bitfield_has(gdt[i].type, gdt_type::read_write) ? "RW" : " ",
|
||||||
|
bitfield_has(gdt[i].type, gdt_type::conforming) ? "C" : " ",
|
||||||
|
bitfield_has(gdt[i].type, gdt_type::execute) ? "EX" : " ",
|
||||||
|
bitfield_has(gdt[i].type, gdt_type::system) ? "S" : " ",
|
||||||
|
(gdt[i].size & 0x80) ? "KB" : " B",
|
||||||
|
(gdt[i].size & 0x60) == 0x20 ? "64" :
|
||||||
|
(gdt[i].size & 0x60) == 0x40 ? "32" : "16");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user