* Free a contiguous, power of two-sized set of physical pages. * * The free page queues must be locked. */
| 1081 | * The free page queues must be locked. |
| 1082 | */ |
| 1083 | void |
| 1084 | vm_phys_free_pages(vm_page_t m, int order) |
| 1085 | { |
| 1086 | struct vm_freelist *fl; |
| 1087 | struct vm_phys_seg *seg; |
| 1088 | vm_paddr_t pa; |
| 1089 | vm_page_t m_buddy; |
| 1090 | |
| 1091 | KASSERT(m->order == VM_NFREEORDER, |
| 1092 | ("vm_phys_free_pages: page %p has unexpected order %d", |
| 1093 | m, m->order)); |
| 1094 | KASSERT(m->pool < VM_NFREEPOOL, |
| 1095 | ("vm_phys_free_pages: page %p has unexpected pool %d", |
| 1096 | m, m->pool)); |
| 1097 | KASSERT(order < VM_NFREEORDER, |
| 1098 | ("vm_phys_free_pages: order %d is out of range", order)); |
| 1099 | seg = &vm_phys_segs[m->segind]; |
| 1100 | vm_domain_free_assert_locked(VM_DOMAIN(seg->domain)); |
| 1101 | if (order < VM_NFREEORDER - 1) { |
| 1102 | pa = VM_PAGE_TO_PHYS(m); |
| 1103 | do { |
| 1104 | pa ^= ((vm_paddr_t)1 << (PAGE_SHIFT + order)); |
| 1105 | if (pa < seg->start || pa >= seg->end) |
| 1106 | break; |
| 1107 | m_buddy = &seg->first_page[atop(pa - seg->start)]; |
| 1108 | if (m_buddy->order != order) |
| 1109 | break; |
| 1110 | fl = (*seg->free_queues)[m_buddy->pool]; |
| 1111 | vm_freelist_rem(fl, m_buddy, order); |
| 1112 | if (m_buddy->pool != m->pool) |
| 1113 | vm_phys_set_pool(m->pool, m_buddy, order); |
| 1114 | order++; |
| 1115 | pa &= ~(((vm_paddr_t)1 << (PAGE_SHIFT + order)) - 1); |
| 1116 | m = &seg->first_page[atop(pa - seg->start)]; |
| 1117 | } while (order < VM_NFREEORDER - 1); |
| 1118 | } |
| 1119 | fl = (*seg->free_queues)[m->pool]; |
| 1120 | vm_freelist_add(fl, m, order, 1); |
| 1121 | } |
| 1122 | |
| 1123 | /* |
| 1124 | * Return the largest possible order of a set of pages starting at m. |
no test coverage detected