svn commit: r351439 - in stable/11/sys/amd64: amd64 include pci
John Baldwin
jhb at FreeBSD.org
Fri Aug 23 22:03:52 UTC 2019
Author: jhb
Date: Fri Aug 23 22:03:50 2019
New Revision: 351439
URL: https://svnweb.freebsd.org/changeset/base/351439
Log:
MFC 339432: Do not flush cache for PCIe config window.
Apparently AMD machines cannot tolerate this. This was uncovered by
r339386, where cache flush started really flushing the requested range.
Introduce pmap_mapdev_pciecfg(), which simply does not flush cache
comparing with pmap_mapdev(). It assumes that the MCFG region was
never accessed through the cacheable mapping, which is most likely
true for machine to boot at all.
Note that i386 does not need the change, since the architecture
handles access per-page due to the KVA shortage, and page remapping
already does not flush the cache.
MFC note: 339386 has not been MFC'd to 11, but merging this change
should still be fine for 11 and reduces conflicts in MFCs of other
changes.
Modified:
stable/11/sys/amd64/amd64/pmap.c
stable/11/sys/amd64/include/pmap.h
stable/11/sys/amd64/pci/pci_cfgreg.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/amd64/amd64/pmap.c
==============================================================================
--- stable/11/sys/amd64/amd64/pmap.c Fri Aug 23 21:05:37 2019 (r351438)
+++ stable/11/sys/amd64/amd64/pmap.c Fri Aug 23 22:03:50 2019 (r351439)
@@ -634,7 +634,8 @@ static void pmap_pvh_free(struct md_page *pvh, pmap_t
static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap,
vm_offset_t va);
-static int pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode);
+static int pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode,
+ bool noflush);
static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va);
static boolean_t pmap_demote_pde_locked(pmap_t pmap, pd_entry_t *pde,
vm_offset_t va, struct rwlock **lockp);
@@ -6834,8 +6835,8 @@ pmap_pde_attr(pd_entry_t *pde, int cache_bits, int mas
* routine is intended to be used for mapping device memory,
* NOT real memory.
*/
-void *
-pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode)
+static void *
+pmap_mapdev_internal(vm_paddr_t pa, vm_size_t size, int mode, bool noflush)
{
struct pmap_preinit_mapping *ppim;
vm_offset_t va, offset;
@@ -6878,7 +6879,10 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mo
*/
if (pa < dmaplimit && pa + size <= dmaplimit) {
va = PHYS_TO_DMAP(pa);
- if (!pmap_change_attr(va, size, mode))
+ PMAP_LOCK(kernel_pmap);
+ i = pmap_change_attr_locked(va, size, mode, noflush);
+ PMAP_UNLOCK(kernel_pmap);
+ if (!i)
return ((void *)(va + offset));
}
va = kva_alloc(size);
@@ -6888,22 +6892,37 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mo
for (tmpsize = 0; tmpsize < size; tmpsize += PAGE_SIZE)
pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
- pmap_invalidate_cache_range(va, va + tmpsize, FALSE);
+ if (!noflush)
+ pmap_invalidate_cache_range(va, va + tmpsize, FALSE);
return ((void *)(va + offset));
}
void *
+pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode)
+{
+
+ return (pmap_mapdev_internal(pa, size, mode, false));
+}
+
+void *
pmap_mapdev(vm_paddr_t pa, vm_size_t size)
{
- return (pmap_mapdev_attr(pa, size, PAT_UNCACHEABLE));
+ return (pmap_mapdev_internal(pa, size, PAT_UNCACHEABLE, false));
}
void *
+pmap_mapdev_pciecfg(vm_paddr_t pa, vm_size_t size)
+{
+
+ return (pmap_mapdev_internal(pa, size, PAT_UNCACHEABLE, true));
+}
+
+void *
pmap_mapbios(vm_paddr_t pa, vm_size_t size)
{
- return (pmap_mapdev_attr(pa, size, PAT_WRITE_BACK));
+ return (pmap_mapdev_internal(pa, size, PAT_WRITE_BACK, false));
}
void
@@ -7042,13 +7061,13 @@ pmap_change_attr(vm_offset_t va, vm_size_t size, int m
int error;
PMAP_LOCK(kernel_pmap);
- error = pmap_change_attr_locked(va, size, mode);
+ error = pmap_change_attr_locked(va, size, mode, false);
PMAP_UNLOCK(kernel_pmap);
return (error);
}
static int
-pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
+pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode, bool noflush)
{
vm_offset_t base, offset, tmpva;
vm_paddr_t pa_start, pa_end, pa_end1;
@@ -7165,7 +7184,7 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size
/* Run ended, update direct map. */
error = pmap_change_attr_locked(
PHYS_TO_DMAP(pa_start),
- pa_end - pa_start, mode);
+ pa_end - pa_start, mode, noflush);
if (error != 0)
break;
/* Start physical address run. */
@@ -7195,7 +7214,7 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size
/* Run ended, update direct map. */
error = pmap_change_attr_locked(
PHYS_TO_DMAP(pa_start),
- pa_end - pa_start, mode);
+ pa_end - pa_start, mode, noflush);
if (error != 0)
break;
/* Start physical address run. */
@@ -7223,7 +7242,7 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size
/* Run ended, update direct map. */
error = pmap_change_attr_locked(
PHYS_TO_DMAP(pa_start),
- pa_end - pa_start, mode);
+ pa_end - pa_start, mode, noflush);
if (error != 0)
break;
/* Start physical address run. */
@@ -7238,7 +7257,7 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size
pa_end1 = MIN(pa_end, dmaplimit);
if (pa_start != pa_end1)
error = pmap_change_attr_locked(PHYS_TO_DMAP(pa_start),
- pa_end1 - pa_start, mode);
+ pa_end1 - pa_start, mode, noflush);
}
/*
@@ -7247,7 +7266,8 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size
*/
if (changed) {
pmap_invalidate_range(kernel_pmap, base, tmpva);
- pmap_invalidate_cache_range(base, tmpva, FALSE);
+ if (!noflush)
+ pmap_invalidate_cache_range(base, tmpva, FALSE);
}
return (error);
}
Modified: stable/11/sys/amd64/include/pmap.h
==============================================================================
--- stable/11/sys/amd64/include/pmap.h Fri Aug 23 21:05:37 2019 (r351438)
+++ stable/11/sys/amd64/include/pmap.h Fri Aug 23 22:03:50 2019 (r351439)
@@ -419,6 +419,7 @@ void pmap_kremove(vm_offset_t);
void *pmap_mapbios(vm_paddr_t, vm_size_t);
void *pmap_mapdev(vm_paddr_t, vm_size_t);
void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, int);
+void *pmap_mapdev_pciecfg(vm_paddr_t pa, vm_size_t size);
boolean_t pmap_page_is_mapped(vm_page_t m);
void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma);
void pmap_pinit_pml4(vm_page_t);
Modified: stable/11/sys/amd64/pci/pci_cfgreg.c
==============================================================================
--- stable/11/sys/amd64/pci/pci_cfgreg.c Fri Aug 23 21:05:37 2019 (r351438)
+++ stable/11/sys/amd64/pci/pci_cfgreg.c Fri Aug 23 22:03:50 2019 (r351439)
@@ -269,7 +269,7 @@ pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t
base);
/* XXX: We should make sure this really fits into the direct map. */
- pcie_base = (vm_offset_t)pmap_mapdev(base, (maxbus + 1) << 20);
+ pcie_base = (vm_offset_t)pmap_mapdev_pciecfg(base, (maxbus + 1) << 20);
pcie_minbus = minbus;
pcie_maxbus = maxbus;
cfgmech = CFGMECH_PCIE;
More information about the svn-src-all
mailing list