Index: head/sys/amd64/amd64/machdep.c =================================================================== --- head/sys/amd64/amd64/machdep.c +++ head/sys/amd64/amd64/machdep.c @@ -101,6 +101,7 @@ #include #include #include +#include #ifdef DDB #ifndef KDB @@ -1226,6 +1227,12 @@ pt_entry_t *pte; quad_t dcons_addr, dcons_size; int page_counter; + + /* + * Tell the physical memory allocator about pages used to store + * the kernel and preloaded data. See kmem_bootstrap_free(). + */ + vm_phys_add_seg((vm_paddr_t)kernphys, trunc_page(first)); bzero(physmap, sizeof(physmap)); physmap_idx = 0; Index: head/sys/i386/i386/machdep.c =================================================================== --- head/sys/i386/i386/machdep.c +++ head/sys/i386/i386/machdep.c @@ -101,6 +101,7 @@ #include #include #include +#include #ifdef DDB #ifndef KDB @@ -1832,6 +1833,12 @@ bzero(&vmf, sizeof(vmf)); bzero(physmap, sizeof(physmap)); basemem = 0; + + /* + * Tell the physical memory allocator about pages used to store + * the kernel and preloaded data. See kmem_bootstrap_free(). + */ + vm_phys_add_seg((vm_paddr_t)KERNLOAD, trunc_page(first)); /* * Check if the loader supplied an SMAP memory map. If so, Index: head/sys/kern/subr_module.c =================================================================== --- head/sys/kern/subr_module.c +++ head/sys/kern/subr_module.c @@ -33,6 +33,9 @@ #include #include +#include +#include + /* * Preloaded module support */ @@ -204,29 +207,42 @@ void preload_delete_name(const char *name) { - caddr_t curp; - uint32_t *hdr; + caddr_t addr, curp; + uint32_t *hdr, sz; int next; int clearing; + + addr = 0; + sz = 0; if (preload_metadata != NULL) { - + clearing = 0; curp = preload_metadata; for (;;) { hdr = (uint32_t *)curp; - if (hdr[0] == 0 && hdr[1] == 0) - break; + if (hdr[0] == MODINFO_NAME || (hdr[0] == 0 && hdr[1] == 0)) { + /* Free memory used to store the file. */ + if (addr != 0 && sz != 0) + kmem_bootstrap_free((vm_offset_t)addr, sz); + addr = 0; + sz = 0; - /* Search for a MODINFO_NAME field */ - if (hdr[0] == MODINFO_NAME) { + if (hdr[0] == 0) + break; if (!strcmp(name, curp + sizeof(uint32_t) * 2)) clearing = 1; /* got it, start clearing */ - else if (clearing) + else if (clearing) { clearing = 0; /* at next one now.. better stop */ + } } - if (clearing) + if (clearing) { + if (hdr[0] == MODINFO_ADDR) + addr = *(caddr_t *)(curp + sizeof(uint32_t) * 2); + else if (hdr[0] == MODINFO_SIZE) + sz = *(uint32_t *)(curp + sizeof(uint32_t) * 2); hdr[0] = MODINFO_EMPTY; + } /* skip to next field */ next = sizeof(uint32_t) * 2 + hdr[1]; Index: head/sys/vm/vm_extern.h =================================================================== --- head/sys/vm/vm_extern.h +++ head/sys/vm/vm_extern.h @@ -75,6 +75,7 @@ void kmem_unback(vm_object_t, vm_offset_t, vm_size_t); /* Bootstrapping. */ +void kmem_bootstrap_free(vm_offset_t, vm_size_t); vm_map_t kmem_suballoc(vm_map_t, vm_offset_t *, vm_offset_t *, vm_size_t, boolean_t); void kmem_init(vm_offset_t, vm_offset_t); Index: head/sys/vm/vm_kern.c =================================================================== --- head/sys/vm/vm_kern.c +++ head/sys/vm/vm_kern.c @@ -688,6 +688,38 @@ vm_map_unlock(m); } +/* + * kmem_bootstrap_free: + * + * Free pages backing preloaded data (e.g., kernel modules) to the + * system. Currently only supported on platforms that create a + * vm_phys segment for preloaded data. + */ +void +kmem_bootstrap_free(vm_offset_t start, vm_size_t size) +{ +#if defined(__i386__) || defined(__amd64__) + struct vm_domain *vmd; + vm_offset_t end; + vm_paddr_t pa; + vm_page_t m; + + end = trunc_page(start + size); + start = round_page(start); + + (void)vm_map_remove(kernel_map, start, end); + for (; start < end; start += PAGE_SIZE) { + pa = pmap_kextract(start); + m = PHYS_TO_VM_PAGE(pa); + + vmd = vm_pagequeue_domain(m); + vm_domain_free_lock(vmd); + vm_phys_free_pages(m, 0); + vm_domain_free_unlock(vmd); + } +#endif +} + #ifdef DIAGNOSTIC /* * Allow userspace to directly trigger the VM drain routine for testing