void acpi::parse_hpet(time::hpet::timer *& timers, uint64_t & timers_num) { hpet * table = (hpet *)_find_table("HPET"); timers_num = 0; timers = nullptr; if (!table) { screen::debug("\nNo HPET ACPI table, falling back to PIT"); return; } screen::debug("\nFound HPET."); screen::debug("\nNumber: ", table->hpet_number); screen::debug("\nPCI vendor ID: ", table->pci_vendor_id); screen::debug("\nAddress: ", (void *)table->address.address); screen::debug("\nCounter size: ", 32 + 32 * table->counter_size); screen::debug("\nNumber of comparators: ", table->comparator_count + 1); screen::debug("\nMinimum tick: ", table->minimum_tick); uint64_t mmio = memory::vm::allocate_address_range(4096); memory::vm::map(mmio, table->address.address); timers_num = 1; uint64_t address = memory::vm::allocate_address_range(sizeof(time::hpet::timer)); memory::vm::map_multiple(address, address + sizeof(time::hpet::timer)); timers = new ((void *)address) time::hpet::timer{ table->hpet_number, table->pci_vendor_id, mmio, table->counter_size, (uint8_t)(table->comparator_count + 1), table->minimum_tick, table->page_protection }; _free_table(); }
void acpi::initialize() { _root_address = memory::vm::allocate_address_range(8 * 4096); _table_address = memory::vm::allocate_address_range(8 * 4096); _find_rsdp(); _find_table("FFFF"); }
struct session * _find_session( struct hashtable * table, sid_t id ) { struct hashnode * node = _find_table( table, id, 0 ); if ( node == NULL ) { return NULL; } if ( node->session == NULL ) { return NULL; } assert( node->session->id == id ); return node->session; }
int32_t _remove_session( struct hashtable * table, struct session * s ) { struct hashnode * node = _find_table( table, s->id, 0 ); if ( node == NULL ) { return -1; } if ( node->session == NULL ) { return -2; } assert( node->session == s ); --table->count; node->session = NULL; return 0; }
int32_t _append_session( struct hashtable * table, struct session * s ) { struct hashnode * node = _find_table( table, s->id, 1 ); if ( unlikely(node == NULL) ) { return -1; } if ( unlikely( node->session != NULL && node->session->id == s->id ) ) { syslog(LOG_WARNING, "%s(Index=%d): the SID (Seq=%u, Sid=%ld) conflict !", __FUNCTION__, (int32_t)SID_INDEX(s->id), (uint32_t)SID_SEQ(s->id), s->id ); return -2; } ++table->count; node->session = s; return 0; }
void acpi::parse_madt(processor::core *& cores, uint64_t & core_num, processor::ioapic *& ioapics, uint64_t & ioapic_num, processor::interrupt_entry * ints) { madt * table = (madt *)_find_table("APIC"); if (!table) { return; } uint64_t lic_address = table->lic_address; core_num = 0; ioapic_num = 0; madt_entry * entry = table->entries; while ((uint64_t)entry - (uint64_t)table < table->length) { if (entry->type == 0 || entry->type == 9) { ++core_num; } else if (entry->type == 1) { ++ioapic_num; } entry = (acpi::madt_entry *)((uint64_t)entry + entry->length); } { uint64_t cores_address = memory::vm::allocate_address_range(core_num * sizeof(processor::core)); uint64_t ioapics_address = memory::vm::allocate_address_range(ioapic_num * sizeof(processor::ioapic)); memory::vm::map_multiple(cores_address, cores_address + core_num * sizeof(processor::core)); memory::vm::map_multiple(ioapics_address, ioapics_address + ioapic_num * sizeof(processor::ioapic)); cores = (processor::core *)cores_address; ioapics = (processor::ioapic *)ioapics_address; } core_num = 0; ioapic_num = 0; entry = table->entries; while ((uint64_t)entry - (uint64_t)table < table->length) { switch (entry->type) { case 0: { auto lapic = (acpi::madt_lapic_entry *)((entry + 1)); if (lapic->flags & 1) { new ((void *)(cores + core_num++)) processor::core{ lapic->apic_id, lapic->acpi_id }; screen::debug("\nFound LAPIC entry: ", lapic->apic_id); } break; } case 1: { auto ioapic = (acpi::madt_ioapic_entry *)((entry + 1)); new ((void *)(ioapics + ioapic_num++)) processor::ioapic{ ioapic->apic_id, ioapic->base_int, ioapic->base_address }; screen::debug("\nFound I/O APIC entry: ", ioapic->apic_id, ", handling vectors from ", ioapic->base_int, " to ", ioapics[ioapic_num - 1].end()); break; } case 2: { auto iso = (acpi::madt_int_override_entry *)(entry + 1); ints[iso->source].set(iso->source, iso->int_number, iso->flags); screen::debug("\nFound redirection entry: ", iso->source, " -> ", iso->int_number, ", polarity: "); switch (iso->flags & 3) { case 0: screen::debug("standard"); break; case 1: screen::debug("active high"); break; case 2: screen::debug("RESERVED"); PANIC("Reserved polarity in MADT"); case 3: screen::debug("active low"); } screen::debug(", trigger mode: "); switch ((iso->flags >> 2) & 3) { case 0: screen::debug("standard"); break; case 1: screen::debug("edge"); break; case 2: screen::debug("RESERVED"); PANIC("Reserved trigger mode in MADT"); case 3: screen::debug("level"); } } case 3: { auto nmi = (acpi::madt_nmi_source_entry *)((entry + 1)); for (uint64_t i = 0; i < ioapic_num; ++i) { if (ioapics[i].set_global_nmi(nmi->int_number, nmi->flags)) { break; } } break; } case 5: { auto override = (acpi::madt_lapic_address_override_entry *)((entry + 1)); lic_address = override->base_address; break; } case 9: { auto x2apic = (acpi::madt_x2apic_entry *)((entry + 1)); if (x2apic->flags & 1) { new ((void *)(cores + core_num++)) processor::core{ x2apic->x2apic_id, x2apic->acpi_uuid, false }; screen::debug("\nFound x2APIC entry: ", x2apic->x2apic_id); } break; } } entry = (acpi::madt_entry *)((uint64_t)entry + entry->length); } entry = table->entries; while ((uint64_t)entry - (uint64_t)table < table->length) { switch (entry->type) { case 4: { auto lapic_nmi = (acpi::madt_lapic_nmi_entry *)((entry + 1)); if (lapic_nmi->acpi_id == 0xff) { for (uint64_t i = 0; i < core_num; ++i) { if (cores[i].lapic()) { cores[i].set_nmi(lapic_nmi->int_number, lapic_nmi->flags); } } break; } for (uint64_t idx = 0; idx < core_num; ++idx) { if (cores[idx].acpi_id() == lapic_nmi->acpi_id) { cores[idx].set_nmi(lapic_nmi->int_number, lapic_nmi->flags); break; } if (idx == core_num - 1) { screen::debug(tag::acpi, "Ignoring NMI vector entry for unknown ACPI ID ", lapic_nmi->acpi_id, "\n"); } } break; } case 10: { auto x2apic_nmi = (acpi::madt_x2apic_nmi_entry *)((entry + 1)); if (x2apic_nmi->acpi_uuid == 0xffffffff) { for (uint64_t i = 0; i < core_num; ++i) { cores[i].set_nmi(x2apic_nmi->int_number, x2apic_nmi->flags); } break; } for (uint64_t idx = 0; idx < core_num; ++idx) { if (cores[idx].acpi_id() == x2apic_nmi->acpi_uuid) { cores[idx].set_nmi(x2apic_nmi->int_number, x2apic_nmi->flags); break; } if (idx == core_num - 1) { screen::debug(tag::acpi, "Ignoring x2APIC NMI entry for unknown ACPI UUID ", x2apic_nmi->acpi_uuid, "\n"); } } break; } } entry = (acpi::madt_entry *)((uint64_t)entry + entry->length); } memory::vm::map(processor::get_lapic_base(), lic_address); _free_table(); }