Index: sys/vm/vm_phys.c =================================================================== --- sys/vm/vm_phys.c +++ sys/vm/vm_phys.c @@ -1131,7 +1131,6 @@ { struct vm_freelist *fl; struct vm_phys_seg *seg; - vm_paddr_t pa; vm_page_t m_buddy; KASSERT(m->order == VM_NFREEORDER, @@ -1145,22 +1144,22 @@ seg = &vm_phys_segs[m->segind]; vm_domain_free_assert_locked(VM_DOMAIN(seg->domain)); if (order < VM_NFREEORDER - 1) { - pa = VM_PAGE_TO_PHYS(m); - do { - pa ^= ((vm_paddr_t)1 << (PAGE_SHIFT + order)); - if (pa < seg->start || pa >= seg->end) - break; + vm_paddr_t pa = VM_PAGE_TO_PHYS(m); + int ord_cap; + for (ord_cap = min(VM_NFREEORDER - 1, + fls(atop(MIN(pa & -seg->start, ~pa & seg->end))) - 1); + order < ord_cap; order++) { + pa ^= (vm_paddr_t)1 << (PAGE_SHIFT + order); m_buddy = &seg->first_page[atop(pa - seg->start)]; if (m_buddy->order != order) break; - fl = (*seg->free_queues)[m_buddy->pool]; - vm_freelist_rem(fl, m_buddy, order); + pa &= ~((vm_paddr_t)1 << (PAGE_SHIFT + order)); if (m_buddy->pool != m->pool) vm_phys_set_pool(m->pool, m_buddy, order); - order++; - pa &= ~(((vm_paddr_t)1 << (PAGE_SHIFT + order)) - 1); + fl = (*seg->free_queues)[m_buddy->pool]; + vm_freelist_rem(fl, m_buddy, order); m = &seg->first_page[atop(pa - seg->start)]; - } while (order < VM_NFREEORDER - 1); + } } fl = (*seg->free_queues)[m->pool]; vm_freelist_add(fl, m, order, 1);