180 lines
4.3 KiB
C
180 lines
4.3 KiB
C
#include <stdint.h>
|
|
#include <libc.h>
|
|
#include <acpi.h>
|
|
#include <int.h>
|
|
#include <kernel.h>
|
|
#include <stddef.h>
|
|
#include <heap.h>
|
|
#include <printf.h>
|
|
#include <smp.h>
|
|
#include <madt.h>
|
|
#include <cpuid.h>
|
|
|
|
//madt entry types. there's more, we don't need em yet
|
|
#define LOCAL_APIC 0
|
|
#define IO_APIC 1
|
|
#define IO_INT_OVERRIDE 2
|
|
#define IO_APIC_NMI_SOURCE 3
|
|
#define IO_APIC_NMI 4
|
|
#define MADT_LOCAL_APIC_ADDR_OVERRIDE 5
|
|
|
|
struct madt_sdt {
|
|
sdt_head header;
|
|
uint32_t apic_base;
|
|
uint32_t flags;
|
|
} __attribute__((packed));
|
|
|
|
struct madt_entry {
|
|
uint8_t type;
|
|
uint8_t length;
|
|
} __attribute__((packed));
|
|
|
|
struct madt_local_apic {
|
|
uint8_t processor_id;
|
|
uint8_t apic_id;
|
|
uint32_t flags;
|
|
} __attribute__((packed));
|
|
|
|
struct madt_local_apic_override {
|
|
uint16_t reserved;
|
|
void *apic_base;
|
|
} __attribute__((packed));
|
|
|
|
struct madt_ioapic {
|
|
uint8_t apic_id;
|
|
uint8_t reserved;
|
|
uint32_t addr;
|
|
uint32_t gsi_base;
|
|
} __attribute__((packed));
|
|
|
|
struct madt_io_int_override {
|
|
uint8_t bus_src; //not sure what this is used for.
|
|
uint8_t irq;
|
|
uint32_t global_vector;
|
|
uint16_t flags;
|
|
} __attribute__((packed));
|
|
|
|
static struct madt_sdt *madt;
|
|
|
|
|
|
void init_madt() {
|
|
madt = find_sdt(SDT_MADT);
|
|
}
|
|
|
|
void debug_madt() {
|
|
struct madt_entry *entry;
|
|
for(
|
|
entry = (void *)madt + sizeof(*madt);
|
|
(void *)entry < (void *)madt + madt->header.length;
|
|
entry = (void *)entry + entry->length) {
|
|
printf("MADT debug: ");
|
|
switch(entry->type) {
|
|
case LOCAL_APIC:
|
|
printf("local APIC\n");
|
|
break;
|
|
case IO_APIC:
|
|
printf("IOAPIC\n");
|
|
break;
|
|
case IO_INT_OVERRIDE:
|
|
printf("IOAPIC interupt override\n");
|
|
break;
|
|
case IO_APIC_NMI_SOURCE:
|
|
printf("IOAPIC NMI\n");
|
|
break;
|
|
case IO_APIC_NMI:
|
|
printf("Local APIC NMI\n");
|
|
break;
|
|
case MADT_LOCAL_APIC_ADDR_OVERRIDE:
|
|
printf("APIC addr override\n");
|
|
break;
|
|
default:
|
|
printf("other\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned int irq_to_gsi(unsigned int irq) {
|
|
struct madt_io_int_override *irq_override;
|
|
struct madt_entry *entry;
|
|
|
|
for(
|
|
entry = (void *)madt + sizeof(*madt);
|
|
(void *)entry < (void *)madt + madt->header.length;
|
|
entry = (void *)entry + entry->length) {
|
|
|
|
if(entry->type == IO_INT_OVERRIDE) {
|
|
irq_override = (void *)entry + 2;
|
|
if(irq_override->irq == irq) return irq_override->global_vector;
|
|
}
|
|
}
|
|
return (uint32_t)irq; //no entry found
|
|
}
|
|
|
|
void get_ioapic(struct ioapic_fixedlen *ret) {
|
|
struct madt_entry *entry;
|
|
struct madt_ioapic *mpio_entry;
|
|
|
|
ret->count = 0;
|
|
|
|
for(
|
|
entry = (void *)madt + sizeof(*madt);
|
|
(void *)entry < (void *)madt + madt->header.length;
|
|
entry = (void *)entry + entry->length) {
|
|
if(entry->type == IO_APIC) {
|
|
mpio_entry = (void *)entry + 2;
|
|
if(ret->count) {
|
|
ret->ioapic = realloc(ret->ioapic, ++ret->count * sizeof(struct ioapic_t));
|
|
}
|
|
else {
|
|
ret->ioapic = malloc(++ret->count * sizeof(struct ioapic_t));
|
|
}
|
|
ret->ioapic[ret->count - 1].address = PHYS_TO_VIRT((uintptr_t)mpio_entry->addr);
|
|
ret->ioapic[ret->count - 1].gsi_base = mpio_entry->gsi_base;
|
|
}
|
|
}
|
|
}
|
|
|
|
lapic_t get_lapic() {
|
|
struct madt_local_apic_override *ap_override;
|
|
struct madt_entry *entry;
|
|
|
|
for(
|
|
entry = (void *)madt + sizeof(*madt);
|
|
(void *)entry < (void *)madt + madt->header.length;
|
|
entry = (void *)entry + entry->length) {
|
|
|
|
if(entry->type == MADT_LOCAL_APIC_ADDR_OVERRIDE) {
|
|
ap_override = (void *)entry + 2;
|
|
|
|
return (lapic_t)PHYS_TO_VIRT(ap_override->apic_base);
|
|
}
|
|
}
|
|
return (lapic_t)PHYS_TO_VIRT((uint64_t)madt->apic_base);
|
|
}
|
|
|
|
void get_coreinfo(struct cores_info *cores) {
|
|
struct madt_local_apic *ap_info;
|
|
struct madt_entry *entry;
|
|
uint32_t unused_cpuid, ebx;
|
|
|
|
__get_cpuid(1, &unused_cpuid, &ebx, &unused_cpuid, &unused_cpuid);
|
|
cores->bsp = ebx << 24;
|
|
|
|
bzero(cores, sizeof(*cores));
|
|
|
|
for(
|
|
entry = (void *)madt + sizeof(*madt);
|
|
(void *)entry < (void *)madt + madt->header.length;
|
|
entry = (void *)entry + entry->length) {
|
|
|
|
if(entry->type == LOCAL_APIC) {
|
|
ap_info = (void *)entry + 2;
|
|
if(ap_info->flags & 1) {
|
|
cores->apic_id[cores->corecount] = ap_info->processor_id;
|
|
cores->corecount++;
|
|
}
|
|
}
|
|
}
|
|
}
|