// Copyright 2016 The Fuchsia Authors
// Copyright (c) 2009 Corey Tabaka
// Copyright (c) 2015 Intel Corporation
// Copyright (c) 2016 Travis Geiselbrecht
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#if WITH_DEV_PCIE

#include <arch/x86/feature.h>
#include <dev/pcie_bus_driver.h>
#include <dev/pcie_device.h>
#include <fbl/algorithm.h>
#include <fbl/ref_ptr.h>
#include <inttypes.h>
#include <trace.h>
#include <zircon/types.h>

#define LOCAL_TRACE 0

// Top-of-lower-usable-DRAM quirk.
//
// Intel processors sometimes steal a bit memory for GPU and SMM needs.  When
// they do, the BIOS/bootloader sometimes does not report these regions as
// reserved in the memory map passed to the OS, they just remove them from the
// usable RAM portion of the memory map.  If we fail to remove these regions
// from the set allocatable MMIO regions used by the PCIe bus driver, we can end
// up allocating portions of the bus containing GPU/SMM stolen memory to devices
// to use for BAR windows (this would be Very Bad).
//
// For processors which have a "TOLUD" register (top of lower usable DRAM), we
// can simply subtract out the region [0, TOLUD) from the PCIe bus driver's
// allocatable regions.  This register (on 6th gen Intel Core processors at
// least) lives in the config space for the host bridge device.  Look for it and
// subtract out the region.  If we don't find the register, and cannot be sure
// that the target we are running on does not need this special treatment, log a
// big warning so someone can come and update this code to do the right thing.
static void pcie_tolud_quirk(const fbl::RefPtr<PcieDevice>& dev) {
    // TODO(johngro): Expand this table as we add support for new
    // processors/chipsets.  Set offset to 0 if no action needs to be taken.
    static const struct {
        uint32_t match;
        uint32_t mask;
        uint16_t offset;
    } TOLUD_CHIPSET_LUT[] = {
        // QEMU's emulation of Intel Q35.   No TOLUD register that I know of.
        {.match = 0x808629c0, .mask = 0xFFFFFFFF, .offset = 0x0},
        // PIIX4
        {.match = 0x80861237, .mask = 0xFFFFFFFF, .offset = 0x0},
        // Second/Third gen core family
        {.match = 0x80860100, .mask = 0xFFFFFF00, .offset = 0xBC},
        // Intel 6th Generation Core Family (Skylake)
        {.match = 0x80861900, .mask = 0xFFFFFF00, .offset = 0xBC},

        // Intel 7th Generation Core Family (Kaby Lake)
        //
        // TODO(johngro) : Get confirmation of this.  Intel's public docs claim
        // that the DID is 0x19xx, like Skylake.  Hardware I have seen
        // (i3-7100u), as well as HW that people have talked about online
        // (i5-7500u, as well as some desktop SKUs), however, all seem to use
        // 0x59xx.
        {.match = 0x80865900, .mask = 0xFFFFFF00, .offset = 0xBC},
    };

    // only makes sense on intel hardware
    if (x86_vendor != X86_VENDOR_INTEL)
        return;

    static bool found_chipset_device = false;

    // If we have already recognized our chipset and taken appropriate action,
    // then there is nothing left for us to do.
    if (found_chipset_device)
        return;

    // If dev is nullptr, then the PCIe bus driver is about to start allocating
    // resources.  If we have not recognized the chipset we are running on yet,
    // log a big warning.  Someone needs to come into this code and add support
    // for the unrecognized chipset (even if not special action needs to be
    // taken, the quirk needs to be taught to recognize the chipset we are
    // running on).
    if (dev == nullptr) {
        if (!found_chipset_device) {
            TRACEF("WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING\n");
            TRACEF("WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING\n");
            TRACEF("PCIe TOLUD quirk was not able to identify the chipset we are running on!\n");
            TRACEF("Someone needs to teach this quirk about the new chipset!\n");
            TRACEF("WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING\n");
            TRACEF("WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING\n");
        }
        return;
    }

    // The device we are looking for will always be a BDF 00:00.0
    if (dev->bus_id() || dev->dev_id() || dev->func_id())
        return;

    // Concatenate the vendor and device ID and search our LUT to see if we
    // recognize this host bridge.
    size_t i;
    uint32_t vid_did = (static_cast<uint32_t>(dev->vendor_id()) << 16) | dev->device_id();
    for (i = 0; i < fbl::count_of(TOLUD_CHIPSET_LUT); ++i) {
        const auto& entry = TOLUD_CHIPSET_LUT[i];
        if ((vid_did & entry.mask) == entry.match)
            break;
    }

    if (i >= fbl::count_of(TOLUD_CHIPSET_LUT))
        return;

    // Looks like we recognize this chip.  Check our table to see if there is a
    // TOLUD register we should read.
    uint16_t offset = TOLUD_CHIPSET_LUT[i].offset;
    if (offset) {
        static constexpr uint32_t TOLUD_MASK = 0xFFF00000;
        auto tolud_reg = PciReg32(offset);
        uint32_t tolud_val = dev->config()->Read(tolud_reg) & TOLUD_MASK;

        // Subtract out the TOLUD region from the PCI driver's allocatable MMIO region.
        if (tolud_val) {
            LTRACEF("TOLUD Quirk subtracting region [0x%08x, 0x%08x)\n", 0u, tolud_val);
            zx_status_t res = dev->driver().SubtractBusRegion(0u, tolud_val, PciAddrSpace::MMIO);
            if (res != ZX_OK)
                TRACEF("WARNING : PCIe TOLUD Quirk failed to subtract region "
                       "[0x%08x, 0x%08x) (res %d)!\n",
                       0u, tolud_val, res);
        }
    }

    found_chipset_device = true;
}

