diff options
| author | Mitchell Horne <mhorne@FreeBSD.org> | 2026-05-14 14:20:22 +0000 |
|---|---|---|
| committer | Mitchell Horne <mhorne@FreeBSD.org> | 2026-05-14 14:25:09 +0000 |
| commit | 988c03980452a56fb0fbb15e18b0a644602d0ab3 (patch) | |
| tree | 9248a005b47820a259a9c3244454b6ddd7cd0fea | |
| parent | 4cdcacb9b2969b681b9547da61535b09e9e67478 (diff) | |
linux/io: handle memtype_wc mapping for !DMAP range
The amdgpu driver in drm-kmod will attempt to update/reserve certain GPU
VRAM ranges as write-combining. Depending on the system, this address
range may fall outside of FreeBSD's constructed DMAP. We cannot use
pmap_change_attr() in this case.
When INVARIANTS is enabled, this results in the following:
panic: physical address 0x880000000 not covered by the DMAP
Add a guard against triggering the KASSERT in PHYS_TO_DMAP().
This limitation in our implementation of arch_io_reserve_memtype_wc() is
already known in drm-kmod's amdgpu_bo_init(), and errors are ignored
there (see "BSDFIXME"). This change is only to eliminate the preventable
assertion failure within this scheme.
Tested by: kevans
Reviewed by: kib, emaste
MFC after: 3 days
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D56971
| -rw-r--r-- | sys/compat/linuxkpi/common/include/linux/io.h | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/io.h b/sys/compat/linuxkpi/common/include/linux/io.h index f89c150e7a3b..4dfc04b3f3fc 100644 --- a/sys/compat/linuxkpi/common/include/linux/io.h +++ b/sys/compat/linuxkpi/common/include/linux/io.h @@ -544,6 +544,9 @@ arch_io_reserve_memtype_wc(resource_size_t start, resource_size_t size) #if defined(__amd64__) void *va; + if (!PHYS_IN_DMAP(start) || !PHYS_IN_DMAP(start + size)) + return (-EINVAL); + va = PHYS_TO_DMAP(start); return (-pmap_change_attr(va, size, VM_MEMATTR_WRITE_COMBINING)); #else @@ -557,8 +560,10 @@ arch_io_free_memtype_wc(resource_size_t start, resource_size_t size) #if defined(__amd64__) void *va; - va = PHYS_TO_DMAP(start); + if (!PHYS_IN_DMAP(start) || !PHYS_IN_DMAP(start + size)) + return; + va = PHYS_TO_DMAP(start); pmap_change_attr(va, size, VM_MEMATTR_WRITE_BACK); #endif } |
