HelenOS sources
This source file includes following definitions.
- madt_cpu_apic_id
- madt_cpu_enabled
- madt_cpu_bootstrap
- madt_irq_to_pin
- madt_cmp
- madt_l_apic_entry
- madt_io_apic_entry
- madt_intr_src_ovrd_entry
- acpi_madt_parse
#include <assert.h>
#include <typedefs.h>
#include <genarch/acpi/acpi.h>
#include <genarch/acpi/madt.h>
#include <arch/smp/apic.h>
#include <arch/smp/smp.h>
#include <panic.h>
#include <config.h>
#include <log.h>
#include <stdlib.h>
#include <gsort.h>
struct acpi_madt *acpi_madt = NULL;
#ifdef CONFIG_SMP
static int isa_irq_map[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
struct madt_l_apic *madt_l_apic_entries = NULL;
struct madt_io_apic *madt_io_apic_entries = NULL;
static size_t madt_l_apic_entry_index = 0;
static size_t madt_io_apic_entry_index = 0;
static size_t madt_l_apic_entry_cnt = 0;
static size_t madt_io_apic_entry_cnt = 0;
static struct madt_apic_header **madt_entries_index = NULL;
const char *entry[] = {
"L_APIC",
"IO_APIC",
"INTR_SRC_OVRD",
"NMI_SRC",
"L_APIC_NMI",
"L_APIC_ADDR_OVRD",
"IO_SAPIC",
"L_SAPIC",
"PLATFORM_INTR_SRC"
};
static uint8_t madt_cpu_apic_id(size_t i)
{
assert(i < madt_l_apic_entry_cnt);
return ((struct madt_l_apic *)
madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
}
static bool madt_cpu_enabled(size_t i)
{
assert(i < madt_l_apic_entry_cnt);
if (i > 7)
return false;
return ((struct madt_l_apic *)
madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
}
static bool madt_cpu_bootstrap(size_t i)
{
assert(i < madt_l_apic_entry_cnt);
return ((struct madt_l_apic *)
madt_entries_index[madt_l_apic_entry_index + i])->apic_id ==
bsp_l_apic;
}
static int madt_irq_to_pin(unsigned int irq)
{
if (irq >= sizeof(isa_irq_map) / sizeof(int))
return (int) irq;
return isa_irq_map[irq];
}
struct smp_config_operations madt_config_operations = {
.cpu_enabled = madt_cpu_enabled,
.cpu_bootstrap = madt_cpu_bootstrap,
.cpu_apic_id = madt_cpu_apic_id,
.irq_to_pin = madt_irq_to_pin
};
static int madt_cmp(void *a, void *b, void *arg)
{
uint8_t typea = (*((struct madt_apic_header **) a))->type;
uint8_t typeb = (*((struct madt_apic_header **) b))->type;
if (typea > typeb)
return 1;
if (typea < typeb)
return -1;
return 0;
}
static void madt_l_apic_entry(struct madt_l_apic *la, size_t i)
{
if (madt_l_apic_entry_cnt == 0)
madt_l_apic_entry_index = i;
madt_l_apic_entry_cnt++;
if (!(la->flags & 0x1)) {
return;
}
apic_id_mask |= 1 << la->apic_id;
}
static void madt_io_apic_entry(struct madt_io_apic *ioa, size_t i)
{
if (madt_io_apic_entry_cnt == 0) {
madt_io_apic_entry_index = i;
io_apic = (uint32_t *) (sysarg_t) ioa->io_apic_address;
} else {
}
madt_io_apic_entry_cnt++;
}
static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override,
size_t i)
{
assert(override->source < sizeof(isa_irq_map) / sizeof(int));
isa_irq_map[override->source] = override->global_int;
}
void acpi_madt_parse(void)
{
struct madt_apic_header *end = (struct madt_apic_header *)
(((uint8_t *) acpi_madt) + acpi_madt->header.length);
struct madt_apic_header *hdr;
l_apic = (uint32_t *) (sysarg_t) acpi_madt->l_apic_address;
unsigned int madt_entries_index_cnt = 0;
for (hdr = acpi_madt->apic_header; hdr < end;
hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length))
madt_entries_index_cnt++;
madt_entries_index = (struct madt_apic_header **)
malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header *));
if (!madt_entries_index)
panic("Memory allocation error.");
size_t i = 0;
for (hdr = acpi_madt->apic_header; hdr < end;
hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length)) {
madt_entries_index[i] = hdr;
i++;
}
if (!gsort(madt_entries_index, madt_entries_index_cnt,
sizeof(struct madt_apic_header *), madt_cmp, NULL))
panic("Sorting error.");
for (i = 0; i < madt_entries_index_cnt; i++) {
hdr = madt_entries_index[i];
switch (hdr->type) {
case MADT_L_APIC:
madt_l_apic_entry((struct madt_l_apic *) hdr, i);
break;
case MADT_IO_APIC:
madt_io_apic_entry((struct madt_io_apic *) hdr, i);
break;
case MADT_INTR_SRC_OVRD:
madt_intr_src_ovrd_entry((struct madt_intr_src_ovrd *) hdr, i);
break;
case MADT_NMI_SRC:
case MADT_L_APIC_NMI:
case MADT_L_APIC_ADDR_OVRD:
case MADT_IO_SAPIC:
case MADT_L_SAPIC:
case MADT_PLATFORM_INTR_SRC:
log(LF_ARCH, LVL_WARN,
"MADT: Skipping %s entry (type=%" PRIu8 ")",
entry[hdr->type], hdr->type);
break;
default:
if ((hdr->type >= MADT_RESERVED_SKIP_BEGIN) &&
(hdr->type <= MADT_RESERVED_SKIP_END))
log(LF_ARCH, LVL_NOTE,
"MADT: Skipping reserved entry (type=%" PRIu8 ")",
hdr->type);
if (hdr->type >= MADT_RESERVED_OEM_BEGIN)
log(LF_ARCH, LVL_NOTE,
"MADT: Skipping OEM entry (type=%" PRIu8 ")",
hdr->type);
break;
}
}
if (madt_l_apic_entry_cnt > 0)
config.cpu_count = madt_l_apic_entry_cnt;
}
#endif
HelenOS homepage, sources at GitHub