Add a new per-domain vmem arena whose import function allocates
aligned 2MB chunks of kernel memory. Introduce a new malloc flag,
M_STABLE, which indicates that the caller will not free the memory back
to the allocator. Handle M_STABLE in kmem_malloc() and
kmem_alloc_contig() by returning ranges from this arena. This ensures
that M_STABLE allocations are grouped together.
Pass M_STABLE when allocating slabs for a UMA_ZONE_NOFREE keg. Ensure
that we do not use the direct map for such slabs.
This helps minimize the fragmentation of physical memory caused by
_NOFREE objects, particularly VM object and thread structures. In the
past I have found that over time, slabs for these structures cover wide
ranges of memory, inhibiting superpage creation. For example, on my
desktop with ~2 days uptime, 25% of the 2MB chunks of RAM in the system
contain at least one VM object slab page. That's 4GB of RAM in which
every 2MB large page contains at least one _NOFREE slab, but the system
has less than 100MB worth of VM object slabs.
I wanted to call the flag M_NOFREE, but mbuf.h has already claimed this
name. I think this mechanism could be extended to support long-lived
allocations (like typical per-CPU structures) rather than strict _NOFREE
allocations, so "stable" seems like a reasonable name. Internally the
functions are suffixed with _nofree since that is more specific. I am
open to suggestions for different names.