From 0fc369789e48cf0298e09668083752ebc6c7dbaa Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Mon, 14 May 2018 22:52:28 -0700 Subject: [PATCH] Change GDT code to enforce correct CS --- src/kernel/interrupts.cpp | 47 +++++++++++++++++++++++++++++---------- src/kernel/interrupts.s | 11 +++++++++ src/kernel/pci.cpp | 42 +++++++++++++++++++++++++++------- 3 files changed, 80 insertions(+), 20 deletions(-) diff --git a/src/kernel/interrupts.cpp b/src/kernel/interrupts.cpp index 25bad16..c68ccd5 100644 --- a/src/kernel/interrupts.cpp +++ b/src/kernel/interrupts.cpp @@ -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(&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(&g_idt_table); -#define ISR(i, name) set_idt_entry(i, reinterpret_cast(& name), 0x38, 0x8e); -#define EISR(i, name) set_idt_entry(i, reinterpret_cast(& name), 0x38, 0x8e); -#define IRQ(i, q, name) set_idt_entry(i, reinterpret_cast(& name), 0x38, 0x8e); +#define ISR(i, name) set_idt_entry(i, reinterpret_cast(& name), 0x08, 0x8e); +#define EISR(i, name) set_idt_entry(i, reinterpret_cast(& name), 0x08, 0x8e); +#define IRQ(i, q, name) set_idt_entry(i, reinterpret_cast(& 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(sp)); + sp += sizeof(uint64_t); + } } while(1) asm("hlt"); break; diff --git a/src/kernel/interrupts.s b/src/kernel/interrupts.s index 98cc951..ddc626f 100644 --- a/src/kernel/interrupts.s +++ b/src/kernel/interrupts.s @@ -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 diff --git a/src/kernel/pci.cpp b/src/kernel/pci.cpp index 577dc84..1ddc7c9 100644 --- a/src/kernel/pci.cpp +++ b/src/kernel/pci.cpp @@ -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(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(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(m_msi); - mcap->address = address; - mcap->data = data; - mcap->control |= 1; + if (mcap->control & 0x0080) { + pci_cap_msi64 *mcap64 = reinterpret_cast(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(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"); }