Change GDT code to enforce correct CS

This commit is contained in:
Justin C. Miller
2018-05-14 22:52:28 -07:00
parent 09f72f5ac6
commit 0fc369789e
3 changed files with 80 additions and 20 deletions

View File

@@ -61,7 +61,7 @@ extern "C" {
void idt_write();
void idt_load();
void gdt_write();
void gdt_write(uint16_t cs, uint16_t ds);
void gdt_load();
void isr_handler(registers);
@@ -168,28 +168,26 @@ interrupts_init()
g_gdtr.limit = sizeof(g_gdt_table) - 1;
g_gdtr.base = reinterpret_cast<uint64_t>(&g_gdt_table);
set_gdt_entry(1, 0, 0xfffff, false, gdt_type::read_write);
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_type::read_write);
set_gdt_entry(4, 0, 0xfffff, false, gdt_type::read_write | gdt_type::execute);
set_gdt_entry(1, 0, 0xfffff, true, gdt_type::read_write | gdt_type::execute);
set_gdt_entry(2, 0, 0xfffff, true, gdt_type::read_write);
set_gdt_entry(3, 0, 0xfffff, true, gdt_type::ring3 | gdt_type::read_write | gdt_type::execute);
set_gdt_entry(4, 0, 0xfffff, true, gdt_type::ring3 | gdt_type::read_write);
set_gdt_entry(6, 0, 0xfffff, false, gdt_type::read_write);
set_gdt_entry(7, 0, 0xfffff, true, gdt_type::read_write | gdt_type::execute);
gdt_write();
gdt_write(1 << 3, 2 << 3);
g_idtr.limit = sizeof(g_idt_table) - 1;
g_idtr.base = reinterpret_cast<uint64_t>(&g_idt_table);
#define ISR(i, name) set_idt_entry(i, reinterpret_cast<uint64_t>(& name), 0x38, 0x8e);
#define EISR(i, name) set_idt_entry(i, reinterpret_cast<uint64_t>(& name), 0x38, 0x8e);
#define IRQ(i, q, name) set_idt_entry(i, reinterpret_cast<uint64_t>(& name), 0x38, 0x8e);
#define ISR(i, name) set_idt_entry(i, reinterpret_cast<uint64_t>(& name), 0x08, 0x8e);
#define EISR(i, name) set_idt_entry(i, reinterpret_cast<uint64_t>(& name), 0x08, 0x8e);
#define IRQ(i, q, name) set_idt_entry(i, reinterpret_cast<uint64_t>(& name), 0x08, 0x8e);
#include "interrupt_isrs.inc"
#undef IRQ
#undef EISR
#undef ISR
idt_write();
disable_legacy_pic();
enable_serial_interrupts();
@@ -284,9 +282,34 @@ isr_handler(registers regs)
cons->putc('\n');
}
cons->puts("\n");
print_reg(" ds", regs.ds);
print_reg(" cs", regs.cs);
print_reg(" ss", regs.ss);
cons->puts("\n");
print_reg("rax", regs.rax);
print_reg("rbx", regs.rbx);
print_reg("rcx", regs.rcx);
print_reg("rdx", regs.rdx);
print_reg("rdi", regs.rdi);
print_reg("rsi", regs.rsi);
cons->puts("\n");
print_reg("rbp", regs.rbp);
print_reg("rsp", regs.rsp);
cons->puts("\n");
print_reg("rip", regs.rip);
print_stacktrace(2);
cons->puts("\nStack:\n");
uint64_t sp = regs.rsp;
while (sp <= regs.rbp) {
cons->printf("%016x: %016x\n", sp, *reinterpret_cast<uint64_t *>(sp));
sp += sizeof(uint64_t);
}
}
while(1) asm("hlt");
break;

View File

@@ -14,6 +14,17 @@ idt_load:
global gdt_write
gdt_write:
lgdt [rel g_gdtr]
mov ax, si ; second arg is data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
push qword rdi ; first arg is code segment
lea rax, [rel .next]
push rax
o64 retf
.next:
ret
global gdt_load

View File

@@ -3,20 +3,29 @@
#include "interrupts.h"
#include "pci.h"
struct pci_cap_msi :
public pci_cap
struct pci_cap_msi
{
pci_cap::type id;
uint8_t next;
uint16_t control;
uint64_t address;
} __attribute__ ((packed));
struct pci_cap_msi32
{
pci_cap::type id;
uint8_t next;
uint16_t control;
uint32_t address;
uint16_t data;
uint16_t reserved;
uint32_t mask;
uint32_t pending;
} __attribute__ ((packed));
struct pci_cap_msix :
public pci_cap
struct pci_cap_msi64
{
pci_cap::type id;
uint8_t next;
uint16_t control;
uint64_t address;
uint16_t data;
@@ -68,11 +77,13 @@ pci_device::pci_device(pci_group &group, uint8_t bus, uint8_t device, uint8_t fu
while (next) {
pci_cap *cap = reinterpret_cast<pci_cap *>(kutil::offset_pointer(m_base, next));
next = cap->next;
log::debug(logs::device, " - found PCI cap type %02x", cap->id);
if (cap->id == pci_cap::type::msi) {
m_msi = cap;
pci_cap_msi *mcap = reinterpret_cast<pci_cap_msi *>(cap);
mcap->control |= ~0x1; // Mask interrupts
log::debug(logs::device, " - MSI control %08x", mcap->control);
}
}
}
@@ -111,9 +122,24 @@ pci_device::write_msi_regs(addr_t address, uint16_t data)
kassert(m_msi, "Tried to write MSI for a device without that cap");
if (m_msi->id == pci_cap::type::msi) {
pci_cap_msi *mcap = reinterpret_cast<pci_cap_msi *>(m_msi);
mcap->address = address;
mcap->data = data;
mcap->control |= 1;
if (mcap->control & 0x0080) {
pci_cap_msi64 *mcap64 = reinterpret_cast<pci_cap_msi64 *>(m_msi);
mcap64->address = address;
mcap64->data = data;
if (mcap64->control & 0x0100)
log::debug(logs::device, " - MSI mask %08x pending %08x", mcap64->mask, mcap64->pending);
} else {
pci_cap_msi32 *mcap32 = reinterpret_cast<pci_cap_msi32 *>(m_msi);
mcap32->address = address;
mcap32->data = data;
if (mcap32->control & 0x0100)
log::debug(logs::device, " - MSI mask %08x pending %08x", mcap32->mask, mcap32->pending);
}
uint16_t control = mcap->control;
control &= 0xff8f; // We're allocating one vector, clear 6::4
control |= 0x0001; // Enable MSI
mcap->control = control;
} else {
kassert(0, "MIS-X is NYI");
}