* kmem_back_domain: * * Allocate physical pages from the specified domain for the specified * virtual address range. */
| 451 | * virtual address range. |
| 452 | */ |
| 453 | int |
| 454 | kmem_back_domain(int domain, vm_object_t object, vm_offset_t addr, |
| 455 | vm_size_t size, int flags) |
| 456 | { |
| 457 | vm_offset_t offset, i; |
| 458 | vm_page_t m, mpred; |
| 459 | vm_prot_t prot; |
| 460 | int pflags; |
| 461 | |
| 462 | KASSERT(object == kernel_object, |
| 463 | ("kmem_back_domain: only supports kernel object.")); |
| 464 | |
| 465 | offset = addr - VM_MIN_KERNEL_ADDRESS; |
| 466 | pflags = malloc2vm_flags(flags) | VM_ALLOC_WIRED; |
| 467 | pflags &= ~(VM_ALLOC_NOWAIT | VM_ALLOC_WAITOK | VM_ALLOC_WAITFAIL); |
| 468 | if (flags & M_WAITOK) |
| 469 | pflags |= VM_ALLOC_WAITFAIL; |
| 470 | prot = (flags & M_EXEC) != 0 ? VM_PROT_ALL : VM_PROT_RW; |
| 471 | |
| 472 | i = 0; |
| 473 | VM_OBJECT_WLOCK(object); |
| 474 | retry: |
| 475 | mpred = vm_radix_lookup_le(&object->rtree, atop(offset + i)); |
| 476 | for (; i < size; i += PAGE_SIZE, mpred = m) { |
| 477 | m = vm_page_alloc_domain_after(object, atop(offset + i), |
| 478 | domain, pflags, mpred); |
| 479 | |
| 480 | /* |
| 481 | * Ran out of space, free everything up and return. Don't need |
| 482 | * to lock page queues here as we know that the pages we got |
| 483 | * aren't on any queues. |
| 484 | */ |
| 485 | if (m == NULL) { |
| 486 | if ((flags & M_NOWAIT) == 0) |
| 487 | goto retry; |
| 488 | VM_OBJECT_WUNLOCK(object); |
| 489 | kmem_unback(object, addr, i); |
| 490 | return (KERN_NO_SPACE); |
| 491 | } |
| 492 | KASSERT(vm_page_domain(m) == domain, |
| 493 | ("kmem_back_domain: Domain mismatch %d != %d", |
| 494 | vm_page_domain(m), domain)); |
| 495 | if (flags & M_ZERO && (m->flags & PG_ZERO) == 0) |
| 496 | pmap_zero_page(m); |
| 497 | KASSERT((m->oflags & VPO_UNMANAGED) != 0, |
| 498 | ("kmem_malloc: page %p is managed", m)); |
| 499 | vm_page_valid(m); |
| 500 | pmap_enter(kernel_pmap, addr + i, m, prot, |
| 501 | prot | PMAP_ENTER_WIRED, 0); |
| 502 | if (__predict_false((prot & VM_PROT_EXECUTE) != 0)) |
| 503 | m->oflags |= VPO_KMEM_EXEC; |
| 504 | } |
| 505 | VM_OBJECT_WUNLOCK(object); |
| 506 | |
| 507 | return (KERN_SUCCESS); |
| 508 | } |
| 509 | |
| 510 | /* |
no test coverage detected