| 805 | } |
| 806 | |
| 807 | int |
| 808 | kern_mincore(struct thread *td, uintptr_t addr0, size_t len, char *vec) |
| 809 | { |
| 810 | pmap_t pmap; |
| 811 | vm_map_t map; |
| 812 | vm_map_entry_t current, entry; |
| 813 | vm_object_t object; |
| 814 | vm_offset_t addr, cend, end, first_addr; |
| 815 | vm_paddr_t pa; |
| 816 | vm_page_t m; |
| 817 | vm_pindex_t pindex; |
| 818 | int error, lastvecindex, mincoreinfo, vecindex; |
| 819 | unsigned int timestamp; |
| 820 | |
| 821 | /* |
| 822 | * Make sure that the addresses presented are valid for user |
| 823 | * mode. |
| 824 | */ |
| 825 | first_addr = addr = trunc_page(addr0); |
| 826 | end = round_page(addr0 + len); |
| 827 | map = &td->td_proc->p_vmspace->vm_map; |
| 828 | if (end > vm_map_max(map) || end < addr) |
| 829 | return (ENOMEM); |
| 830 | |
| 831 | pmap = vmspace_pmap(td->td_proc->p_vmspace); |
| 832 | |
| 833 | vm_map_lock_read(map); |
| 834 | RestartScan: |
| 835 | timestamp = map->timestamp; |
| 836 | |
| 837 | if (!vm_map_lookup_entry(map, addr, &entry)) { |
| 838 | vm_map_unlock_read(map); |
| 839 | return (ENOMEM); |
| 840 | } |
| 841 | |
| 842 | /* |
| 843 | * Do this on a map entry basis so that if the pages are not |
| 844 | * in the current processes address space, we can easily look |
| 845 | * up the pages elsewhere. |
| 846 | */ |
| 847 | lastvecindex = -1; |
| 848 | while (entry->start < end) { |
| 849 | /* |
| 850 | * check for contiguity |
| 851 | */ |
| 852 | current = entry; |
| 853 | entry = vm_map_entry_succ(current); |
| 854 | if (current->end < end && |
| 855 | entry->start > current->end) { |
| 856 | vm_map_unlock_read(map); |
| 857 | return (ENOMEM); |
| 858 | } |
| 859 | |
| 860 | /* |
| 861 | * ignore submaps (for now) or null objects |
| 862 | */ |
| 863 | if ((current->eflags & MAP_ENTRY_IS_SUB_MAP) || |
| 864 | current->object.vm_object == NULL) |
no test coverage detected