x86_64: acpi: bring up other APs in long mode

This commit is contained in:
2023-05-01 18:13:44 +01:00
parent 223b37a113
commit 4677c881e1
6 changed files with 201 additions and 114 deletions

View File

@@ -21,7 +21,6 @@ static unsigned int bsp_id = (unsigned int)-1;
using namespace arch::acpi;
static uint32_t *lapic_base;
static struct queue io_apics;
extern "C" {
@@ -46,45 +45,13 @@ static void disable_8259(void)
outportb(PIC2_DATA, 0xFF);
}
static void *find_lapic(struct acpi_madt *madt)
kern_status_t local_apic_enable(struct acpi_madt *madt)
{
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);
return vm_phys_to_virt(lapic->l_lapic_ptr);
default:
break;
}
p += rec->r_length;
}
return vm_phys_to_virt(local_apic);
}
kern_status_t local_apic_enable(void)
{
struct acpi_madt *madt = (struct acpi_madt *)acpi_find_sdt(ACPI_SIG_MADT);
if (!madt) {
return KERN_UNSUPPORTED;
}
apic_set_base(apic_get_base());
lapic_base = (uint32_t *)find_lapic(madt);
local_apic lapic(lapic_base);
local_apic::find(madt, local_apic::get());
lapic.write(0xF0, 0x1FF);
lapic.ack();
local_apic::get().write(0xF0, 0x1FF);
local_apic::get().ack();
return KERN_OK;
}
@@ -136,7 +103,8 @@ static struct irq_hook lapic_clock_irq_hook = {
void local_apic_config_timer(void)
{
local_apic lapic(lapic_base);
local_apic& lapic = local_apic::get();
lapic.write(local_apic::TIMER_DIV, 0x3);
lapic.write(local_apic::TIMER_INITCOUNT, (uint32_t)-1);
clock_wait(10);
@@ -223,7 +191,7 @@ kern_status_t apic_init(void)
init_all_ioapic(madt);
}
local_apic_enable();
local_apic_enable(madt);
disable_8259();
apic_enabled = 1;
@@ -243,8 +211,7 @@ kern_status_t apic_init(void)
void irq_ack(unsigned int vec)
{
if (apic_enabled) {
local_apic lapic(lapic_base);
lapic.ack();
local_apic::get().ack();
} else {
if (vec >= 40) {
outportb(0xA0, 0x20);