2023-03-24 14:21:02 +00:00
|
|
|
#include <arch/acpi/local_apic.hpp>
|
2023-05-01 18:13:44 +01:00
|
|
|
#include <arch/acpi.h>
|
2023-03-24 14:21:02 +00:00
|
|
|
#include <socks/vm.h>
|
2023-03-25 20:37:37 +00:00
|
|
|
#include <socks/compiler.h>
|
2023-03-24 14:21:02 +00:00
|
|
|
|
|
|
|
|
#define LAPIC_REG_EOI 0xB0
|
|
|
|
|
|
|
|
|
|
namespace arch::acpi {
|
2023-05-01 18:13:44 +01:00
|
|
|
static local_apic lapic;
|
|
|
|
|
|
2023-03-25 20:37:37 +00:00
|
|
|
local_apic::local_apic(uint32_t *base) : base_(base)
|
|
|
|
|
{
|
|
|
|
|
}
|
2023-03-24 14:21:02 +00:00
|
|
|
|
2023-05-01 18:13:44 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-25 20:37:37 +00:00
|
|
|
uint32_t local_apic::read(uint32_t reg)
|
|
|
|
|
{
|
|
|
|
|
return read_once(base_ + (reg >> 2));
|
|
|
|
|
}
|
2023-03-24 14:21:02 +00:00
|
|
|
|
2023-03-25 20:37:37 +00:00
|
|
|
void local_apic::write(uint32_t reg, uint32_t val)
|
|
|
|
|
{
|
|
|
|
|
write_once(base_ + (reg >> 2), val);
|
|
|
|
|
}
|
2023-03-24 14:21:02 +00:00
|
|
|
|
2023-03-25 20:37:37 +00:00
|
|
|
void local_apic::ack()
|
|
|
|
|
{
|
|
|
|
|
write(LAPIC_REG_EOI, 0);
|
|
|
|
|
}
|
2023-05-01 18:13:44 +01:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2023-03-24 14:21:02 +00:00
|
|
|
}
|