static void pcie_amd_topmem_quirk(const fbl::RefPtr<PcieDevice>& dev) {
    // only makes sense on AMD hardware
    if (x86_vendor != X86_VENDOR_AMD)
        return;

    // do this the first time
    static bool initialized = false;
    if (initialized)
        return;

    // only do this once
    initialized = true;

    // see if the TOP_MEM and TOP_MEM2 msrs are active by reading the SYSCFG MSR
    uint64_t syscfg = read_msr(0xc0010010);
    LTRACEF("SYSCFG 0x%lx\n", syscfg);

    // for AMD, use the TOP_MEM and TOP_MEM2 MSR
    // see AMD64 architecture programming manual, volume 2, rev 3.25, page 209
    uint64_t top_mem = 0;
    uint64_t top_mem2 = 0;
    if (syscfg & (1 << 20)) { // MtrrVarDramEn
        top_mem = read_msr(0xc001001a);
    }
    if (syscfg & (1 << 21)) { // MtrrTom2En
        top_mem2 = read_msr(0xc001001d);
    }

    /* mask out reserved bits */
    top_mem &= ((1ULL << 52) - 1);
    top_mem &= ~((1ULL << 23) - 1);
    top_mem2 &= ((1ULL << 52) - 1);
    top_mem2 &= ~((1ULL << 23) - 1);

    LTRACEF("TOP_MEM %#" PRIx64 " TOP_MEM2 %#" PRIx64 "\n", top_mem, top_mem2);

    if (top_mem >= UINT32_MAX) {
        TRACEF("WARNING: AMD TOP_MEM >= 4GB\n");
    }

    if (top_mem && dev) {
        zx_status_t res = dev->driver().SubtractBusRegion(0u, top_mem, PciAddrSpace::MMIO);
        if (res != ZX_OK) {
            TRACEF("WARNING : PCIe AMD top_mem quirk failed to subtract region "
                   "[0x0, %#" PRIx64 ") (res %d)!\n",
                   top_mem, res);
        }
    }

    if (top_mem2 && dev) {
        uint64_t max = (1ULL << x86_physical_address_width());

        // TODO: make this subtractive on (0, TOP_MEM2) when we start preloading the
        // upper pci range.
        zx_status_t res = dev->driver().AddBusRegion(top_mem2, max, PciAddrSpace::MMIO);
        if (res != ZX_OK) {
            TRACEF("WARNING : PCIe AMD top_mem quirk failed to add 64bit region "
                   "[%#" PRIx64 ", %#" PRIx64 ") (res %d)!\n",
                   top_mem2, max, res);
        }
    }
}

extern const PcieBusDriver::QuirkHandler pcie_quirk_handlers[] = {
    pcie_tolud_quirk,
    pcie_amd_topmem_quirk,
    nullptr,
};

#endif // WITH_DEV_PCIE
