mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
Add initial IO APIC support
- IO APIC vector mapping - Legacy PIC disable - Real interrupts happening
This commit is contained in:
@@ -6,17 +6,30 @@
|
||||
|
||||
|
||||
static uint32_t
|
||||
apic_read(uint32_t *apic, uint16_t offset)
|
||||
apic_read(uint32_t volatile *apic, uint16_t offset)
|
||||
{
|
||||
return *(apic + offset/sizeof(uint32_t));
|
||||
}
|
||||
|
||||
static void
|
||||
apic_write(uint32_t *apic, uint16_t offset, uint32_t value)
|
||||
apic_write(uint32_t volatile *apic, uint16_t offset, uint32_t value)
|
||||
{
|
||||
*(apic + offset/sizeof(uint32_t)) = value;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ioapic_read(uint32_t volatile *base, uint8_t reg)
|
||||
{
|
||||
*base = reg;
|
||||
return *(base + 4);
|
||||
}
|
||||
|
||||
static void
|
||||
ioapic_write(uint32_t volatile *base, uint8_t reg, uint32_t value)
|
||||
{
|
||||
*base = reg;
|
||||
*(base + 4) = value;
|
||||
}
|
||||
|
||||
apic::apic(uint32_t *base) :
|
||||
m_base(base)
|
||||
@@ -69,7 +82,7 @@ lapic::enable_lint(uint8_t num, isr vector, bool nmi, uint16_t flags)
|
||||
|
||||
uint16_t polarity = flags & 0x3;
|
||||
if (polarity == 3)
|
||||
lvte |= (1 << 13);
|
||||
lvte |= (1 << 13);
|
||||
|
||||
uint16_t trigger = (flags >> 2) & 0x3;
|
||||
if (trigger == 3)
|
||||
@@ -99,8 +112,83 @@ lapic::disable()
|
||||
}
|
||||
|
||||
|
||||
ioapic::ioapic(uint32_t *base, uint32_t base_gsr) :
|
||||
ioapic::ioapic(uint32_t *base, uint32_t base_gsi) :
|
||||
apic(base),
|
||||
m_base_gsr(base_gsr)
|
||||
m_base_gsi(base_gsi)
|
||||
{
|
||||
uint32_t id = ioapic_read(m_base, 0);
|
||||
uint32_t version = ioapic_read(m_base, 1);
|
||||
|
||||
m_id = (id >> 24) & 0xff;
|
||||
m_version = version & 0xff;
|
||||
m_num_gsi = (version >> 16) & 0xff;
|
||||
log::debug(logs::interrupt, "IOAPIC %d loaded, version %d, GSIs %d-%d",
|
||||
m_id, m_version, base_gsi, base_gsi + (m_num_gsi - 1));
|
||||
|
||||
for (uint8_t i = 0; i < m_num_gsi; ++i) {
|
||||
uint16_t flags = (i < 0x10) ? 0 : 0xf;
|
||||
isr vector = isr::irq0 + i;
|
||||
redirect(i, vector, flags, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ioapic::redirect(uint8_t irq, isr vector, uint16_t flags, bool masked)
|
||||
{
|
||||
uint64_t entry = static_cast<uint64_t>(vector);
|
||||
|
||||
uint16_t polarity = flags & 0x3;
|
||||
if (polarity == 3)
|
||||
entry |= (1 << 13);
|
||||
|
||||
uint16_t trigger = (flags >> 2) & 0x3;
|
||||
if (trigger == 3)
|
||||
entry |= (1 << 15);
|
||||
|
||||
if (masked)
|
||||
entry |= (1 << 16);
|
||||
|
||||
ioapic_write(m_base, (2 * irq) + 0x10, static_cast<uint32_t>(entry & 0xffffffff));
|
||||
ioapic_write(m_base, (2 * irq) + 0x11, static_cast<uint32_t>(entry >> 32));
|
||||
}
|
||||
|
||||
void
|
||||
ioapic::mask(uint8_t irq, bool masked)
|
||||
{
|
||||
uint32_t entry = ioapic_read(m_base, (2 * irq) + 0x10);
|
||||
if (masked)
|
||||
entry |= (1 << 16);
|
||||
else
|
||||
entry &= ~(1 << 16);
|
||||
|
||||
ioapic_write(m_base, (2 * irq) + 0x10, entry);
|
||||
}
|
||||
|
||||
void
|
||||
ioapic::dump_redirs() const
|
||||
{
|
||||
log::debug(logs::interrupt, "IOAPIC %d redirections:", m_id);
|
||||
|
||||
for (uint8_t i = 0; i < m_num_gsi; ++i) {
|
||||
uint64_t low = ioapic_read(m_base, 0x10 + (2 *i));
|
||||
uint64_t high = ioapic_read(m_base, 0x10 + (2 *i));
|
||||
uint64_t redir = low | (high << 32);
|
||||
if (redir == 0) continue;
|
||||
|
||||
uint8_t vector = redir & 0xff;
|
||||
uint8_t mode = (redir >> 8) & 0x7;
|
||||
uint8_t dest_mode = (redir >> 11) & 0x1;
|
||||
uint8_t polarity = (redir >> 13) & 0x1;
|
||||
uint8_t trigger = (redir >> 15) & 0x1;
|
||||
uint8_t mask = (redir >> 16) & 0x1;
|
||||
uint8_t dest = (redir >> 56) & 0xff;
|
||||
|
||||
log::debug(logs::interrupt, " %2d: vec %3d %s active, %s-triggered %s dest %d: %x",
|
||||
m_base_gsi + i, vector,
|
||||
polarity ? "low" : "high",
|
||||
trigger ? "level" : "edge",
|
||||
mask ? "masked" : "",
|
||||
dest_mode,
|
||||
dest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,14 +56,37 @@ class ioapic :
|
||||
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);
|
||||
/// \arg base_gsi Starting global system interrupt number of this IOAPIC
|
||||
ioapic(uint32_t *base, uint32_t base_gsi);
|
||||
|
||||
uint32_t get_base_gsr() const { return m_base_gsr; }
|
||||
uint32_t get_num_gsr() const { return m_num_gsr; }
|
||||
uint32_t get_base_gsi() const { return m_base_gsi; }
|
||||
uint32_t get_num_gsi() const { return m_num_gsi; }
|
||||
|
||||
/// Set a redirection entry.
|
||||
/// TODO: pick CPU
|
||||
/// \arg source Source interrupt number
|
||||
/// \arg vector Interrupt vector that should be used
|
||||
/// \arg flags Flags for mode/polarity (ACPI MPS INTI flags)
|
||||
/// \arg masked Whether the iterrupt should be suppressed
|
||||
void redirect(uint8_t irq, isr vector, uint16_t flags, bool masked);
|
||||
|
||||
/// Mask or unmask an interrupt to stop/start having it sent to the CPU
|
||||
/// \arg irq The IOAPIC-local irq number
|
||||
/// \arg masked Whether to suppress this interrupt
|
||||
void mask(uint8_t irq, bool masked);
|
||||
|
||||
/// Mask all interrupts on this IOAPIC.
|
||||
void mask_all() { for(int i=0; i<m_num_gsi; ++i) mask(i, true); }
|
||||
|
||||
/// Unmask all interrupts on this IOAPIC.
|
||||
void unmask_all() { for(int i=0; i<m_num_gsi; ++i) mask(i, false); }
|
||||
|
||||
void dump_redirs() const;
|
||||
|
||||
private:
|
||||
uint32_t m_base_gsr;
|
||||
uint32_t m_num_gsr;
|
||||
};
|
||||
uint32_t m_base_gsi;
|
||||
uint32_t m_num_gsi;
|
||||
|
||||
uint8_t m_id;
|
||||
uint8_t m_version;
|
||||
};
|
||||
|
||||
@@ -54,11 +54,12 @@ acpi_table_header::validate(uint32_t expected_type) const
|
||||
|
||||
device_manager::device_manager(const void *root_table) :
|
||||
m_lapic(nullptr),
|
||||
m_ioapics(nullptr),
|
||||
m_num_ioapics(0)
|
||||
{
|
||||
kassert(root_table != 0, "ACPI root table pointer is null.");
|
||||
|
||||
kutil::memset(m_ioapics, 0, sizeof(m_ioapics));
|
||||
|
||||
const acpi1_rsdp *acpi1 =
|
||||
reinterpret_cast<const acpi1_rsdp *>(root_table);
|
||||
|
||||
@@ -83,7 +84,7 @@ device_manager::device_manager(const void *root_table) :
|
||||
ioapic *
|
||||
device_manager::get_ioapic(int i)
|
||||
{
|
||||
return (i < m_num_ioapics) ? m_ioapics + i : nullptr;
|
||||
return (i < m_num_ioapics) ? m_ioapics[i] : nullptr;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -128,36 +129,48 @@ device_manager::load_apic(const acpi_apic *apic)
|
||||
{
|
||||
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);
|
||||
m_lapic = new lapic(local, isr::isrSpurious);
|
||||
|
||||
size_t count = acpi_table_entries(apic, 1);
|
||||
uint8_t const *p = apic->controller_data;
|
||||
uint8_t const *end = p + acpi_table_entries(apic, 1);
|
||||
uint8_t const *end = p + count;
|
||||
|
||||
// Pass one: set up IOAPIC objcts
|
||||
while (p < end) {
|
||||
const uint8_t type = p[0];
|
||||
const uint8_t length = p[1];
|
||||
if (type == 1) {
|
||||
uint32_t *base = reinterpret_cast<uint32_t *>(kutil::read_from<uint32_t>(p+4));
|
||||
uint32_t base_gsr = kutil::read_from<uint32_t>(p+8);
|
||||
m_ioapics[m_num_ioapics++] = new ioapic(base, base_gsr);
|
||||
}
|
||||
p += length;
|
||||
}
|
||||
|
||||
// Pass two: configure APIC objects
|
||||
p = apic->controller_data;
|
||||
while (p < end) {
|
||||
const uint8_t type = p[0];
|
||||
const uint8_t length = p[1];
|
||||
|
||||
switch (type) {
|
||||
case 0: // Local APIC
|
||||
case 1: // I/O APIC
|
||||
break;
|
||||
|
||||
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);
|
||||
case 2: { // Interrupt source override
|
||||
uint8_t source = kutil::read_from<uint8_t>(p+3);
|
||||
isr gsi = isr::irq0 + kutil::read_from<uint32_t>(p+4);
|
||||
uint16_t flags = kutil::read_from<uint16_t>(p+8);
|
||||
|
||||
log::info(logs::devices, " Intr source override IRQ %d -> %d Pol %d Tri %d",
|
||||
source, gsi, (flags & 0x3), ((flags >> 2) & 0x3));
|
||||
|
||||
// TODO: in a multiple-IOAPIC system this might be elsewhere
|
||||
m_ioapics[0]->redirect(source, static_cast<isr>(gsi), flags, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Interrupt source override
|
||||
log::info(logs::devices, " Intr source override IRQ %d -> %d Pol %d Tri %d",
|
||||
kutil::read_from<uint8_t>(p+3),
|
||||
kutil::read_from<uint32_t>(p+4),
|
||||
kutil::read_from<uint16_t>(p+8) & 0x3,
|
||||
(kutil::read_from<uint16_t>(p+8) >> 2) & 0x3);
|
||||
break;
|
||||
|
||||
case 4: {// LAPIC NMI
|
||||
uint8_t cpu = kutil::read_from<uint8_t>(p + 2);
|
||||
uint8_t num = kutil::read_from<uint8_t>(p + 5);
|
||||
@@ -181,5 +194,14 @@ device_manager::load_apic(const acpi_apic *apic)
|
||||
}
|
||||
|
||||
// m_lapic->enable_timer(isr::isrTimer, 128, 3000000);
|
||||
|
||||
for (uint8_t i = 0; i < m_ioapics[0]->get_num_gsi(); ++i) {
|
||||
switch (i) {
|
||||
case 2: break;
|
||||
default: m_ioapics[0]->mask(i, false);
|
||||
}
|
||||
}
|
||||
|
||||
m_ioapics[0]->dump_redirs();
|
||||
m_lapic->enable();
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@ public:
|
||||
ioapic * get_ioapic(int i);
|
||||
|
||||
private:
|
||||
static const int max_ioapics = 16;
|
||||
|
||||
lapic *m_lapic;
|
||||
ioapic *m_ioapics;
|
||||
ioapic *m_ioapics[16];
|
||||
int m_num_ioapics;
|
||||
|
||||
void load_xsdt(const acpi_xsdt *xsdt);
|
||||
|
||||
@@ -47,8 +47,33 @@ IRQ (76, 12, irq12)
|
||||
IRQ (77, 13, irq13)
|
||||
IRQ (78, 14, irq14)
|
||||
IRQ (79, 15, irq15)
|
||||
IRQ (80, 16, irq16)
|
||||
IRQ (81, 17, irq17)
|
||||
IRQ (82, 18, irq18)
|
||||
IRQ (83, 19, irq19)
|
||||
IRQ (84, 20, irq20)
|
||||
IRQ (85, 21, irq21)
|
||||
IRQ (86, 22, irq22)
|
||||
|
||||
ISR (0x7c, isrTimer)
|
||||
ISR (0x7d, isrLINT0)
|
||||
ISR (0x7e, isrLINT1)
|
||||
ISR (0x7f, isrSpurious)
|
||||
|
||||
ISR (0xf0, isrIgnore0)
|
||||
ISR (0xf1, isrIgnore1)
|
||||
ISR (0xf2, isrIgnore2)
|
||||
ISR (0xf3, isrIgnore3)
|
||||
ISR (0xf4, isrIgnore4)
|
||||
ISR (0xf5, isrIgnore5)
|
||||
ISR (0xf6, isrIgnore6)
|
||||
ISR (0xf7, isrIgnore7)
|
||||
|
||||
ISR (0xf8, isrIgnore8)
|
||||
ISR (0xf9, isrIgnore9)
|
||||
ISR (0xfa, isrIgnoreA)
|
||||
ISR (0xfb, isrIgnoreB)
|
||||
ISR (0xfc, isrIgnoreC)
|
||||
ISR (0xfd, isrIgnoreD)
|
||||
ISR (0xfe, isrIgnoreE)
|
||||
ISR (0xff, isrIgnoreF)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "kutil/enum_bitfields.h"
|
||||
#include "kutil/memory.h"
|
||||
#include "console.h"
|
||||
#include "interrupts.h"
|
||||
#include "io.h"
|
||||
#include "log.h"
|
||||
#include "memory_pages.h"
|
||||
|
||||
@@ -20,13 +22,7 @@ enum class gdt_flags : uint8_t
|
||||
|
||||
res_1 = 0x10
|
||||
};
|
||||
|
||||
inline gdt_flags
|
||||
operator | (gdt_flags lhs, gdt_flags rhs)
|
||||
{
|
||||
return static_cast<gdt_flags>(
|
||||
static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
|
||||
}
|
||||
IS_BITFIELD(gdt_flags);
|
||||
|
||||
struct gdt_descriptor
|
||||
{
|
||||
@@ -84,6 +80,29 @@ extern "C" {
|
||||
void idt_dump(const table_ptr &table);
|
||||
void gdt_dump(const table_ptr &table);
|
||||
|
||||
isr
|
||||
operator+(const isr &lhs, int rhs)
|
||||
{
|
||||
using under_t = std::underlying_type<isr>::type;
|
||||
return static_cast<isr>(static_cast<under_t>(lhs) + rhs);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
get_irq(unsigned vector)
|
||||
{
|
||||
switch (vector) {
|
||||
#define ISR(i, name)
|
||||
#define EISR(i, name)
|
||||
#define IRQ(i, q, name) case i : return q;
|
||||
#include "interrupt_isrs.inc"
|
||||
#undef IRQ
|
||||
#undef EISR
|
||||
#undef ISR
|
||||
|
||||
default: return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_gdt_entry(uint8_t i, uint32_t base, uint32_t limit, bool is64, gdt_flags flags)
|
||||
{
|
||||
@@ -111,6 +130,30 @@ set_idt_entry(uint8_t i, uint64_t addr, uint16_t selector, uint8_t flags)
|
||||
g_idt_table[i].reserved = 0;
|
||||
}
|
||||
|
||||
void
|
||||
disable_legacy_pic()
|
||||
{
|
||||
|
||||
static const uint16_t PIC1 = 0x20;
|
||||
static const uint16_t PIC2 = 0xa0;
|
||||
|
||||
// Mask all interrupts
|
||||
outb(0xa1, 0xff);
|
||||
outb(0x21, 0xff);
|
||||
|
||||
// Start initialization sequence
|
||||
outb(PIC1, 0x11); io_wait();
|
||||
outb(PIC2, 0x11); io_wait();
|
||||
|
||||
// Remap into ignore ISRs
|
||||
outb(PIC1+1, static_cast<uint8_t>(isr::isrIgnore0)); io_wait();
|
||||
outb(PIC2+1, static_cast<uint8_t>(isr::isrIgnore8)); io_wait();
|
||||
|
||||
// Tell PICs about each other
|
||||
outb(PIC1+1, 0x04); io_wait();
|
||||
outb(PIC2+1, 0x02); io_wait();
|
||||
}
|
||||
|
||||
void
|
||||
interrupts_init()
|
||||
{
|
||||
@@ -142,6 +185,8 @@ interrupts_init()
|
||||
#undef ISR
|
||||
|
||||
idt_write();
|
||||
disable_legacy_pic();
|
||||
|
||||
log::info(logs::interrupt, "Interrupts enabled.");
|
||||
}
|
||||
|
||||
@@ -173,6 +218,28 @@ isr_handler(registers regs)
|
||||
cons->puts("\nLINT1\n");
|
||||
break;
|
||||
|
||||
case isr::isrIgnore0:
|
||||
case isr::isrIgnore1:
|
||||
case isr::isrIgnore2:
|
||||
case isr::isrIgnore3:
|
||||
case isr::isrIgnore4:
|
||||
case isr::isrIgnore5:
|
||||
case isr::isrIgnore6:
|
||||
case isr::isrIgnore7:
|
||||
case isr::isrIgnore8:
|
||||
case isr::isrIgnore9:
|
||||
case isr::isrIgnoreA:
|
||||
case isr::isrIgnoreB:
|
||||
case isr::isrIgnoreC:
|
||||
case isr::isrIgnoreD:
|
||||
case isr::isrIgnoreE:
|
||||
case isr::isrIgnoreF:
|
||||
/*
|
||||
cons->printf("\nIGNORED PIC INTERRUPT %d\n",
|
||||
(regs.interrupt % 0xff) - 0xf0);
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
cons->set_color(9);
|
||||
cons->puts("\nReceived ISR interrupt:\n");
|
||||
@@ -212,32 +279,41 @@ void
|
||||
irq_handler(registers regs)
|
||||
{
|
||||
console *cons = console::get();
|
||||
uint8_t irq = get_irq(regs.interrupt);
|
||||
|
||||
cons->set_color(9);
|
||||
cons->puts("\nReceived IRQ interrupt:\n");
|
||||
cons->set_color();
|
||||
switch (irq) {
|
||||
case 2:
|
||||
cons->set_color(11);
|
||||
cons->puts(".");
|
||||
cons->set_color();
|
||||
break;
|
||||
|
||||
print_reg("ISR", regs.interrupt);
|
||||
print_reg("ERR", regs.errorcode);
|
||||
cons->puts("\n");
|
||||
default:
|
||||
cons->set_color(11);
|
||||
cons->printf("\nReceived IRQ interrupt: %d (vec %d)\n",
|
||||
irq, regs.interrupt);
|
||||
cons->set_color();
|
||||
|
||||
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(" 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");
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,9 +14,11 @@ enum class isr : uint8_t
|
||||
#undef EISR
|
||||
#undef ISR
|
||||
|
||||
max
|
||||
_zero = 0
|
||||
};
|
||||
|
||||
isr operator+(const isr &lhs, int rhs);
|
||||
|
||||
extern "C" {
|
||||
void interrupts_enable();
|
||||
void interrupts_disable();
|
||||
|
||||
@@ -30,3 +30,8 @@ wrmsr(uint64_t addr, uint64_t value)
|
||||
__asm__ __volatile__ ("wrmsr" :: "c"(addr), "a"(low), "d"(high));
|
||||
}
|
||||
|
||||
void
|
||||
io_wait()
|
||||
{
|
||||
outb(0x80, 0);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ uint64_t rdmsr(uint64_t addr);
|
||||
/// \arg value The value to write
|
||||
void wrmsr(uint64_t addr, uint64_t value);
|
||||
|
||||
/// Pause briefly by doing IO to port 0x80
|
||||
void io_wait();
|
||||
|
||||
}
|
||||
|
||||
const uint16_t COM1 = 0x03f8;
|
||||
|
||||
@@ -72,9 +72,9 @@ kernel_main(popcorn_data *header)
|
||||
pager->map_offset_pointer(&header->frame_buffer, header->frame_buffer_length);
|
||||
|
||||
interrupts_init();
|
||||
interrupts_enable();
|
||||
|
||||
device_manager devices(header->acpi_table);
|
||||
interrupts_enable();
|
||||
|
||||
// int x = 1 / 0;
|
||||
// __asm__ __volatile__("int $15");
|
||||
|
||||
@@ -44,3 +44,12 @@ void memory_initialize_managers(const void *memory_map, size_t map_length, size_
|
||||
/// \returns A pointer to the allocated memory, or nullptr if
|
||||
/// allocation failed.
|
||||
inline void * kalloc(size_t length) { return g_kernel_memory_manager.allocate(length); }
|
||||
|
||||
/// Free kernel space memory.
|
||||
/// \arg p The pointer to free
|
||||
inline void kfree(void *p) { g_kernel_memory_manager.free(p); }
|
||||
|
||||
inline void * operator new (size_t n) { return g_kernel_memory_manager.allocate(n); }
|
||||
inline void * operator new[] (size_t n) { return g_kernel_memory_manager.allocate(n); }
|
||||
inline void operator delete (void *p) { return g_kernel_memory_manager.free(p); }
|
||||
inline void operator delete[] (void *p){ return g_kernel_memory_manager.free(p); }
|
||||
|
||||
Reference in New Issue
Block a user