The first part is to add "special" aligned free and inactive page lists apart from the normal free list. These lists contain pages who's physical address is aligned one of a power-of-2 boundaries: 16KB, 64KB, 256KB, 1MB, 4MB should be enough.
The second part is that when uvm_map maps a page from a map entry, it tries to allocate a physical page that conforms to va & (map_entry's alignment_mask). If this is the first page of the entry, it tries to allocate from off of the aligned page lists. If successful, simply use that page. If not, reset the alignment mask to 0.
When a page is other than the first page, see if the page at (first page pa + (new va - first page va)) , if there is a first, page, can be used and use it, if that fails, and this page's (va & alignment mask) == 0, act as if it's a first page.
Otherwise, if the page belonging to (va ^ PAGE_SIZE) and is mapped and (its pa ^ its va) & PAGE_SIZE == 0, try the physical page at (its pa ^ PAGE_SIZE).
Next, if the page is even, try the pa for the previous, or if odd, the pa for the next page...
Should at least in most instances give you contiguous runs of 2 pages, and hopefully more.