From 536db45418c8d01848e59d163e2a0401ac13b84d Mon Sep 17 00:00:00 2001 From: Matheus Date: Mon, 7 Aug 2023 21:30:24 -0300 Subject: [PATCH] x86_64 pci: properly map ECAM and fix access to it --- kernel-src/include/x86-64/arch/pci.h | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/kernel-src/include/x86-64/arch/pci.h b/kernel-src/include/x86-64/arch/pci.h index 0a9b2c7b..b29994f3 100644 --- a/kernel-src/include/x86-64/arch/pci.h +++ b/kernel-src/include/x86-64/arch/pci.h @@ -8,6 +8,7 @@ #include #include #include +#include #include static size_t mcfgentrycount; @@ -51,8 +52,8 @@ static uint32_t mcfg_read32(int bus, int device, int function, uint32_t offset) if (entry == NULL) return 0xffffffff; - uint64_t base = (uint64_t)MAKE_HHDM(entry->address); - uint32_t *address = (uint32_t *)(base | ((bus - entry->startbus) << 20) | (device << 15) | (function << 12) | (offset & ~0x3)); + uint64_t base = (uint64_t)entry->address; + volatile uint32_t *address = (uint32_t *)((uintptr_t)base + (((bus - entry->startbus) << 20) | (device << 15) | (function << 12) | (offset & ~0x3))); return *address; } @@ -60,8 +61,8 @@ static uint32_t mcfg_read32(int bus, int device, int function, uint32_t offset) static void mcfg_write32(int bus, int device, int function, uint32_t offset, uint32_t value) { mcfgentry_t *entry = getmcfgentry(bus); - uint64_t base = (uint64_t)MAKE_HHDM(entry->address); - uint32_t *address = (uint32_t *)(base | ((bus - entry->startbus) << 20) | (device << 15) | (function << 12) | (offset & ~0x3)); + uint64_t base = (uint64_t)entry->address; + volatile uint32_t *address = (uint32_t *)((uintptr_t)base + (((bus - entry->startbus) << 20) | (device << 15) | (function << 12) | (offset & ~0x3))); *address = value; } @@ -71,15 +72,30 @@ static uint64_t msiformatmessage(uint32_t *data, int vector, int edgetrigger, in return 0xfee00000 | (_cpu()->id << 12); } +// in PCIe, every function has 4096 bytes of config space for it. +// there are 8 functions per device and 32 devices per bus +#define MCFG_MAPPING_SIZE(buscount) (4096l * 8l * 32l * (buscount)) + static void pci_archinit() { mcfg_t *mcfg = arch_acpi_findtable("MCFG", 0); + if (mcfg) { printf("pci: MCFG table found. Using extended configuration space\n"); - mcfgentries = mcfg->entries; pci_archread32 = mcfg_read32; pci_archwrite32 = mcfg_write32; mcfgentrycount = (mcfg->header.length - sizeof(sdtheader_t)) / sizeof(mcfgentry_t); - // TODO map mcfg entries as UC + mcfgentries = alloc(sizeof(mcfgentry_t) * mcfgentrycount); + __assert(mcfgentries); + memcpy(mcfgentries, mcfg->entries, sizeof(mcfgentry_t) * mcfgentrycount); + for (int i = 0; i < mcfgentrycount; ++i) { + void *phys = (void *)mcfgentries[i].address; + uintmax_t pageoffset = (uintptr_t)phys % PAGE_SIZE; + size_t mappingsize = pageoffset + MCFG_MAPPING_SIZE(mcfgentries[i].endbus - mcfgentries[i].startbus + 1); + void *virt = vmm_map(NULL, mappingsize, VMM_FLAGS_PHYSICAL, + ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC | ARCH_MMU_FLAGS_UC, phys); + __assert(virt); + mcfgentries[i].address = (uintptr_t)virt + pageoffset; + } } else { printf("pci: MCFG table not found. Falling back to legacy access mechanism\n"); pci_archread32 = legacy_read32;