[Bug 278233] PHYS_IN_DMAP and VIRT_IN_DMAP macros assume contiguous DMAP memory
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 07 Apr 2024 13:00:47 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=278233 Bug ID: 278233 Summary: PHYS_IN_DMAP and VIRT_IN_DMAP macros assume contiguous DMAP memory Product: Base System Version: Unspecified Hardware: arm64 OS: Any Status: New Severity: Affects Only Me Priority: --- Component: arm Assignee: freebsd-arm@FreeBSD.org Reporter: zeev@amazon.com Created attachment 249802 --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=249802&action=edit bug fix: support non-contiguous memory in PHYS_IN_DMAP and VIRT_IN_DMAP The issue was observed on r8g.metal-48xl which is a coherent Graviton4-based system with 2 SoCs. ENA driver crashes when trying to remap BAR2 memory with WC attributes: ena0: Elastic Network Adapter (ENA)ena v2.7.0 panic: Invalid DMAP table level: 0 cpuid = 0 time = 1 KDB: stack backtrace: db_trace_self() at db_trace_self db_trace_self_wrapper() at db_trace_self_wrapper+0x38 vpanic() at vpanic+0x1a4 panic() at panic+0x48 pmap_change_props_locked() at pmap_change_props_locked+0x6dc pmap_change_props_locked() at pmap_change_props_locked+0x550 pmap_change_attr() at pmap_change_attr+0x5c ena_attach() at ena_attach+0x264 device_attach() at device_attach+0x3fc device_probe_and_attach() at device_probe_and_attach+0x80 bus_generic_attach() at bus_generic_attach+0x1c pci_attach() at pci_attach+0xec ... The memory map on those systems has 2 large DRAM regions, one for each SoC. The regions are non contiguous and IO memory that includes the PCI BARs for the 2nd SoC is between those 2 regions. So the memory map looks like following DRAM region 0: 0x10000000000-0x1c000000000 IO memory(SoC1): 0x41000000000-0x050000000000 DRAM region 1: 0x50000000000-0x5c000000000 PHYS_IN_DMAP and VIRT_IN_DMAP macros in arm64 vmparam.h that inherently assume that the DMAP region is contiguous with current implementation: /* True if pa is in the dmap range */ #define PHYS_IN_DMAP(pa) ((pa) >= DMAP_MIN_PHYSADDR && \ (pa) < DMAP_MAX_PHYSADDR) /* True if va is in the dmap range */ #define VIRT_IN_DMAP(va) ((va) >= DMAP_MIN_ADDRESS && \ (va) < (dmap_max_addr)) This causes the following check in sys/arm64/arm64/pmap.c, pmap_change_props_locked() to wrongly conclude that PCI memory is part of DMAP: if (!VIRT_IN_DMAP(tmpva) && PHYS_IN_DMAP(pa)) { /* * Keep the DMAP memory in sync. */ rv = pmap_change_props_locked( PHYS_TO_DMAP(pa), pte_size, prot, mode, true); if (rv != 0) return (rv); } And consequent lookup of this memory in DMAP page tables fails, as PCI memory is not mapped in DMAP. Attached a proposed patch that stores a list of DMAP regions and changes the macros above to functions that check the address vs the list. (Based on https://reviews.freebsd.org/D3538) The instance boots properly after applying this patch. -- You are receiving this mail because: You are the assignee for the bug.