--- a/sys/platform/pc64/x86_64/nexus.c +++ b/sys/platform/pc64/x86_64/nexus.c @@ -374,8 +374,11 @@ switch (type) { case SYS_RES_IRQ: - KASSERT(cpuid >= 0 && cpuid < ncpus, - ("nexus invalid cpuid: %d", cpuid)); + if (cpuid < 0 || cpuid >= ncpus) { + kprintf("nexus_alloc_resource: invalid cpuid %d for " + "SYS_RES_IRQ allocation\n", cpuid); + return 0; + } rm = &irq_rman[cpuid]; break; @@ -426,6 +429,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 +460,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)); } @@ -564,8 +586,6 @@ struct resource_list_entry *rle; rle = resource_list_find(rl, type, rid); - device_printf(child, "type %d rid %d startp %p countp %p - got %p\n", - type, rid, startp, countp, rle); if (!rle) return(ENOENT); if (startp)