| 2197 | |
| 2198 | #ifdef NUMA |
| 2199 | static void |
| 2200 | pmap_init_pv_table(void) |
| 2201 | { |
| 2202 | struct pmap_large_md_page *pvd; |
| 2203 | vm_size_t s; |
| 2204 | long start, end, highest, pv_npg; |
| 2205 | int domain, i, j, pages; |
| 2206 | |
| 2207 | /* |
| 2208 | * We strongly depend on the size being a power of two, so the assert |
| 2209 | * is overzealous. However, should the struct be resized to a |
| 2210 | * different power of two, the code below needs to be revisited. |
| 2211 | */ |
| 2212 | CTASSERT((sizeof(*pvd) == 64)); |
| 2213 | |
| 2214 | /* |
| 2215 | * Calculate the size of the array. |
| 2216 | */ |
| 2217 | pmap_last_pa = vm_phys_segs[vm_phys_nsegs - 1].end; |
| 2218 | pv_npg = howmany(pmap_last_pa, NBPDR); |
| 2219 | s = (vm_size_t)pv_npg * sizeof(struct pmap_large_md_page); |
| 2220 | s = round_page(s); |
| 2221 | pv_table = (struct pmap_large_md_page *)kva_alloc(s); |
| 2222 | if (pv_table == NULL) |
| 2223 | panic("%s: kva_alloc failed\n", __func__); |
| 2224 | |
| 2225 | /* |
| 2226 | * Iterate physical segments to allocate space for respective pages. |
| 2227 | */ |
| 2228 | highest = -1; |
| 2229 | s = 0; |
| 2230 | for (i = 0; i < vm_phys_nsegs; i++) { |
| 2231 | end = vm_phys_segs[i].end / NBPDR; |
| 2232 | domain = vm_phys_segs[i].domain; |
| 2233 | |
| 2234 | if (highest >= end) |
| 2235 | continue; |
| 2236 | |
| 2237 | start = highest + 1; |
| 2238 | pvd = &pv_table[start]; |
| 2239 | |
| 2240 | pages = end - start + 1; |
| 2241 | s = round_page(pages * sizeof(*pvd)); |
| 2242 | highest = start + (s / sizeof(*pvd)) - 1; |
| 2243 | |
| 2244 | for (j = 0; j < s; j += PAGE_SIZE) { |
| 2245 | vm_page_t m = vm_page_alloc_domain(NULL, 0, |
| 2246 | domain, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ); |
| 2247 | if (m == NULL) |
| 2248 | panic("vm_page_alloc_domain failed for %lx\n", (vm_offset_t)pvd + j); |
| 2249 | pmap_qenter((vm_offset_t)pvd + j, &m, 1); |
| 2250 | } |
| 2251 | |
| 2252 | for (j = 0; j < s / sizeof(*pvd); j++) { |
| 2253 | rw_init_flags(&pvd->pv_lock, "pmap pv list", RW_NEW); |
| 2254 | TAILQ_INIT(&pvd->pv_page.pv_list); |
| 2255 | pvd->pv_page.pv_gen = 0; |
| 2256 | pvd->pv_page.pat_mode = 0; |
no test coverage detected