#include #include #include #include #include #include #include #include #include #include #include //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->apic_id; cores->corecount++; } } } }