* Routine: * vm_fault_copy_entry * Function: * Create new shadow object backing dst_entry with private copy of * all underlying pages. When src_entry is equal to dst_entry, * function implements COW for wired-down map entry. Otherwise, * it forks wired entry into dst_map. * * In/out conditions: * The source and destination maps must be locked for write. * The source map entry must
| 1882 | * entry corresponding to a main map entry that is wired down). |
| 1883 | */ |
| 1884 | void |
| 1885 | vm_fault_copy_entry(vm_map_t dst_map, vm_map_t src_map, |
| 1886 | vm_map_entry_t dst_entry, vm_map_entry_t src_entry, |
| 1887 | vm_ooffset_t *fork_charge) |
| 1888 | { |
| 1889 | vm_object_t backing_object, dst_object, object, src_object; |
| 1890 | vm_pindex_t dst_pindex, pindex, src_pindex; |
| 1891 | vm_prot_t access, prot; |
| 1892 | vm_offset_t vaddr; |
| 1893 | vm_page_t dst_m; |
| 1894 | vm_page_t src_m; |
| 1895 | boolean_t upgrade; |
| 1896 | |
| 1897 | #ifdef lint |
| 1898 | src_map++; |
| 1899 | #endif /* lint */ |
| 1900 | |
| 1901 | upgrade = src_entry == dst_entry; |
| 1902 | access = prot = dst_entry->protection; |
| 1903 | |
| 1904 | src_object = src_entry->object.vm_object; |
| 1905 | src_pindex = OFF_TO_IDX(src_entry->offset); |
| 1906 | |
| 1907 | if (upgrade && (dst_entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) { |
| 1908 | dst_object = src_object; |
| 1909 | vm_object_reference(dst_object); |
| 1910 | } else { |
| 1911 | /* |
| 1912 | * Create the top-level object for the destination entry. |
| 1913 | * Doesn't actually shadow anything - we copy the pages |
| 1914 | * directly. |
| 1915 | */ |
| 1916 | dst_object = vm_object_allocate_anon(atop(dst_entry->end - |
| 1917 | dst_entry->start), NULL, NULL, 0); |
| 1918 | #if VM_NRESERVLEVEL > 0 |
| 1919 | dst_object->flags |= OBJ_COLORED; |
| 1920 | dst_object->pg_color = atop(dst_entry->start); |
| 1921 | #endif |
| 1922 | dst_object->domain = src_object->domain; |
| 1923 | dst_object->charge = dst_entry->end - dst_entry->start; |
| 1924 | } |
| 1925 | |
| 1926 | VM_OBJECT_WLOCK(dst_object); |
| 1927 | KASSERT(upgrade || dst_entry->object.vm_object == NULL, |
| 1928 | ("vm_fault_copy_entry: vm_object not NULL")); |
| 1929 | if (src_object != dst_object) { |
| 1930 | dst_entry->object.vm_object = dst_object; |
| 1931 | dst_entry->offset = 0; |
| 1932 | dst_entry->eflags &= ~MAP_ENTRY_VN_EXEC; |
| 1933 | } |
| 1934 | if (fork_charge != NULL) { |
| 1935 | KASSERT(dst_entry->cred == NULL, |
| 1936 | ("vm_fault_copy_entry: leaked swp charge")); |
| 1937 | dst_object->cred = curthread->td_ucred; |
| 1938 | crhold(dst_object->cred); |
| 1939 | *fork_charge += dst_object->charge; |
| 1940 | } else if ((dst_object->type == OBJT_DEFAULT || |
| 1941 | dst_object->type == OBJT_SWAP) && |
no test coverage detected