static int parse_madt_ioapic_entry(u32 gsi_base, u64 *phys_addr) { struct acpi_subtable_header *hdr; unsigned long madt_end, entry; struct acpi_table_madt *madt; int apic_id = -1; madt = get_madt_table(); if (!madt) return apic_id; entry = (unsigned long)madt; madt_end = entry + madt->header.length; /* Parse all entries looking for a match. */ entry += sizeof(struct acpi_table_madt); while (entry + sizeof(struct acpi_subtable_header) < madt_end) { hdr = (struct acpi_subtable_header *)entry; if (hdr->type == ACPI_MADT_TYPE_IO_APIC && get_ioapic_id(hdr, gsi_base, phys_addr, &apic_id)) break; else entry += hdr->length; } return apic_id; }
static int map_madt_entry(int type, u32 acpi_id) { unsigned long madt_end, entry; int apic_id = -1; struct acpi_table_madt *madt; madt = get_madt_table(); if (!madt) return apic_id; entry = (unsigned long)madt; madt_end = entry + madt->header.length; /* Parse all entries looking for a match. */ entry += sizeof(struct acpi_table_madt); while (entry + sizeof(struct acpi_subtable_header) < madt_end) { struct acpi_subtable_header *header = (struct acpi_subtable_header *)entry; if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { if (!map_lapic_id(header, acpi_id, &apic_id)) break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) { if (!map_x2apic_id(header, type, acpi_id, &apic_id)) break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { if (!map_lsapic_id(header, type, acpi_id, &apic_id)) break; } entry += header->length; } return apic_id; }
phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id) { phys_cpuid_t phys_id; phys_id = map_mat_entry(handle, type, acpi_id); if (invalid_phys_cpuid(phys_id)) phys_id = map_madt_entry(get_madt_table(), type, acpi_id); return phys_id; }
static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) { unsigned long madt_end, entry; phys_cpuid_t phys_id = PHYS_CPUID_INVALID; /* CPU hardware ID */ struct acpi_table_madt *madt; madt = get_madt_table(); if (!madt) return phys_id; entry = (unsigned long)madt; madt_end = entry + madt->header.length; /* Parse all entries looking for a match. */ entry += sizeof(struct acpi_table_madt); while (entry + sizeof(struct acpi_subtable_header) < madt_end) { struct acpi_subtable_header *header = (struct acpi_subtable_header *)entry; if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { if (!map_lapic_id(header, acpi_id, &phys_id)) break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) { if (!map_x2apic_id(header, type, acpi_id, &phys_id)) break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { if (!map_lsapic_id(header, type, acpi_id, &phys_id)) break; } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { if (!map_gicc_mpidr(header, type, acpi_id, &phys_id)) break; } entry += header->length; } return phys_id; }