// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef KERNEL_LIB_APIC_TABLES_H
#define KERNEL_LIB_APIC_TABLES_H

#include <acpica/acpi.h>
#include <arch/x86/apic.h>
#include <zircon/types.h>

// TODO(edcoyne): rename this to C++ naming.
struct acpi_hpet_descriptor {
    uint64_t address;
    bool port_io;

    uint16_t minimum_tick;
    uint8_t sequence;
};

constexpr uint8_t kAcpiMaxNumaRegions = 5;

struct AcpiNumaRegion {
    uint64_t base_address;
    uint64_t length;
};

struct AcpiNumaDomain {
    uint32_t domain = 0xFF;
    AcpiNumaRegion memory[kAcpiMaxNumaRegions];
    uint8_t memory_count = 0;
};

// Wraps ACPICA functions (except init) to allow testing.
class AcpiTableProvider {
public:
    virtual ~AcpiTableProvider() {}

    // Looks up table, on success sets header to point to table. Maintains
    // ownership of the table's memory.
    virtual ACPI_STATUS GetTable(char* signature, uint32_t instance,
                                 ACPI_TABLE_HEADER** header) const {
        return AcpiGetTable(signature, instance, header);
    }
};

// Designed to read and parse APIC tables, other functions of the APIC
// subsystem are out of scope of this class. This class can work before dynamic memory
// allocation is available.
class AcpiTables {
public:
    AcpiTables(const AcpiTableProvider* tables)
        : tables_(tables) {}

    // Initialize the APIC Tables subsystem, this is separate from initializing
    // the whole APIC subsystem and generally happens much earlier. Argument is
    // ignored.
    static void Initialize(uint32_t);

    // Sets count equal to the number of cpus in the system.
    zx_status_t cpu_count(uint32_t* count) const;

    // Populates the apic_ids array with the apic ids of all cpus in the system.
    // Sets apic_id_count equal to the number of ids written to the array and is
    // bounded by array_size.
    zx_status_t cpu_apic_ids(uint32_t* apic_ids, uint32_t array_size, uint32_t* apic_id_count) const;

    // Sets count equal to the number of IO APICs in the system.
    zx_status_t io_apic_count(uint32_t* count) const;

    // Populates the io_apics array with data about the IO APICS in the system,
    // bounded by array_size. io_apics_count will contain how many io_apics were
    // populated in the array.
    zx_status_t io_apics(io_apic_descriptor* io_apics, uint32_t array_size,
                         uint32_t* io_apics_count) const;

    // Populates overrides with data on all overrides, bounded by array_size.
    // override_count will contain the number of overrides populated in the
    // array.
    zx_status_t interrupt_source_overrides(io_apic_isa_override* overrides, uint32_t array_size,
                                           uint32_t* override_count) const;

    // Sets count equal to the number of overrides registered in the system.
    zx_status_t interrupt_source_overrides_count(uint32_t* count) const;

    // Lookup high precision event timer information. Returns ZX_OK and
    // populates hpet if successful, otherwise returns error.
    zx_status_t hpet(acpi_hpet_descriptor* hpet) const;

    // Vists all pairs of cpu apic id and NumaRegion.
    // Visitor is expected to have the signature:
    // void(const AcpiNumaRegion&, uint32_t)
    template <typename V>
    zx_status_t VisitCpuNumaPairs(V visitor) const;

private:
    zx_status_t NumInMadt(uint8_t type, uint32_t* count) const;

    // For each subtable of type run visitor.
    // We can't take a std::function for the visitor because that can use dynamic
    // memory.
    template <typename V>
    zx_status_t ForEachInMadt(uint8_t type, V visitor) const;

    // Set start and end to the first and last (respectively) records in the
    // MADT table.
    zx_status_t GetMadtRecordLimits(uintptr_t* start, uintptr_t* end) const;

    const AcpiTableProvider* const tables_;

    // Whether APIC tables have ever been initialized.
    static bool initialized_;
};

template <typename V>
zx_status_t AcpiTables::VisitCpuNumaPairs(V visitor) const {
    ACPI_TABLE_HEADER* table = NULL;
    ACPI_STATUS status = tables_->GetTable((char*)ACPI_SIG_SRAT, 1, &table);
    if (status != AE_OK) {
        printf("Could not find SRAT table. ACPICA returned: %u\n", status);
        return ZX_ERR_NOT_FOUND;
    }

    ACPI_TABLE_SRAT* srat = (ACPI_TABLE_SRAT*)table;

    static constexpr size_t kSratHeaderSize = 48;
    static constexpr size_t kMaxNumaDomains = 10;
    AcpiNumaDomain domains[kMaxNumaDomains];

    // First find all numa domains.
    size_t offset = kSratHeaderSize;
    while (offset < srat->Header.Length) {
        ACPI_SUBTABLE_HEADER* sub_header = (ACPI_SUBTABLE_HEADER*)((uint64_t)table + offset);
        DEBUG_ASSERT(sub_header->Length > 0);
        offset += sub_header->Length;
        if (sub_header->Type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) {
            const acpi_srat_mem_affinity* mem = (acpi_srat_mem_affinity*)sub_header;
            if (!(mem->Flags & ACPI_SRAT_MEM_ENABLED)) {
                // Ignore disabled entries.
                continue;
            }

            DEBUG_ASSERT(mem->ProximityDomain < kMaxNumaDomains);

            auto& domain = domains[mem->ProximityDomain];
            domain.memory[domain.memory_count++] = {
                .base_address = mem->BaseAddress,
                .length = mem->Length,
            };

            printf("Numa Region:{ domain: %u base: %#llx length: %#llx (%llu) }\n",
                   mem->ProximityDomain, mem->BaseAddress, mem->Length, mem->Length);
        }
    }

    // Then visit all cpu apic ids and provide the accompanying numa region.
    offset = kSratHeaderSize;
    while (offset < srat->Header.Length) {
        ACPI_SUBTABLE_HEADER* sub_header = (ACPI_SUBTABLE_HEADER*)((uint64_t)table + offset);
        offset += sub_header->Length;
        const auto type = sub_header->Type;
        if (type == ACPI_SRAT_TYPE_CPU_AFFINITY) {
            const auto* cpu = (acpi_srat_cpu_affinity*)sub_header;
            if (!(cpu->Flags & ACPI_SRAT_CPU_ENABLED)) {
                // Ignore disabled entries.
                continue;
            }
            const auto domain = cpu->ProximityDomainLo |
                                (*((uint32_t*)cpu->ProximityDomainHi) & 0xFFFFFF) << 8;
            DEBUG_ASSERT_MSG(domain < kMaxNumaDomains, "%u < %lu", domain, kMaxNumaDomains);
            domains[domain].domain = domain;
            visitor(domains[domain], cpu->ApicId);

        } else if (type == ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY) {
            const auto* cpu = (acpi_srat_x2apic_cpu_affinity*)sub_header;
            if (!(cpu->Flags & ACPI_SRAT_CPU_ENABLED)) {
                // Ignore disabled entries.
                continue;
            }

            DEBUG_ASSERT(cpu->ProximityDomain < kMaxNumaDomains);
            visitor(domains[cpu->ProximityDomain], cpu->ApicId);
        }
    }

    return ZX_OK;
}

#endif // KERNEL_LIB_APIC_TABLES_H
