mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
Add initial classes representing APIC
This commit is contained in:
106
src/kernel/apic.cpp
Normal file
106
src/kernel/apic.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "apic.h"
|
||||
#include "assert.h"
|
||||
#include "interrupts.h"
|
||||
#include "log.h"
|
||||
#include "memory_pages.h"
|
||||
|
||||
|
||||
static uint32_t
|
||||
apic_read(uint32_t *apic, uint16_t offset)
|
||||
{
|
||||
return *(apic + offset/sizeof(uint32_t));
|
||||
}
|
||||
|
||||
static void
|
||||
apic_write(uint32_t *apic, uint16_t offset, uint32_t value)
|
||||
{
|
||||
*(apic + offset/sizeof(uint32_t)) = value;
|
||||
}
|
||||
|
||||
|
||||
apic::apic(uint32_t *base) :
|
||||
m_base(base)
|
||||
{
|
||||
g_page_manager.map_offset_pointer(reinterpret_cast<void **>(&m_base), 0x1000);
|
||||
}
|
||||
|
||||
|
||||
lapic::lapic(uint32_t *base, isr spurious) :
|
||||
apic(base)
|
||||
{
|
||||
apic_write(m_base, 0xf0, static_cast<uint32_t>(spurious));
|
||||
log::info(logs::interrupt, "LAPIC created, base %lx", m_base);
|
||||
}
|
||||
|
||||
void
|
||||
lapic::enable_timer(isr vector, uint8_t divisor, uint32_t count, bool repeat)
|
||||
{
|
||||
switch (divisor) {
|
||||
case 1: divisor = 11; break;
|
||||
case 2: divisor = 0; break;
|
||||
case 4: divisor = 1; break;
|
||||
case 8: divisor = 2; break;
|
||||
case 16: divisor = 3; break;
|
||||
case 32: divisor = 8; break;
|
||||
case 64: divisor = 9; break;
|
||||
case 128: divisor = 10; break;
|
||||
default:
|
||||
kassert(0, "Invalid divisor passed to lapic::enable_timer");
|
||||
}
|
||||
|
||||
apic_write(m_base, 0x3e0, divisor);
|
||||
apic_write(m_base, 0x380, count);
|
||||
|
||||
uint32_t lvte = static_cast<uint8_t>(vector);
|
||||
if (repeat)
|
||||
lvte |= 0x20000;
|
||||
|
||||
log::debug(logs::interrupt, "Enabling APIC timer with isr %d.", vector);
|
||||
apic_write(m_base, 0x320, lvte);
|
||||
}
|
||||
|
||||
void
|
||||
lapic::enable_lint(uint8_t num, isr vector, bool nmi, uint16_t flags)
|
||||
{
|
||||
kassert(num == 0 || num == 1, "Invalid LINT passed to lapic::enable_lint.");
|
||||
|
||||
uint16_t off = num ? 0x360 : 0x350;
|
||||
uint32_t lvte = static_cast<uint8_t>(vector);
|
||||
|
||||
uint16_t polarity = flags & 0x3;
|
||||
if (polarity == 3)
|
||||
lvte |= (1 << 13);
|
||||
|
||||
uint16_t trigger = (flags >> 2) & 0x3;
|
||||
if (trigger == 3)
|
||||
lvte |= (1 << 15);
|
||||
|
||||
apic_write(m_base, off, lvte);
|
||||
log::debug(logs::interrupt, "APIC LINT%d enabled as %s %d %s-triggered, active %s.",
|
||||
num, nmi ? "NMI" : "ISR", vector,
|
||||
polarity == 3 ? "level" : "edge",
|
||||
trigger == 3 ? "low" : "high");
|
||||
}
|
||||
|
||||
void
|
||||
lapic::enable()
|
||||
{
|
||||
apic_write(m_base, 0xf0,
|
||||
apic_read(m_base, 0xf0) | 0x100);
|
||||
log::debug(logs::interrupt, "LAPIC enabled!");
|
||||
}
|
||||
|
||||
void
|
||||
lapic::disable()
|
||||
{
|
||||
apic_write(m_base, 0xf0,
|
||||
apic_read(m_base, 0xf0) & ~0x100);
|
||||
log::debug(logs::interrupt, "LAPIC disabled.");
|
||||
}
|
||||
|
||||
|
||||
ioapic::ioapic(uint32_t *base, uint32_t base_gsr) :
|
||||
apic(base),
|
||||
m_base_gsr(base_gsr)
|
||||
{
|
||||
}
|
||||
69
src/kernel/apic.h
Normal file
69
src/kernel/apic.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
/// \file apic.h
|
||||
/// Classes to control both local and I/O APICs.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum class isr : uint8_t;
|
||||
|
||||
|
||||
/// Base class for other APIC types
|
||||
class apic
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
/// \arg base Base virtual address of the APIC's MMIO registers
|
||||
apic(uint32_t *base);
|
||||
|
||||
protected:
|
||||
uint32_t *m_base;
|
||||
};
|
||||
|
||||
|
||||
/// Controller for processor-local APICs
|
||||
class lapic :
|
||||
public apic
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
/// \arg base Base virtual address of the APIC's MMIO registers
|
||||
/// \arg spurious Vector of the spurious interrupt handler
|
||||
lapic(uint32_t *base, isr spurious);
|
||||
|
||||
/// Enable interrupts for the LAPIC timer.
|
||||
/// \arg vector Interrupt vector the timer should use
|
||||
/// \arg divisor The frequency divisor of the bus Hz (power of 2, <= 128)
|
||||
/// \arg count The count of ticks before an interrupt
|
||||
/// \arg repeat If false, this timer is one-off, otherwise repeating
|
||||
void enable_timer(isr vector, uint8_t divisor, uint32_t count, bool repeat = true);
|
||||
|
||||
/// Enable interrupts for the LAPIC LINT0 pin.
|
||||
/// \arg num Local interrupt number (0 or 1)
|
||||
/// \arg vector Interrupt vector LINT0 should use
|
||||
/// \arg nmi Whether this interrupt is NMI delivery mode
|
||||
/// \arg flags Flags for mode/polarity (ACPI MPS INTI flags)
|
||||
void enable_lint(uint8_t num, isr vector, bool nmi, uint16_t flags);
|
||||
|
||||
void enable(); ///< Enable servicing of interrupts
|
||||
void disable(); ///< Disable (temporarily) servicing of interrupts
|
||||
};
|
||||
|
||||
|
||||
/// Controller for I/O APICs
|
||||
class ioapic :
|
||||
public apic
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
/// \arg base Base virtual address of the APIC's MMIO registers
|
||||
/// \arg base_gsr Starting global system interrupt number of this IOAPIC
|
||||
ioapic(uint32_t *base, uint32_t base_gsr);
|
||||
|
||||
uint32_t get_base_gsr() const { return m_base_gsr; }
|
||||
uint32_t get_num_gsr() const { return m_num_gsr; }
|
||||
|
||||
private:
|
||||
uint32_t m_base_gsr;
|
||||
uint32_t m_num_gsr;
|
||||
};
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
|
||||
#include "kutil/memory.h"
|
||||
#include "acpi_tables.h"
|
||||
#include "apic.h"
|
||||
#include "assert.h"
|
||||
#include "device_manager.h"
|
||||
#include "interrupts.h"
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
|
||||
static const char expected_signature[] = "RSD PTR ";
|
||||
|
||||
@@ -50,9 +53,9 @@ acpi_table_header::validate(uint32_t expected_type) const
|
||||
}
|
||||
|
||||
device_manager::device_manager(const void *root_table) :
|
||||
m_local_apic(nullptr),
|
||||
m_io_apic(nullptr),
|
||||
m_global_interrupt_base(0)
|
||||
m_lapic(nullptr),
|
||||
m_ioapics(nullptr),
|
||||
m_num_ioapics(0)
|
||||
{
|
||||
kassert(root_table != 0, "ACPI root table pointer is null.");
|
||||
|
||||
@@ -77,6 +80,12 @@ device_manager::device_manager(const void *root_table) :
|
||||
load_xsdt(reinterpret_cast<const acpi_xsdt *>(acpi2->xsdt_address));
|
||||
}
|
||||
|
||||
ioapic *
|
||||
device_manager::get_ioapic(int i)
|
||||
{
|
||||
return (i < m_num_ioapics) ? m_ioapics + i : nullptr;
|
||||
}
|
||||
|
||||
static void
|
||||
put_sig(char *into, uint32_t type)
|
||||
{
|
||||
@@ -117,8 +126,11 @@ device_manager::load_xsdt(const acpi_xsdt *xsdt)
|
||||
void
|
||||
device_manager::load_apic(const acpi_apic *apic)
|
||||
{
|
||||
m_local_apic = reinterpret_cast<uint32_t *>(apic->local_address);
|
||||
log::info(logs::devices, " APIC local address %lx", apic->local_address);
|
||||
uint32_t *local = reinterpret_cast<uint32_t *>(apic->local_address);
|
||||
|
||||
m_lapic = new (kalloc(sizeof(lapic))) lapic(local, isr::isrSpurious);
|
||||
m_lapic->enable_lint(0, isr::isrLINT0, false, 0);
|
||||
m_lapic->enable_lint(1, isr::isrLINT1, false, 0);
|
||||
|
||||
uint8_t const *p = apic->controller_data;
|
||||
uint8_t const *end = p + acpi_table_entries(apic, 1);
|
||||
@@ -131,11 +143,11 @@ device_manager::load_apic(const acpi_apic *apic)
|
||||
case 0: // Local APIC
|
||||
break;
|
||||
|
||||
case 1: // I/O APIC
|
||||
m_io_apic = reinterpret_cast<uint32_t *>(kutil::read_from<uint32_t>(p+4));
|
||||
m_global_interrupt_base = kutil::read_from<uint32_t>(p+8);
|
||||
log::info(logs::devices, " IO APIC address %lx base %d",
|
||||
m_io_apic, m_global_interrupt_base);
|
||||
case 1: { // I/O APIC
|
||||
uint32_t *io_apic = reinterpret_cast<uint32_t *>(kutil::read_from<uint32_t>(p+4));
|
||||
uint32_t base = kutil::read_from<uint32_t>(p+8);
|
||||
log::info(logs::devices, " IO APIC address %lx base %d", io_apic, base);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Interrupt source override
|
||||
@@ -146,12 +158,19 @@ device_manager::load_apic(const acpi_apic *apic)
|
||||
(kutil::read_from<uint16_t>(p+8) >> 2) & 0x3);
|
||||
break;
|
||||
|
||||
case 4: // Interrupt source override
|
||||
case 4: {// LAPIC NMI
|
||||
uint8_t cpu = kutil::read_from<uint8_t>(p + 2);
|
||||
uint8_t num = kutil::read_from<uint8_t>(p + 5);
|
||||
uint16_t flags = kutil::read_from<uint16_t>(p + 3);
|
||||
|
||||
m_lapic->enable_lint(num, num == 0 ? isr::isrLINT0 : isr::isrLINT1, true, flags);
|
||||
|
||||
log::info(logs::devices, " LAPIC NMI Proc %d LINT%d Pol %d Tri %d",
|
||||
kutil::read_from<uint8_t>(p+2),
|
||||
kutil::read_from<uint8_t>(p+5),
|
||||
kutil::read_from<uint16_t>(p+3) & 0x3,
|
||||
(kutil::read_from<uint16_t>(p+3) >> 2) & 0x3);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -160,4 +179,7 @@ device_manager::load_apic(const acpi_apic *apic)
|
||||
|
||||
p += length;
|
||||
}
|
||||
|
||||
// m_lapic->enable_timer(isr::isrTimer, 128, 3000000);
|
||||
m_lapic->enable();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
struct acpi_xsdt;
|
||||
struct acpi_apic;
|
||||
|
||||
class lapic;
|
||||
class ioapic;
|
||||
|
||||
class device_manager
|
||||
{
|
||||
public:
|
||||
@@ -11,14 +14,13 @@ public:
|
||||
device_manager() = delete;
|
||||
device_manager(const device_manager &) = delete;
|
||||
|
||||
uint8_t * local_apic() const;
|
||||
uint8_t * io_apic() const;
|
||||
lapic * get_lapic() { return m_lapic; }
|
||||
ioapic * get_ioapic(int i);
|
||||
|
||||
private:
|
||||
uint32_t *m_local_apic;
|
||||
uint32_t *m_io_apic;
|
||||
|
||||
uint32_t m_global_interrupt_base;
|
||||
lapic *m_lapic;
|
||||
ioapic *m_ioapics;
|
||||
int m_num_ioapics;
|
||||
|
||||
void load_xsdt(const acpi_xsdt *xsdt);
|
||||
void load_apic(const acpi_apic *apic);
|
||||
|
||||
@@ -1,51 +1,54 @@
|
||||
ISR ( 0, isr0);
|
||||
ISR ( 1, isr1);
|
||||
ISR ( 2, isr2);
|
||||
ISR ( 3, isr3);
|
||||
ISR ( 4, isr4);
|
||||
ISR ( 5, isr5);
|
||||
ISR ( 6, isr6);
|
||||
ISR ( 7, isr7);
|
||||
EISR( 8, isr8);
|
||||
ISR ( 9, isr9);
|
||||
EISR(10, isr10);
|
||||
EISR(11, isr11);
|
||||
EISR(12, isr12);
|
||||
EISR(13, isr13);
|
||||
EISR(14, isr14);
|
||||
ISR (15, isr15);
|
||||
ISR (16, isr16);
|
||||
ISR (17, isr17);
|
||||
ISR (18, isr18);
|
||||
ISR (19, isr19);
|
||||
ISR (20, isr20);
|
||||
ISR (21, isr21);
|
||||
ISR (22, isr22);
|
||||
ISR (23, isr23);
|
||||
ISR (24, isr24);
|
||||
ISR (25, isr25);
|
||||
ISR (26, isr26);
|
||||
ISR (27, isr27);
|
||||
ISR (28, isr28);
|
||||
ISR (29, isr29);
|
||||
ISR (30, isr30);
|
||||
ISR (31, isr31);
|
||||
ISR ( 0, isr0)
|
||||
ISR ( 1, isr1)
|
||||
ISR ( 2, isr2)
|
||||
ISR ( 3, isr3)
|
||||
ISR ( 4, isr4)
|
||||
ISR ( 5, isr5)
|
||||
ISR ( 6, isr6)
|
||||
ISR ( 7, isr7)
|
||||
EISR( 8, isr8)
|
||||
ISR ( 9, isr9)
|
||||
EISR(10, isr10)
|
||||
EISR(11, isr11)
|
||||
EISR(12, isr12)
|
||||
EISR(13, isr13)
|
||||
EISR(14, isr14)
|
||||
ISR (15, isr15)
|
||||
ISR (16, isr16)
|
||||
ISR (17, isr17)
|
||||
ISR (18, isr18)
|
||||
ISR (19, isr19)
|
||||
ISR (20, isr20)
|
||||
ISR (21, isr21)
|
||||
ISR (22, isr22)
|
||||
ISR (23, isr23)
|
||||
ISR (24, isr24)
|
||||
ISR (25, isr25)
|
||||
ISR (26, isr26)
|
||||
ISR (27, isr27)
|
||||
ISR (28, isr28)
|
||||
ISR (29, isr29)
|
||||
ISR (30, isr30)
|
||||
ISR (31, isr31)
|
||||
|
||||
IRQ (64, 0, irq0);
|
||||
IRQ (65, 1, irq1);
|
||||
IRQ (66, 2, irq2);
|
||||
IRQ (67, 3, irq3);
|
||||
IRQ (68, 4, irq4);
|
||||
IRQ (69, 5, irq5);
|
||||
IRQ (70, 6, irq6);
|
||||
IRQ (71, 7, irq7);
|
||||
IRQ (72, 8, irq8);
|
||||
IRQ (73, 9, irq9);
|
||||
IRQ (74, 10, irq10);
|
||||
IRQ (75, 11, irq11);
|
||||
IRQ (76, 12, irq12);
|
||||
IRQ (77, 13, irq13);
|
||||
IRQ (78, 14, irq14);
|
||||
IRQ (79, 15, irq15);
|
||||
IRQ (64, 0, irq0)
|
||||
IRQ (65, 1, irq1)
|
||||
IRQ (66, 2, irq2)
|
||||
IRQ (67, 3, irq3)
|
||||
IRQ (68, 4, irq4)
|
||||
IRQ (69, 5, irq5)
|
||||
IRQ (70, 6, irq6)
|
||||
IRQ (71, 7, irq7)
|
||||
IRQ (72, 8, irq8)
|
||||
IRQ (73, 9, irq9)
|
||||
IRQ (74, 10, irq10)
|
||||
IRQ (75, 11, irq11)
|
||||
IRQ (76, 12, irq12)
|
||||
IRQ (77, 13, irq13)
|
||||
IRQ (78, 14, irq14)
|
||||
IRQ (79, 15, irq15)
|
||||
|
||||
ISR (0xff, isrSpurious);
|
||||
ISR (0x7c, isrTimer)
|
||||
ISR (0x7d, isrLINT0)
|
||||
ISR (0x7e, isrLINT1)
|
||||
ISR (0x7f, isrSpurious)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "console.h"
|
||||
#include "interrupts.h"
|
||||
#include "log.h"
|
||||
#include "memory_pages.h"
|
||||
|
||||
enum class gdt_flags : uint8_t
|
||||
{
|
||||
@@ -29,29 +30,29 @@ operator | (gdt_flags lhs, gdt_flags rhs)
|
||||
|
||||
struct gdt_descriptor
|
||||
{
|
||||
uint16_t limit_low;
|
||||
uint16_t base_low;
|
||||
uint8_t base_mid;
|
||||
uint8_t flags;
|
||||
uint8_t granularity;
|
||||
uint8_t base_high;
|
||||
uint16_t limit_low;
|
||||
uint16_t base_low;
|
||||
uint8_t base_mid;
|
||||
uint8_t flags;
|
||||
uint8_t granularity;
|
||||
uint8_t base_high;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct idt_descriptor
|
||||
{
|
||||
uint16_t base_low;
|
||||
uint16_t selector;
|
||||
uint8_t ist;
|
||||
uint8_t flags;
|
||||
uint16_t base_mid;
|
||||
uint32_t base_high;
|
||||
uint32_t reserved; // must be zero
|
||||
uint16_t base_low;
|
||||
uint16_t selector;
|
||||
uint8_t ist;
|
||||
uint8_t flags;
|
||||
uint16_t base_mid;
|
||||
uint32_t base_high;
|
||||
uint32_t reserved; // must be zero
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct table_ptr
|
||||
{
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
gdt_descriptor g_gdt_table[10];
|
||||
@@ -59,7 +60,6 @@ idt_descriptor g_idt_table[256];
|
||||
table_ptr g_gdtr;
|
||||
table_ptr g_idtr;
|
||||
|
||||
|
||||
struct registers;
|
||||
|
||||
extern "C" {
|
||||
@@ -72,9 +72,9 @@ extern "C" {
|
||||
void isr_handler(registers);
|
||||
void irq_handler(registers);
|
||||
|
||||
#define ISR(i, name) extern void name ()
|
||||
#define EISR(i, name) extern void name ()
|
||||
#define IRQ(i, q, name) extern void name ()
|
||||
#define ISR(i, name) extern void name ();
|
||||
#define EISR(i, name) extern void name ();
|
||||
#define IRQ(i, q, name) extern void name ();
|
||||
#include "interrupt_isrs.inc"
|
||||
#undef IRQ
|
||||
#undef EISR
|
||||
@@ -87,16 +87,16 @@ void gdt_dump(const table_ptr &table);
|
||||
void
|
||||
set_gdt_entry(uint8_t i, uint32_t base, uint32_t limit, bool is64, gdt_flags flags)
|
||||
{
|
||||
g_gdt_table[i].limit_low = limit & 0xffff;
|
||||
g_gdt_table[i].limit_low = limit & 0xffff;
|
||||
|
||||
g_gdt_table[i].base_low = base & 0xffff;
|
||||
g_gdt_table[i].base_mid = (base >> 16) & 0xff;
|
||||
g_gdt_table[i].base_high = (base >> 24) & 0xff;
|
||||
g_gdt_table[i].base_low = base & 0xffff;
|
||||
g_gdt_table[i].base_mid = (base >> 16) & 0xff;
|
||||
g_gdt_table[i].base_high = (base >> 24) & 0xff;
|
||||
|
||||
g_gdt_table[i].granularity =
|
||||
((limit >> 16) & 0xf) | (is64 ? 0xa0 : 0xc0);
|
||||
g_gdt_table[i].granularity =
|
||||
((limit >> 16) & 0xf) | (is64 ? 0xa0 : 0xc0);
|
||||
|
||||
g_gdt_table[i].flags = static_cast<uint8_t>(flags | gdt_flags::res_1 | gdt_flags::pr);
|
||||
g_gdt_table[i].flags = static_cast<uint8_t>(flags | gdt_flags::res_1 | gdt_flags::pr);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -143,8 +143,6 @@ interrupts_init()
|
||||
|
||||
idt_write();
|
||||
log::info(logs::interrupt, "Interrupts enabled.");
|
||||
gdt_dump(g_gdtr);
|
||||
idt_dump(g_idtr);
|
||||
}
|
||||
|
||||
struct registers
|
||||
@@ -162,35 +160,52 @@ isr_handler(registers regs)
|
||||
{
|
||||
console *cons = console::get();
|
||||
|
||||
cons->set_color(9);
|
||||
cons->puts("\nReceived ISR interrupt:\n");
|
||||
cons->set_color();
|
||||
switch (static_cast<isr>(regs.interrupt & 0xff)) {
|
||||
case isr::isrTimer:
|
||||
cons->puts("\nTICK\n");
|
||||
break;
|
||||
|
||||
uint64_t cr2 = 0;
|
||||
__asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2));
|
||||
case isr::isrLINT0:
|
||||
cons->puts("\nLINT0\n");
|
||||
break;
|
||||
|
||||
print_reg("ISR", regs.interrupt);
|
||||
print_reg("ERR", regs.errorcode);
|
||||
print_reg("CR2", cr2);
|
||||
cons->puts("\n");
|
||||
case isr::isrLINT1:
|
||||
cons->puts("\nLINT1\n");
|
||||
break;
|
||||
|
||||
print_reg(" ds", regs.ds);
|
||||
print_reg("rdi", regs.rdi);
|
||||
print_reg("rsi", regs.rsi);
|
||||
print_reg("rbp", regs.rbp);
|
||||
print_reg("rsp", regs.rsp);
|
||||
print_reg("rbx", regs.rbx);
|
||||
print_reg("rdx", regs.rdx);
|
||||
print_reg("rcx", regs.rcx);
|
||||
print_reg("rax", regs.rax);
|
||||
cons->puts("\n");
|
||||
default:
|
||||
cons->set_color(9);
|
||||
cons->puts("\nReceived ISR interrupt:\n");
|
||||
cons->set_color();
|
||||
|
||||
print_reg("rip", regs.rip);
|
||||
print_reg(" cs", regs.cs);
|
||||
print_reg(" ef", regs.eflags);
|
||||
print_reg("esp", regs.user_esp);
|
||||
print_reg(" ss", regs.ss);
|
||||
while(1) asm("hlt");
|
||||
uint64_t cr2 = 0;
|
||||
__asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2));
|
||||
|
||||
print_reg("ISR", regs.interrupt);
|
||||
print_reg("ERR", regs.errorcode);
|
||||
print_reg("CR2", cr2);
|
||||
cons->puts("\n");
|
||||
|
||||
print_reg(" ds", regs.ds);
|
||||
print_reg("rdi", regs.rdi);
|
||||
print_reg("rsi", regs.rsi);
|
||||
print_reg("rbp", regs.rbp);
|
||||
print_reg("rsp", regs.rsp);
|
||||
print_reg("rbx", regs.rbx);
|
||||
print_reg("rdx", regs.rdx);
|
||||
print_reg("rcx", regs.rcx);
|
||||
print_reg("rax", regs.rax);
|
||||
cons->puts("\n");
|
||||
|
||||
print_reg("rip", regs.rip);
|
||||
print_reg(" cs", regs.cs);
|
||||
print_reg(" ef", regs.eflags);
|
||||
print_reg("esp", regs.user_esp);
|
||||
print_reg(" ss", regs.ss);
|
||||
while(1) asm("hlt");
|
||||
}
|
||||
|
||||
*reinterpret_cast<uint32_t *>(0xffffff80fee000b0) = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,4 +1,21 @@
|
||||
#pragma once
|
||||
/// \file interrupts.h
|
||||
/// Free functions and definitions related to interrupt service vectors
|
||||
|
||||
|
||||
/// Enum of all defined ISR/IRQ vectors
|
||||
enum class isr : uint8_t
|
||||
{
|
||||
#define ISR(i, name) name = i,
|
||||
#define EISR(i, name) name = i,
|
||||
#define IRQ(i, q, name) name = i,
|
||||
#include "interrupt_isrs.inc"
|
||||
#undef IRQ
|
||||
#undef EISR
|
||||
#undef ISR
|
||||
|
||||
max
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
void interrupts_enable();
|
||||
|
||||
@@ -48,6 +48,7 @@ kernel_main(popcorn_data *header)
|
||||
cons->puts(GIT_VERSION " booting...\n");
|
||||
|
||||
log::init(cons);
|
||||
log::enable(logs::interrupt, log::level::debug);
|
||||
|
||||
cpu_id cpu;
|
||||
|
||||
@@ -62,13 +63,14 @@ kernel_main(popcorn_data *header)
|
||||
cpu_info.ecx_bit(21) ? "yes" : "no");
|
||||
|
||||
page_manager *pager = new (&g_page_manager) page_manager;
|
||||
pager->mark_offset_pointer(&header->frame_buffer, header->frame_buffer_length);
|
||||
|
||||
memory_initialize_managers(
|
||||
header->memory_map,
|
||||
header->memory_map_length,
|
||||
header->memory_map_desc_size);
|
||||
|
||||
pager->map_offset_pointer(&header->frame_buffer, header->frame_buffer_length);
|
||||
|
||||
interrupts_init();
|
||||
interrupts_enable();
|
||||
|
||||
|
||||
@@ -191,33 +191,6 @@ page_manager::init(
|
||||
// allocated, full of page_block structs. Eventually hand
|
||||
// control of that to a slab allocator.
|
||||
|
||||
page_table *pml4 = get_pml4();
|
||||
|
||||
// Fix up the offset-marked pointers
|
||||
for (unsigned i = 0; i < m_marked_pointer_count; ++i) {
|
||||
addr_t *p = reinterpret_cast<addr_t *>(m_marked_pointers[i]);
|
||||
addr_t v = *p + page_offset;
|
||||
addr_t c = (m_marked_pointer_lengths[i] / page_size) + 1;
|
||||
|
||||
// TODO: cleanly search/split this as a block out of used/free if possible
|
||||
page_block *block = get_block();
|
||||
|
||||
// TODO: page-align
|
||||
block->physical_address = *p;
|
||||
block->virtual_address = v;
|
||||
block->count = c;
|
||||
block->flags =
|
||||
page_block_flags::used |
|
||||
page_block_flags::mapped |
|
||||
page_block_flags::mmio;
|
||||
|
||||
log::info(logs::memory, "Fixing up pointer %lx [%3d] -> %lx", *p, c, v);
|
||||
|
||||
m_used = page_block::insert(m_used, block);
|
||||
page_in(pml4, *p, v, c);
|
||||
*p = v;
|
||||
}
|
||||
|
||||
consolidate_blocks();
|
||||
|
||||
page_block::dump(m_used, "used", true);
|
||||
@@ -238,10 +211,31 @@ page_manager::init(
|
||||
}
|
||||
|
||||
void
|
||||
page_manager::mark_offset_pointer(void **pointer, size_t length)
|
||||
page_manager::map_offset_pointer(void **pointer, size_t length)
|
||||
{
|
||||
m_marked_pointers[m_marked_pointer_count] = pointer;
|
||||
m_marked_pointer_lengths[m_marked_pointer_count++] = length;
|
||||
addr_t *p = reinterpret_cast<addr_t *>(pointer);
|
||||
addr_t v = *p + page_offset;
|
||||
addr_t c = ((length - 1) / page_size) + 1;
|
||||
|
||||
// TODO: cleanly search/split this as a block out of used/free if possible
|
||||
page_block *block = get_block();
|
||||
|
||||
// TODO: page-align
|
||||
block->physical_address = *p;
|
||||
block->virtual_address = v;
|
||||
block->count = c;
|
||||
block->flags =
|
||||
page_block_flags::used |
|
||||
page_block_flags::mapped |
|
||||
page_block_flags::mmio;
|
||||
|
||||
log::info(logs::memory, "Fixing up pointer %lx [%3d] -> %lx", *p, c, v);
|
||||
|
||||
m_used = page_block::insert(m_used, block);
|
||||
|
||||
page_table *pml4 = get_pml4();
|
||||
page_in(pml4, *p, v, c);
|
||||
*p = v;
|
||||
}
|
||||
|
||||
page_block *
|
||||
|
||||
@@ -40,11 +40,10 @@ public:
|
||||
/// \arg count The number of pages to unmap
|
||||
void unmap_pages(addr_t address, size_t count);
|
||||
|
||||
/// Mark a pointer and range to be offset-mapped. This pointer will
|
||||
/// automatically get updated once page_manager::init() is called.
|
||||
/// Offset-map a pointer. No physical pages will be mapped.
|
||||
/// \arg pointer Pointer to a pointer to the memory area to be mapped
|
||||
/// \arg length Length of the memory area to be mapped
|
||||
void mark_offset_pointer(void **pointer, size_t length);
|
||||
void map_offset_pointer(void **pointer, size_t length);
|
||||
|
||||
private:
|
||||
friend void memory_initialize_managers(const void *, size_t, size_t);
|
||||
@@ -137,11 +136,6 @@ private:
|
||||
page_block *m_block_cache; ///< Cache of unused page_block structs
|
||||
free_page_header *m_page_cache; ///< Cache of free pages to use for tables
|
||||
|
||||
static const unsigned marked_pointer_max = 16;
|
||||
unsigned m_marked_pointer_count;
|
||||
void **m_marked_pointers[marked_pointer_max];
|
||||
size_t m_marked_pointer_lengths[marked_pointer_max];
|
||||
|
||||
page_manager(const page_manager &) = delete;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user