Files
mango/arch/x86_64/acpi/local_apic.cpp

76 lines
1.6 KiB
C++
Raw Normal View History

#include <arch/acpi/local_apic.hpp>
#include <arch/acpi.h>
#include <socks/vm.h>
#include <socks/compiler.h>
#define LAPIC_REG_EOI 0xB0
namespace arch::acpi {
static local_apic lapic;
local_apic::local_apic(uint32_t *base) : base_(base)
{
}
kern_status_t local_apic::find(struct acpi_madt *madt, local_apic& out)
{
phys_addr_t local_apic = madt->m_lapic_ptr;
unsigned char *p = (unsigned char *)madt + sizeof *madt;
unsigned char *madt_end = (unsigned char *)madt + madt->m_base.s_length;
while (p < madt_end) {
struct acpi_madt_record *rec = (struct acpi_madt_record *)p;
struct lapic_override_record *lapic;
switch (rec->r_type) {
case ACPI_MADT_LAPIC_OVERRIDE:
lapic = (struct lapic_override_record *)(rec + 1);
out.base_ = (uint32_t *)vm_phys_to_virt(lapic->l_lapic_ptr);
return KERN_OK;
default:
break;
}
p += rec->r_length;
}
out.base_ = (uint32_t *)vm_phys_to_virt(local_apic);
return KERN_OK;
}
uint32_t local_apic::read(uint32_t reg)
{
return read_once(base_ + (reg >> 2));
}
void local_apic::write(uint32_t reg, uint32_t val)
{
write_once(base_ + (reg >> 2), val);
}
void local_apic::ack()
{
write(LAPIC_REG_EOI, 0);
}
void local_apic::send_ipi(unsigned int dest, unsigned int data)
{
uint32_t dest_val = (read(IPI_DEST) & 0x00FFFFFF) | (dest << 24);
write(IPI_STATUS, 0);
write(IPI_DEST, dest_val);
uint32_t icr_val = (read(IPI_ICR) & 0xFFF00000) | data;
write(IPI_ICR, icr_val);
do {
__asm__ __volatile__("pause" : : : "memory");
} while (read(IPI_ICR) & (1 << 12));
}
local_apic& local_apic::get(void)
{
return lapic;
}
}