Index: sys/vm/vm_phys.c =================================================================== --- sys/vm/vm_phys.c +++ sys/vm/vm_phys.c @@ -1293,7 +1293,7 @@ { struct vm_freelist *fl; struct vm_phys_seg *seg; - vm_paddr_t pa, pa_half; + vm_paddr_t pa, pa_half, pa_low; vm_page_t m_set, m_tmp; int order; @@ -1304,15 +1304,18 @@ */ seg = &vm_phys_segs[m->segind]; vm_domain_free_assert_locked(VM_DOMAIN(seg->domain)); - for (m_set = m, order = 0; m_set->order == VM_NFREEORDER && - order < VM_NFREEORDER - 1; ) { - order++; - pa = m->phys_addr & (~(vm_paddr_t)0 << (PAGE_SHIFT + order)); - if (pa >= seg->start) - m_set = &seg->first_page[atop(pa - seg->start)]; - else - return (false); + pa = VM_PAGE_TO_PHYS(m); + pa_low = pa &- ptoa(1 << VM_NFREEORDER); + if (pa_low < seg->start) + pa_low = seg->start; + order = 0; + for (m_set = m; pa > pa_low && m_set->order == VM_NFREEORDER; + m_set = &seg->first_page[atop(pa - seg->start)]) { + order = ffsll(atop(pa)); + pa &= pa - 1; } + if (pa < seg->start) + return (false); if (m_set->order < order) return (false); if (m_set->order == VM_NFREEORDER) @@ -1332,8 +1335,8 @@ vm_freelist_rem(fl, m_set, order); while (order > 0) { order--; - pa_half = m_set->phys_addr ^ (1 << (PAGE_SHIFT + order)); - if (m->phys_addr < pa_half) + pa_half = VM_PAGE_TO_PHYS(m_set) ^ ptoa(1 << order); + if (VM_PAGE_TO_PHYS(m) < pa_half) m_tmp = &seg->first_page[atop(pa_half - seg->start)]; else { m_tmp = m_set;