--- a/sys/platform/pc64/x86_64/nexus.c +++ b/sys/platform/pc64/x86_64/nexus.c @@ -426,6 +426,17 @@ */ if (rman_get_bustag(r) == X86_64_BUS_SPACE_MEM) { caddr_t vaddr = 0; + int error; + + /* + * The mapping step must happen exactly once. pmap_mapdev() + * is not idempotent while rman_activate_resource() is: + * re-activating an already RF_ACTIVE resource must not + * create a second kernel_map range, or the first one is + * orphaned (permanent KVA leak + stale RW PTEs). + */ + if (rman_get_flags(r) & RF_ACTIVE) + return (rman_activate_resource(r)); if (rman_get_end(r) < 1024 * 1024) { /* @@ -446,6 +457,14 @@ rman_set_virtual(r, vaddr); /* IBM-PC: the type of bus_space_handle_t is u_int */ rman_set_bushandle(r, (bus_space_handle_t) vaddr); + error = rman_activate_resource(r); + if (error != 0 && rman_get_end(r) >= 1024 * 1024) { + /* roll back the mapping we just created */ + pmap_unmapdev((vm_offset_t)vaddr, + (vm_size_t)rman_get_size(r)); + rman_set_virtual(r, 0); + } + return (error); } return (rman_activate_resource(r)); }