Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_mmap.c
Show First 20 Lines • Show All 213 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
kern_mmap_req(struct thread *td, const struct mmap_req *mrp) | kern_mmap_req(struct thread *td, const struct mmap_req *mrp) | ||||
{ | { | ||||
struct vmspace *vms; | struct vmspace *vms; | ||||
struct file *fp; | struct file *fp; | ||||
struct proc *p; | struct proc *p; | ||||
off_t pos; | off_t pos; | ||||
vm_offset_t addr; | vm_offset_t addr, orig_addr; | ||||
vm_size_t len, pageoff, size; | vm_size_t len, pageoff, size; | ||||
vm_prot_t cap_maxprot; | vm_prot_t cap_maxprot; | ||||
int align, error, fd, flags, max_prot, prot; | int align, error, fd, flags, max_prot, prot; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
mmap_check_fp_fn check_fp_fn; | mmap_check_fp_fn check_fp_fn; | ||||
addr = mrp->mr_hint; | orig_addr = addr = mrp->mr_hint; | ||||
len = mrp->mr_len; | len = mrp->mr_len; | ||||
prot = mrp->mr_prot; | prot = mrp->mr_prot; | ||||
flags = mrp->mr_flags; | flags = mrp->mr_flags; | ||||
fd = mrp->mr_fd; | fd = mrp->mr_fd; | ||||
pos = mrp->mr_pos; | pos = mrp->mr_pos; | ||||
check_fp_fn = mrp->mr_check_fp_fn; | check_fp_fn = mrp->mr_check_fp_fn; | ||||
if ((prot & ~(_PROT_ALL | PROT_MAX(_PROT_ALL))) != 0) | if ((prot & ~(_PROT_ALL | PROT_MAX(_PROT_ALL))) != 0) | ||||
▲ Show 20 Lines • Show All 179 Lines • ▼ Show 20 Lines | if ((flags & (MAP_SHARED | MAP_PRIVATE)) == 0 && | ||||
goto done; | goto done; | ||||
} | } | ||||
if (check_fp_fn != NULL) { | if (check_fp_fn != NULL) { | ||||
error = check_fp_fn(fp, prot, max_prot & cap_maxprot, | error = check_fp_fn(fp, prot, max_prot & cap_maxprot, | ||||
flags); | flags); | ||||
if (error != 0) | if (error != 0) | ||||
goto done; | goto done; | ||||
} | } | ||||
if (fp->f_ops == &shm_ops && shm_largepage(fp->f_data)) | |||||
kevans: No specific suggestion, but it'd be nice if we had a cleaner way to do this, though I suppose… | |||||
Done Inline ActionsI am not sure if the way I redid it is cleaner, but now I do not see a specific need for shm_ops_large. kib: I am not sure if the way I redid it is cleaner, but now I do not see a specific need for… | |||||
addr = orig_addr; | |||||
/* This relies on VM_PROT_* matching PROT_*. */ | /* This relies on VM_PROT_* matching PROT_*. */ | ||||
Done Inline ActionsThe check does not work properly in some cases because shm_flags gets clobbered on every open() as I pointed out before. So either SHM_LARGEPAGE needs to be preserved in kern_shm_open2() or some other method of identifying largepage objects is needed. markj: The check does not work properly in some cases because shm_flags gets clobbered on every open()… | |||||
error = fo_mmap(fp, &vms->vm_map, &addr, size, prot, | error = fo_mmap(fp, &vms->vm_map, &addr, size, prot, | ||||
max_prot & cap_maxprot, flags, pos, td); | max_prot & cap_maxprot, flags, pos, td); | ||||
} | } | ||||
if (error == 0) | if (error == 0) | ||||
td->td_retval[0] = (register_t) (addr + pageoff); | td->td_retval[0] = (register_t) (addr + pageoff); | ||||
done: | done: | ||||
if (fp) | if (fp) | ||||
▲ Show 20 Lines • Show All 138 Lines • ▼ Show 20 Lines | |||||
#ifdef HWPMC_HOOKS | #ifdef HWPMC_HOOKS | ||||
struct pmckern_map_out pkm; | struct pmckern_map_out pkm; | ||||
vm_map_entry_t entry; | vm_map_entry_t entry; | ||||
bool pmc_handled; | bool pmc_handled; | ||||
#endif | #endif | ||||
vm_offset_t addr, end; | vm_offset_t addr, end; | ||||
vm_size_t pageoff; | vm_size_t pageoff; | ||||
vm_map_t map; | vm_map_t map; | ||||
int rv; | |||||
if (size == 0) | if (size == 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
addr = addr0; | addr = addr0; | ||||
pageoff = (addr & PAGE_MASK); | pageoff = (addr & PAGE_MASK); | ||||
addr -= pageoff; | addr -= pageoff; | ||||
size += pageoff; | size += pageoff; | ||||
Show All 21 Lines | if (vm_map_lookup_entry(map, addr, &entry)) { | ||||
pkm.pm_address = (uintptr_t) addr; | pkm.pm_address = (uintptr_t) addr; | ||||
pkm.pm_size = (size_t) size; | pkm.pm_size = (size_t) size; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
vm_map_delete(map, addr, end); | rv = vm_map_delete(map, addr, end); | ||||
Done Inline Actionsvm_map_delete() can fail now, but the error is not propagating to userland. markj: vm_map_delete() can fail now, but the error is not propagating to userland. | |||||
#ifdef HWPMC_HOOKS | #ifdef HWPMC_HOOKS | ||||
if (__predict_false(pmc_handled)) { | if (rv == KERN_SUCCESS && __predict_false(pmc_handled)) { | ||||
/* downgrade the lock to prevent a LOR with the pmc-sx lock */ | /* downgrade the lock to prevent a LOR with the pmc-sx lock */ | ||||
vm_map_lock_downgrade(map); | vm_map_lock_downgrade(map); | ||||
if (pkm.pm_address != (uintptr_t) NULL) | if (pkm.pm_address != (uintptr_t) NULL) | ||||
PMC_CALL_HOOK(td, PMC_FN_MUNMAP, (void *) &pkm); | PMC_CALL_HOOK(td, PMC_FN_MUNMAP, (void *) &pkm); | ||||
vm_map_unlock_read(map); | vm_map_unlock_read(map); | ||||
} else | } else | ||||
#endif | #endif | ||||
vm_map_unlock(map); | vm_map_unlock(map); | ||||
/* vm_map_delete returns nothing but KERN_SUCCESS anyway */ | return (vm_mmap_to_errno(rv)); | ||||
return (0); | |||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct mprotect_args { | struct mprotect_args { | ||||
const void *addr; | const void *addr; | ||||
size_t len; | size_t len; | ||||
int prot; | int prot; | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 459 Lines • ▼ Show 20 Lines | |||||
#ifdef RACCT | #ifdef RACCT | ||||
if (racct_enable && error != KERN_SUCCESS) { | if (racct_enable && error != KERN_SUCCESS) { | ||||
PROC_LOCK(proc); | PROC_LOCK(proc); | ||||
racct_set(proc, RACCT_MEMLOCK, | racct_set(proc, RACCT_MEMLOCK, | ||||
ptoa(pmap_wired_count(map->pmap))); | ptoa(pmap_wired_count(map->pmap))); | ||||
PROC_UNLOCK(proc); | PROC_UNLOCK(proc); | ||||
} | } | ||||
#endif | #endif | ||||
return (error == KERN_SUCCESS ? 0 : ENOMEM); | switch (error) { | ||||
case KERN_SUCCESS: | |||||
return (0); | |||||
case KERN_INVALID_ARGUMENT: | |||||
return (EINVAL); | |||||
default: | |||||
return (ENOMEM); | |||||
} | |||||
Done Inline ActionsThis should become vm_mmap_to_errno() I think. Otherwise a clip error results in ENOMEM. markj: This should become vm_mmap_to_errno() I think. Otherwise a clip error results in ENOMEM. | |||||
Done Inline ActionsThen it would be EACCESS as well. I changed this to local switch. kib: Then it would be EACCESS as well. I changed this to local switch. | |||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct mlockall_args { | struct mlockall_args { | ||||
int how; | int how; | ||||
}; | }; | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 564 Lines • Show Last 20 Lines |
No specific suggestion, but it'd be nice if we had a cleaner way to do this, though I suppose this won't really expand to too many other file types. shmfd can now tell easily enough from some fo_* operation, for example, if it's configured for this since we've recently started recording the opening shm_flags.