Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_map.c
Show First 20 Lines • Show All 2,448 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
vm_map_protect(vm_map_t map, vm_offset_t start, vm_offset_t end, | vm_map_protect(vm_map_t map, vm_offset_t start, vm_offset_t end, | ||||
vm_prot_t new_prot, boolean_t set_max) | vm_prot_t new_prot, boolean_t set_max) | ||||
{ | { | ||||
vm_map_entry_t current, entry, in_tran; | vm_map_entry_t current, entry, in_tran; | ||||
vm_object_t obj; | vm_object_t obj; | ||||
struct ucred *cred; | struct ucred *cred; | ||||
vm_prot_t old_prot; | vm_prot_t old_prot; | ||||
int rv; | |||||
if (start == end) | if (start == end) | ||||
return (KERN_SUCCESS); | return (KERN_SUCCESS); | ||||
again: | again: | ||||
in_tran = NULL; | in_tran = NULL; | ||||
vm_map_lock(map); | vm_map_lock(map); | ||||
Show All 38 Lines | again: | ||||
*/ | */ | ||||
if (in_tran != NULL) { | if (in_tran != NULL) { | ||||
in_tran->eflags |= MAP_ENTRY_NEEDS_WAKEUP; | in_tran->eflags |= MAP_ENTRY_NEEDS_WAKEUP; | ||||
vm_map_unlock_and_wait(map, 0); | vm_map_unlock_and_wait(map, 0); | ||||
goto again; | goto again; | ||||
} | } | ||||
/* | /* | ||||
* Do an accounting pass for private read-only mappings that | * Before changing the protections, try to reserve swap space for any | ||||
* now will do cow due to allowed write (e.g. debugger sets | * private (i.e., copy-on-write) mappings that are transitioning from | ||||
* breakpoint on text segment) | * read-only to read/write access. If a reservation fails, break out | ||||
* of this loop early and let the next loop simplify the entries, since | |||||
* some may now be mergeable. | |||||
*/ | */ | ||||
rv = KERN_SUCCESS; | |||||
vm_map_clip_start(map, entry, start); | vm_map_clip_start(map, entry, start); | ||||
for (current = entry; current->start < end; current = current->next) { | for (current = entry; current->start < end; current = current->next) { | ||||
vm_map_clip_end(map, current, end); | vm_map_clip_end(map, current, end); | ||||
if (set_max || | if (set_max || | ||||
((new_prot & ~(current->protection)) & VM_PROT_WRITE) == 0 || | ((new_prot & ~(current->protection)) & VM_PROT_WRITE) == 0 || | ||||
ENTRY_CHARGED(current) || | ENTRY_CHARGED(current) || | ||||
(current->eflags & MAP_ENTRY_GUARD) != 0) { | (current->eflags & MAP_ENTRY_GUARD) != 0) { | ||||
continue; | continue; | ||||
} | } | ||||
cred = curthread->td_ucred; | cred = curthread->td_ucred; | ||||
obj = current->object.vm_object; | obj = current->object.vm_object; | ||||
if (obj == NULL || (current->eflags & MAP_ENTRY_NEEDS_COPY)) { | if (obj == NULL || (current->eflags & MAP_ENTRY_NEEDS_COPY)) { | ||||
if (!swap_reserve(current->end - current->start)) { | if (!swap_reserve(current->end - current->start)) { | ||||
vm_map_unlock(map); | rv = KERN_RESOURCE_SHORTAGE; | ||||
return (KERN_RESOURCE_SHORTAGE); | end = current->end; | ||||
break; | |||||
} | } | ||||
crhold(cred); | crhold(cred); | ||||
current->cred = cred; | current->cred = cred; | ||||
continue; | continue; | ||||
} | } | ||||
VM_OBJECT_WLOCK(obj); | VM_OBJECT_WLOCK(obj); | ||||
if (obj->type != OBJT_DEFAULT && obj->type != OBJT_SWAP) { | if (obj->type != OBJT_DEFAULT && obj->type != OBJT_SWAP) { | ||||
VM_OBJECT_WUNLOCK(obj); | VM_OBJECT_WUNLOCK(obj); | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* Charge for the whole object allocation now, since | * Charge for the whole object allocation now, since | ||||
* we cannot distinguish between non-charged and | * we cannot distinguish between non-charged and | ||||
* charged clipped mapping of the same object later. | * charged clipped mapping of the same object later. | ||||
*/ | */ | ||||
KASSERT(obj->charge == 0, | KASSERT(obj->charge == 0, | ||||
("vm_map_protect: object %p overcharged (entry %p)", | ("vm_map_protect: object %p overcharged (entry %p)", | ||||
obj, current)); | obj, current)); | ||||
if (!swap_reserve(ptoa(obj->size))) { | if (!swap_reserve(ptoa(obj->size))) { | ||||
VM_OBJECT_WUNLOCK(obj); | VM_OBJECT_WUNLOCK(obj); | ||||
vm_map_unlock(map); | rv = KERN_RESOURCE_SHORTAGE; | ||||
return (KERN_RESOURCE_SHORTAGE); | end = current->end; | ||||
break; | |||||
} | } | ||||
crhold(cred); | crhold(cred); | ||||
obj->cred = cred; | obj->cred = cred; | ||||
obj->charge = ptoa(obj->size); | obj->charge = ptoa(obj->size); | ||||
VM_OBJECT_WUNLOCK(obj); | VM_OBJECT_WUNLOCK(obj); | ||||
} | } | ||||
/* | /* | ||||
* Go back and fix up protections. [Note that clipping is not | * If enough swap space was available, go back and fix up protections. | ||||
* necessary the second time.] | * Otherwise, just simplify entries, since some may have been modified. | ||||
* [Note that clipping is not necessary the second time.] | |||||
*/ | */ | ||||
for (current = entry; current->start < end; current = current->next) { | for (current = entry; current->start < end; | ||||
if ((current->eflags & MAP_ENTRY_GUARD) != 0) | vm_map_simplify_entry(map, current), current = current->next) { | ||||
if (rv != KERN_SUCCESS || | |||||
(current->eflags & MAP_ENTRY_GUARD) != 0) | |||||
continue; | continue; | ||||
old_prot = current->protection; | old_prot = current->protection; | ||||
if (set_max) | if (set_max) | ||||
current->protection = | current->protection = | ||||
(current->max_protection = new_prot) & | (current->max_protection = new_prot) & | ||||
old_prot; | old_prot; | ||||
Show All 18 Lines | for (current = entry; current->start < end; | ||||
if ((old_prot & ~current->protection) != 0) { | if ((old_prot & ~current->protection) != 0) { | ||||
#define MASK(entry) (((entry)->eflags & MAP_ENTRY_COW) ? ~VM_PROT_WRITE : \ | #define MASK(entry) (((entry)->eflags & MAP_ENTRY_COW) ? ~VM_PROT_WRITE : \ | ||||
VM_PROT_ALL) | VM_PROT_ALL) | ||||
pmap_protect(map->pmap, current->start, | pmap_protect(map->pmap, current->start, | ||||
current->end, | current->end, | ||||
current->protection & MASK(current)); | current->protection & MASK(current)); | ||||
#undef MASK | #undef MASK | ||||
} | } | ||||
vm_map_simplify_entry(map, current); | |||||
} | } | ||||
vm_map_unlock(map); | vm_map_unlock(map); | ||||
return (KERN_SUCCESS); | return (rv); | ||||
} | } | ||||
/* | /* | ||||
* vm_map_madvise: | * vm_map_madvise: | ||||
* | * | ||||
* This routine traverses a processes map handling the madvise | * This routine traverses a processes map handling the madvise | ||||
* system call. Advisories are classified as either those effecting | * system call. Advisories are classified as either those effecting | ||||
* the vm_map_entry structure, or those effecting the underlying | * the vm_map_entry structure, or those effecting the underlying | ||||
▲ Show 20 Lines • Show All 2,296 Lines • Show Last 20 Lines |