| 569 | } |
| 570 | |
| 571 | int |
| 572 | kern_munmap(struct thread *td, uintptr_t addr0, size_t size) |
| 573 | { |
| 574 | #ifdef HWPMC_HOOKS |
| 575 | struct pmckern_map_out pkm; |
| 576 | vm_map_entry_t entry; |
| 577 | bool pmc_handled; |
| 578 | #endif |
| 579 | vm_offset_t addr, end; |
| 580 | vm_size_t pageoff; |
| 581 | vm_map_t map; |
| 582 | int rv; |
| 583 | |
| 584 | if (size == 0) |
| 585 | return (EINVAL); |
| 586 | |
| 587 | addr = addr0; |
| 588 | pageoff = (addr & PAGE_MASK); |
| 589 | addr -= pageoff; |
| 590 | size += pageoff; |
| 591 | size = (vm_size_t) round_page(size); |
| 592 | end = addr + size; |
| 593 | map = &td->td_proc->p_vmspace->vm_map; |
| 594 | if (!vm_map_range_valid(map, addr, end)) |
| 595 | return (EINVAL); |
| 596 | |
| 597 | vm_map_lock(map); |
| 598 | #ifdef HWPMC_HOOKS |
| 599 | pmc_handled = false; |
| 600 | if (PMC_HOOK_INSTALLED(PMC_FN_MUNMAP)) { |
| 601 | pmc_handled = true; |
| 602 | /* |
| 603 | * Inform hwpmc if the address range being unmapped contains |
| 604 | * an executable region. |
| 605 | */ |
| 606 | pkm.pm_address = (uintptr_t) NULL; |
| 607 | if (vm_map_lookup_entry(map, addr, &entry)) { |
| 608 | for (; entry->start < end; |
| 609 | entry = vm_map_entry_succ(entry)) { |
| 610 | if (vm_map_check_protection(map, entry->start, |
| 611 | entry->end, VM_PROT_EXECUTE) == TRUE) { |
| 612 | pkm.pm_address = (uintptr_t) addr; |
| 613 | pkm.pm_size = (size_t) size; |
| 614 | break; |
| 615 | } |
| 616 | } |
| 617 | } |
| 618 | } |
| 619 | #endif |
| 620 | rv = vm_map_delete(map, addr, end); |
| 621 | |
| 622 | #ifdef HWPMC_HOOKS |
| 623 | if (rv == KERN_SUCCESS && __predict_false(pmc_handled)) { |
| 624 | /* downgrade the lock to prevent a LOR with the pmc-sx lock */ |
| 625 | vm_map_lock_downgrade(map); |
| 626 | if (pkm.pm_address != (uintptr_t) NULL) |
| 627 | PMC_CALL_HOOK(td, PMC_FN_MUNMAP, (void *) &pkm); |
| 628 | vm_map_unlock_read(map); |
no test coverage detected