version 1.35, 1999/07/17 21:35:50 |
version 1.35.2.5, 2001/03/27 15:32:50 |
|
|
|
|
#include <miscfs/specfs/specdev.h> |
#include <miscfs/specfs/specdev.h> |
|
|
#include <vm/vm.h> |
|
#include <vm/vm_page.h> |
|
#include <vm/vm_kern.h> |
|
|
|
#include <sys/syscallargs.h> |
#include <sys/syscallargs.h> |
|
|
#include <uvm/uvm.h> |
#include <uvm/uvm.h> |
Line 168 sys_mincore(p, v, retval) |
|
Line 164 sys_mincore(p, v, retval) |
|
* Lock down vec, so our returned status isn't outdated by |
* Lock down vec, so our returned status isn't outdated by |
* storing the status byte for a page. |
* storing the status byte for a page. |
*/ |
*/ |
uvm_vslock(p, vec, npgs, VM_PROT_WRITE); |
|
|
|
|
uvm_vslock(p, vec, npgs, VM_PROT_WRITE); |
vm_map_lock_read(map); |
vm_map_lock_read(map); |
|
|
if (uvm_map_lookup_entry(map, start, &entry) == FALSE) { |
if (uvm_map_lookup_entry(map, start, &entry) == FALSE) { |
Line 180 sys_mincore(p, v, retval) |
|
Line 176 sys_mincore(p, v, retval) |
|
for (/* nothing */; |
for (/* nothing */; |
entry != &map->header && entry->start < end; |
entry != &map->header && entry->start < end; |
entry = entry->next) { |
entry = entry->next) { |
#ifdef DIAGNOSTIC |
KASSERT(!UVM_ET_ISSUBMAP(entry)); |
if (UVM_ET_ISSUBMAP(entry)) |
KASSERT(start >= entry->start); |
panic("mincore: user map has submap"); |
|
if (start < entry->start) |
|
panic("mincore: hole"); |
|
#endif |
|
/* Make sure there are no holes. */ |
/* Make sure there are no holes. */ |
if (entry->end < end && |
if (entry->end < end && |
(entry->next == &map->header || |
(entry->next == &map->header || |
Line 200 sys_mincore(p, v, retval) |
|
Line 193 sys_mincore(p, v, retval) |
|
* Special case for objects with no "real" pages. Those |
* Special case for objects with no "real" pages. Those |
* are always considered resident (mapped devices). |
* are always considered resident (mapped devices). |
*/ |
*/ |
|
|
if (UVM_ET_ISOBJ(entry)) { |
if (UVM_ET_ISOBJ(entry)) { |
#ifdef DIAGNOSTIC |
KASSERT(!UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj)); |
if (UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj)) |
|
panic("mincore: user map has kernel object"); |
|
#endif |
|
if (entry->object.uvm_obj->pgops->pgo_releasepg |
if (entry->object.uvm_obj->pgops->pgo_releasepg |
== NULL) { |
== NULL) { |
for (/* nothing */; start < lim; |
for (/* nothing */; start < lim; |
Line 230 sys_mincore(p, v, retval) |
|
Line 221 sys_mincore(p, v, retval) |
|
start - entry->start); |
start - entry->start); |
/* Don't need to lock anon here. */ |
/* Don't need to lock anon here. */ |
if (anon != NULL && anon->u.an_page != NULL) { |
if (anon != NULL && anon->u.an_page != NULL) { |
|
|
/* |
/* |
* Anon has the page for this entry |
* Anon has the page for this entry |
* offset. |
* offset. |
*/ |
*/ |
|
|
pgi = 1; |
pgi = 1; |
} |
} |
} |
} |
|
|
if (uobj != NULL && pgi == 0) { |
if (uobj != NULL && pgi == 0) { |
/* Check the bottom layer. */ |
/* Check the bottom layer. */ |
m = uvm_pagelookup(uobj, |
m = uvm_pagelookup(uobj, |
entry->offset + (start - entry->start)); |
entry->offset + (start - entry->start)); |
if (m != NULL) { |
if (m != NULL) { |
|
|
/* |
/* |
* Object has the page for this entry |
* Object has the page for this entry |
* offset. |
* offset. |
*/ |
*/ |
|
|
pgi = 1; |
pgi = 1; |
} |
} |
} |
} |
|
|
(void) subyte(vec, pgi); |
(void) subyte(vec, pgi); |
} |
} |
|
|
if (uobj != NULL) |
if (uobj != NULL) |
simple_unlock(&uobj->vmobjlock); |
simple_unlock(&uobj->vmobjlock); |
if (amap != NULL) |
if (amap != NULL) |
Line 266 sys_mincore(p, v, retval) |
|
Line 258 sys_mincore(p, v, retval) |
|
return (error); |
return (error); |
} |
} |
|
|
#if 0 |
|
/* |
|
* munmapfd: unmap file descriptor |
|
* |
|
* XXX: is this acutally a useful function? could it be useful? |
|
*/ |
|
|
|
void |
|
munmapfd(p, fd) |
|
struct proc *p; |
|
int fd; |
|
{ |
|
|
|
/* |
|
* XXX should vm_deallocate any regions mapped to this file |
|
*/ |
|
p->p_fd->fd_ofileflags[fd] &= ~UF_MAPPED; |
|
} |
|
#endif |
|
|
|
/* |
/* |
* sys_mmap: mmap system call. |
* sys_mmap: mmap system call. |
* |
* |
Line 301 sys_mmap(p, v, retval) |
|
Line 273 sys_mmap(p, v, retval) |
|
void *v; |
void *v; |
register_t *retval; |
register_t *retval; |
{ |
{ |
register struct sys_mmap_args /* { |
struct sys_mmap_args /* { |
syscallarg(caddr_t) addr; |
syscallarg(caddr_t) addr; |
syscallarg(size_t) len; |
syscallarg(size_t) len; |
syscallarg(int) prot; |
syscallarg(int) prot; |
Line 317 sys_mmap(p, v, retval) |
|
Line 289 sys_mmap(p, v, retval) |
|
vm_prot_t prot, maxprot; |
vm_prot_t prot, maxprot; |
int flags, fd; |
int flags, fd; |
vaddr_t vm_min_address = VM_MIN_ADDRESS; |
vaddr_t vm_min_address = VM_MIN_ADDRESS; |
register struct filedesc *fdp = p->p_fd; |
struct filedesc *fdp = p->p_fd; |
register struct file *fp; |
struct file *fp; |
struct vnode *vp; |
struct vnode *vp; |
caddr_t handle; |
void *handle; |
int error; |
int error; |
|
|
/* |
/* |
* first, extract syscall args from the uap. |
* first, extract syscall args from the uap. |
*/ |
*/ |
|
|
addr = (vaddr_t) SCARG(uap, addr); |
addr = (vaddr_t)SCARG(uap, addr); |
size = (vsize_t) SCARG(uap, len); |
size = (vsize_t)SCARG(uap, len); |
prot = SCARG(uap, prot) & VM_PROT_ALL; |
prot = SCARG(uap, prot) & VM_PROT_ALL; |
flags = SCARG(uap, flags); |
flags = SCARG(uap, flags); |
fd = SCARG(uap, fd); |
fd = SCARG(uap, fd); |
Line 344 sys_mmap(p, v, retval) |
|
Line 316 sys_mmap(p, v, retval) |
|
return (EINVAL); |
return (EINVAL); |
|
|
/* |
/* |
* make sure that the newsize fits within a vaddr_t |
|
* XXX: need to revise addressing data types |
|
*/ |
|
if (pos + size > (vaddr_t)-PAGE_SIZE) { |
|
#ifdef DEBUG |
|
printf("mmap: pos=%qx, size=%lx too big\n", (long long)pos, |
|
(long)size); |
|
#endif |
|
return (EINVAL); |
|
} |
|
|
|
/* |
|
* align file position and save offset. adjust size. |
* align file position and save offset. adjust size. |
*/ |
*/ |
|
|
pageoff = (pos & PAGE_MASK); |
pageoff = (pos & PAGE_MASK); |
pos -= pageoff; |
pos -= pageoff; |
size += pageoff; /* add offset */ |
size += pageoff; /* add offset */ |
size = (vsize_t) round_page(size); /* round up */ |
size = (vsize_t)round_page(size); /* round up */ |
if ((ssize_t) size < 0) |
if ((ssize_t) size < 0) |
return (EINVAL); /* don't allow wrap */ |
return (EINVAL); /* don't allow wrap */ |
|
|
Line 391 sys_mmap(p, v, retval) |
|
Line 351 sys_mmap(p, v, retval) |
|
* not fixed: make sure we skip over the largest possible heap. |
* not fixed: make sure we skip over the largest possible heap. |
* we will refine our guess later (e.g. to account for VAC, etc) |
* we will refine our guess later (e.g. to account for VAC, etc) |
*/ |
*/ |
if (addr < round_page(p->p_vmspace->vm_daddr + MAXDSIZ)) |
|
addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ); |
addr = MAX(addr, round_page((vaddr_t)p->p_vmspace->vm_daddr + |
|
MAXDSIZ)); |
} |
} |
|
|
/* |
/* |
Line 415 sys_mmap(p, v, retval) |
|
Line 376 sys_mmap(p, v, retval) |
|
vp->v_type != VBLK) |
vp->v_type != VBLK) |
return (ENODEV); /* only REG/CHR/BLK support mmap */ |
return (ENODEV); /* only REG/CHR/BLK support mmap */ |
|
|
|
if (vp->v_type == VREG && (pos + size) < pos) |
|
return (EOVERFLOW); /* no offset wrapping */ |
|
|
/* special case: catch SunOS style /dev/zero */ |
/* special case: catch SunOS style /dev/zero */ |
if (vp->v_type == VCHR && iszerodev(vp->v_rdev)) { |
if (vp->v_type == VCHR && iszerodev(vp->v_rdev)) { |
flags |= MAP_ANON; |
flags |= MAP_ANON; |
Line 446 sys_mmap(p, v, retval) |
|
Line 410 sys_mmap(p, v, retval) |
|
* so just change it to MAP_SHARED. |
* so just change it to MAP_SHARED. |
*/ |
*/ |
if (vp->v_type == VCHR && (flags & MAP_PRIVATE) != 0) { |
if (vp->v_type == VCHR && (flags & MAP_PRIVATE) != 0) { |
#if defined(DIAGNOSTIC) |
|
printf("WARNING: converted MAP_PRIVATE device mapping " |
|
"to MAP_SHARED (pid %d comm %s)\n", p->p_pid, |
|
p->p_comm); |
|
#endif |
|
flags = (flags & ~MAP_PRIVATE) | MAP_SHARED; |
flags = (flags & ~MAP_PRIVATE) | MAP_SHARED; |
} |
} |
|
|
Line 489 sys_mmap(p, v, retval) |
|
Line 448 sys_mmap(p, v, retval) |
|
/* MAP_PRIVATE mappings can always write to */ |
/* MAP_PRIVATE mappings can always write to */ |
maxprot |= VM_PROT_WRITE; |
maxprot |= VM_PROT_WRITE; |
} |
} |
|
handle = vp; |
/* |
|
* set handle to vnode |
|
*/ |
|
|
|
handle = (caddr_t)vp; |
|
|
|
} else { /* MAP_ANON case */ |
} else { /* MAP_ANON case */ |
/* |
/* |
Line 519 sys_mmap(p, v, retval) |
|
Line 473 sys_mmap(p, v, retval) |
|
if ((flags & MAP_ANON) != 0 || |
if ((flags & MAP_ANON) != 0 || |
((flags & MAP_PRIVATE) != 0 && (prot & PROT_WRITE) != 0)) { |
((flags & MAP_PRIVATE) != 0 && (prot & PROT_WRITE) != 0)) { |
if (size > |
if (size > |
(p->p_rlimit[RLIMIT_DATA].rlim_cur - ctob(p->p_vmspace->vm_dsize))) { |
(p->p_rlimit[RLIMIT_DATA].rlim_cur - |
|
ctob(p->p_vmspace->vm_dsize))) { |
return (ENOMEM); |
return (ENOMEM); |
} |
} |
} |
} |
Line 556 sys___msync13(p, v, retval) |
|
Line 511 sys___msync13(p, v, retval) |
|
vaddr_t addr; |
vaddr_t addr; |
vsize_t size, pageoff; |
vsize_t size, pageoff; |
vm_map_t map; |
vm_map_t map; |
int rv, flags, uvmflags; |
int error, rv, flags, uvmflags; |
|
|
/* |
/* |
* extract syscall args from the uap |
* extract syscall args from the uap |
Line 575 sys___msync13(p, v, retval) |
|
Line 530 sys___msync13(p, v, retval) |
|
flags |= MS_SYNC; |
flags |= MS_SYNC; |
|
|
/* |
/* |
* align the address to a page boundary, and adjust the size accordingly |
* align the address to a page boundary and adjust the size accordingly. |
*/ |
*/ |
|
|
pageoff = (addr & PAGE_MASK); |
pageoff = (addr & PAGE_MASK); |
addr -= pageoff; |
addr -= pageoff; |
size += pageoff; |
size += pageoff; |
size = (vsize_t) round_page(size); |
size = (vsize_t)round_page(size); |
|
|
/* disallow wrap-around. */ |
/* disallow wrap-around. */ |
if (addr + size < addr) |
if (addr + size < addr) |
Line 603 sys___msync13(p, v, retval) |
|
Line 558 sys___msync13(p, v, retval) |
|
* This can be incorrect if the region splits or is coalesced |
* This can be incorrect if the region splits or is coalesced |
* with a neighbor. |
* with a neighbor. |
*/ |
*/ |
|
|
if (size == 0) { |
if (size == 0) { |
vm_map_entry_t entry; |
vm_map_entry_t entry; |
|
|
Line 620 sys___msync13(p, v, retval) |
|
Line 576 sys___msync13(p, v, retval) |
|
/* |
/* |
* translate MS_ flags into PGO_ flags |
* translate MS_ flags into PGO_ flags |
*/ |
*/ |
|
|
uvmflags = PGO_CLEANIT; |
uvmflags = PGO_CLEANIT; |
if (flags & MS_INVALIDATE) |
if (flags & MS_INVALIDATE) |
uvmflags |= PGO_FREE; |
uvmflags |= PGO_FREE; |
Line 628 sys___msync13(p, v, retval) |
|
Line 585 sys___msync13(p, v, retval) |
|
else |
else |
uvmflags |= PGO_SYNCIO; /* XXXCDC: force sync for now! */ |
uvmflags |= PGO_SYNCIO; /* XXXCDC: force sync for now! */ |
|
|
/* |
error = uvm_map_clean(map, addr, addr+size, uvmflags); |
* doit! |
return error; |
*/ |
|
rv = uvm_map_clean(map, addr, addr+size, uvmflags); |
|
|
|
/* |
|
* and return... |
|
*/ |
|
switch (rv) { |
|
case KERN_SUCCESS: |
|
return(0); |
|
case KERN_INVALID_ADDRESS: |
|
return (ENOMEM); |
|
case KERN_FAILURE: |
|
return (EIO); |
|
case KERN_PAGES_LOCKED: /* XXXCDC: uvm doesn't return this */ |
|
return (EBUSY); |
|
default: |
|
return (EINVAL); |
|
} |
|
/*NOTREACHED*/ |
|
} |
} |
|
|
/* |
/* |
Line 657 sys___msync13(p, v, retval) |
|
Line 595 sys___msync13(p, v, retval) |
|
|
|
int |
int |
sys_munmap(p, v, retval) |
sys_munmap(p, v, retval) |
register struct proc *p; |
struct proc *p; |
void *v; |
void *v; |
register_t *retval; |
register_t *retval; |
{ |
{ |
register struct sys_munmap_args /* { |
struct sys_munmap_args /* { |
syscallarg(caddr_t) addr; |
syscallarg(caddr_t) addr; |
syscallarg(size_t) len; |
syscallarg(size_t) len; |
} */ *uap = v; |
} */ *uap = v; |
Line 672 sys_munmap(p, v, retval) |
|
Line 610 sys_munmap(p, v, retval) |
|
struct vm_map_entry *dead_entries; |
struct vm_map_entry *dead_entries; |
|
|
/* |
/* |
* get syscall args... |
* get syscall args. |
*/ |
*/ |
|
|
addr = (vaddr_t) SCARG(uap, addr); |
addr = (vaddr_t)SCARG(uap, addr); |
size = (vsize_t) SCARG(uap, len); |
size = (vsize_t)SCARG(uap, len); |
|
|
/* |
/* |
* align the address to a page boundary, and adjust the size accordingly |
* align the address to a page boundary and adjust the size accordingly. |
*/ |
*/ |
|
|
pageoff = (addr & PAGE_MASK); |
pageoff = (addr & PAGE_MASK); |
addr -= pageoff; |
addr -= pageoff; |
size += pageoff; |
size += pageoff; |
size = (vsize_t) round_page(size); |
size = (vsize_t)round_page(size); |
|
|
if ((int)size < 0) |
if ((int)size < 0) |
return (EINVAL); |
return (EINVAL); |
Line 704 sys_munmap(p, v, retval) |
|
Line 642 sys_munmap(p, v, retval) |
|
return (EINVAL); |
return (EINVAL); |
map = &p->p_vmspace->vm_map; |
map = &p->p_vmspace->vm_map; |
|
|
|
|
vm_map_lock(map); /* lock map so we can checkprot */ |
|
|
|
/* |
/* |
* interesting system call semantic: make sure entire range is |
* interesting system call semantic: make sure entire range is |
* allocated before allowing an unmap. |
* allocated before allowing an unmap. |
*/ |
*/ |
|
|
|
vm_map_lock(map); |
if (!uvm_map_checkprot(map, addr, addr + size, VM_PROT_NONE)) { |
if (!uvm_map_checkprot(map, addr, addr + size, VM_PROT_NONE)) { |
vm_map_unlock(map); |
vm_map_unlock(map); |
return (EINVAL); |
return (EINVAL); |
} |
} |
|
uvm_unmap_remove(map, addr, addr + size, &dead_entries); |
/* |
vm_map_unlock(map); |
* doit! |
|
*/ |
|
(void) uvm_unmap_remove(map, addr, addr + size, &dead_entries); |
|
|
|
vm_map_unlock(map); /* and unlock */ |
|
|
|
if (dead_entries != NULL) |
if (dead_entries != NULL) |
uvm_unmap_detach(dead_entries, 0); |
uvm_unmap_detach(dead_entries, 0); |
|
|
return (0); |
return (0); |
} |
} |
|
|
Line 748 sys_mprotect(p, v, retval) |
|
Line 677 sys_mprotect(p, v, retval) |
|
vaddr_t addr; |
vaddr_t addr; |
vsize_t size, pageoff; |
vsize_t size, pageoff; |
vm_prot_t prot; |
vm_prot_t prot; |
int rv; |
int error; |
|
|
/* |
/* |
* extract syscall args from uap |
* extract syscall args from uap |
Line 759 sys_mprotect(p, v, retval) |
|
Line 688 sys_mprotect(p, v, retval) |
|
prot = SCARG(uap, prot) & VM_PROT_ALL; |
prot = SCARG(uap, prot) & VM_PROT_ALL; |
|
|
/* |
/* |
* align the address to a page boundary, and adjust the size accordingly |
* align the address to a page boundary and adjust the size accordingly. |
*/ |
*/ |
|
|
pageoff = (addr & PAGE_MASK); |
pageoff = (addr & PAGE_MASK); |
addr -= pageoff; |
addr -= pageoff; |
size += pageoff; |
size += pageoff; |
size = (vsize_t) round_page(size); |
size = (vsize_t)round_page(size); |
|
|
if ((int)size < 0) |
if ((int)size < 0) |
return (EINVAL); |
return (EINVAL); |
|
error = uvm_map_protect(&p->p_vmspace->vm_map, addr, addr + size, prot, |
/* |
FALSE); |
* doit |
return error; |
*/ |
|
|
|
rv = uvm_map_protect(&p->p_vmspace->vm_map, |
|
addr, addr+size, prot, FALSE); |
|
|
|
if (rv == KERN_SUCCESS) |
|
return (0); |
|
if (rv == KERN_PROTECTION_FAILURE) |
|
return (EACCES); |
|
return (EINVAL); |
|
} |
} |
|
|
/* |
/* |
Line 799 sys_minherit(p, v, retval) |
|
Line 720 sys_minherit(p, v, retval) |
|
} */ *uap = v; |
} */ *uap = v; |
vaddr_t addr; |
vaddr_t addr; |
vsize_t size, pageoff; |
vsize_t size, pageoff; |
register vm_inherit_t inherit; |
vm_inherit_t inherit; |
|
int error; |
|
|
addr = (vaddr_t)SCARG(uap, addr); |
addr = (vaddr_t)SCARG(uap, addr); |
size = (vsize_t)SCARG(uap, len); |
size = (vsize_t)SCARG(uap, len); |
inherit = SCARG(uap, inherit); |
inherit = SCARG(uap, inherit); |
|
|
/* |
/* |
* align the address to a page boundary, and adjust the size accordingly |
* align the address to a page boundary and adjust the size accordingly. |
*/ |
*/ |
|
|
pageoff = (addr & PAGE_MASK); |
pageoff = (addr & PAGE_MASK); |
addr -= pageoff; |
addr -= pageoff; |
size += pageoff; |
size += pageoff; |
size = (vsize_t) round_page(size); |
size = (vsize_t)round_page(size); |
|
|
if ((int)size < 0) |
if ((int)size < 0) |
return (EINVAL); |
return (EINVAL); |
|
error = uvm_map_inherit(&p->p_vmspace->vm_map, addr, addr + size, |
switch (uvm_map_inherit(&p->p_vmspace->vm_map, addr, addr+size, |
inherit); |
inherit)) { |
return error; |
case KERN_SUCCESS: |
|
return (0); |
|
case KERN_PROTECTION_FAILURE: |
|
return (EACCES); |
|
} |
|
return (EINVAL); |
|
} |
} |
|
|
/* |
/* |
Line 844 sys_madvise(p, v, retval) |
|
Line 761 sys_madvise(p, v, retval) |
|
} */ *uap = v; |
} */ *uap = v; |
vaddr_t addr; |
vaddr_t addr; |
vsize_t size, pageoff; |
vsize_t size, pageoff; |
int advice, rv;; |
int advice, error; |
|
|
addr = (vaddr_t)SCARG(uap, addr); |
addr = (vaddr_t)SCARG(uap, addr); |
size = (vsize_t)SCARG(uap, len); |
size = (vsize_t)SCARG(uap, len); |
Line 853 sys_madvise(p, v, retval) |
|
Line 770 sys_madvise(p, v, retval) |
|
/* |
/* |
* align the address to a page boundary, and adjust the size accordingly |
* align the address to a page boundary, and adjust the size accordingly |
*/ |
*/ |
|
|
pageoff = (addr & PAGE_MASK); |
pageoff = (addr & PAGE_MASK); |
addr -= pageoff; |
addr -= pageoff; |
size += pageoff; |
size += pageoff; |
size = (vsize_t) round_page(size); |
size = (vsize_t)round_page(size); |
|
|
if ((ssize_t)size <= 0) |
if ((ssize_t)size <= 0) |
return (EINVAL); |
return (EINVAL); |
Line 865 sys_madvise(p, v, retval) |
|
Line 783 sys_madvise(p, v, retval) |
|
case MADV_NORMAL: |
case MADV_NORMAL: |
case MADV_RANDOM: |
case MADV_RANDOM: |
case MADV_SEQUENTIAL: |
case MADV_SEQUENTIAL: |
rv = uvm_map_advice(&p->p_vmspace->vm_map, addr, addr + size, |
error = uvm_map_advice(&p->p_vmspace->vm_map, addr, addr + size, |
advice); |
advice); |
break; |
break; |
|
|
case MADV_WILLNEED: |
case MADV_WILLNEED: |
|
|
/* |
/* |
* Activate all these pages, pre-faulting them in if |
* Activate all these pages, pre-faulting them in if |
* necessary. |
* necessary. |
Line 879 sys_madvise(p, v, retval) |
|
Line 798 sys_madvise(p, v, retval) |
|
* Should invent a "weak" mode for uvm_fault() |
* Should invent a "weak" mode for uvm_fault() |
* which would only do the PGO_LOCKED pgo_get(). |
* which would only do the PGO_LOCKED pgo_get(). |
*/ |
*/ |
|
|
return (0); |
return (0); |
|
|
case MADV_DONTNEED: |
case MADV_DONTNEED: |
|
|
/* |
/* |
* Deactivate all these pages. We don't need them |
* Deactivate all these pages. We don't need them |
* any more. We don't, however, toss the data in |
* any more. We don't, however, toss the data in |
* the pages. |
* the pages. |
*/ |
*/ |
rv = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size, |
|
|
error = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size, |
PGO_DEACTIVATE); |
PGO_DEACTIVATE); |
break; |
break; |
|
|
case MADV_FREE: |
case MADV_FREE: |
|
|
/* |
/* |
* These pages contain no valid data, and may be |
* These pages contain no valid data, and may be |
* grbage-collected. Toss all resources, including |
* garbage-collected. Toss all resources, including |
* any swap space in use. |
* any swap space in use. |
*/ |
*/ |
rv = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size, |
|
|
error = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size, |
PGO_FREE); |
PGO_FREE); |
break; |
break; |
|
|
case MADV_SPACEAVAIL: |
case MADV_SPACEAVAIL: |
|
|
/* |
/* |
* XXXMRG What is this? I think it's: |
* XXXMRG What is this? I think it's: |
* |
* |
Line 912 sys_madvise(p, v, retval) |
|
Line 837 sys_madvise(p, v, retval) |
|
* as it will free swap space allocated to pages in core. |
* as it will free swap space allocated to pages in core. |
* There's also what to do for device/file/anonymous memory. |
* There's also what to do for device/file/anonymous memory. |
*/ |
*/ |
|
|
return (EINVAL); |
return (EINVAL); |
|
|
default: |
default: |
return (EINVAL); |
return (EINVAL); |
} |
} |
|
|
switch (rv) { |
return error; |
case KERN_SUCCESS: |
|
return (0); |
|
case KERN_NO_SPACE: |
|
return (EAGAIN); |
|
case KERN_INVALID_ADDRESS: |
|
return (ENOMEM); |
|
case KERN_FAILURE: |
|
return (EIO); |
|
} |
|
|
|
return (EINVAL); |
|
} |
} |
|
|
/* |
/* |
Line 953 sys_mlock(p, v, retval) |
|
Line 868 sys_mlock(p, v, retval) |
|
/* |
/* |
* extract syscall args from uap |
* extract syscall args from uap |
*/ |
*/ |
|
|
addr = (vaddr_t)SCARG(uap, addr); |
addr = (vaddr_t)SCARG(uap, addr); |
size = (vsize_t)SCARG(uap, len); |
size = (vsize_t)SCARG(uap, len); |
|
|
/* |
/* |
* align the address to a page boundary and adjust the size accordingly |
* align the address to a page boundary and adjust the size accordingly |
*/ |
*/ |
|
|
pageoff = (addr & PAGE_MASK); |
pageoff = (addr & PAGE_MASK); |
addr -= pageoff; |
addr -= pageoff; |
size += pageoff; |
size += pageoff; |
size = (vsize_t) round_page(size); |
size = (vsize_t)round_page(size); |
|
|
/* disallow wrap-around. */ |
/* disallow wrap-around. */ |
if (addr + (int)size < addr) |
if (addr + size < addr) |
return (EINVAL); |
return (EINVAL); |
|
|
if (atop(size) + uvmexp.wired > uvmexp.wiredmax) |
if (atop(size) + uvmexp.wired > uvmexp.wiredmax) |
Line 982 sys_mlock(p, v, retval) |
|
Line 899 sys_mlock(p, v, retval) |
|
|
|
error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, FALSE, |
error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, FALSE, |
0); |
0); |
return (error == KERN_SUCCESS ? 0 : ENOMEM); |
return error; |
} |
} |
|
|
/* |
/* |
Line 1013 sys_munlock(p, v, retval) |
|
Line 930 sys_munlock(p, v, retval) |
|
/* |
/* |
* align the address to a page boundary, and adjust the size accordingly |
* align the address to a page boundary, and adjust the size accordingly |
*/ |
*/ |
|
|
pageoff = (addr & PAGE_MASK); |
pageoff = (addr & PAGE_MASK); |
addr -= pageoff; |
addr -= pageoff; |
size += pageoff; |
size += pageoff; |
size = (vsize_t) round_page(size); |
size = (vsize_t)round_page(size); |
|
|
/* disallow wrap-around. */ |
/* disallow wrap-around. */ |
if (addr + (int)size < addr) |
if (addr + size < addr) |
return (EINVAL); |
return (EINVAL); |
|
|
#ifndef pmap_wired_count |
#ifndef pmap_wired_count |
Line 1029 sys_munlock(p, v, retval) |
|
Line 947 sys_munlock(p, v, retval) |
|
|
|
error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, TRUE, |
error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, TRUE, |
0); |
0); |
return (error == KERN_SUCCESS ? 0 : ENOMEM); |
return error; |
} |
} |
|
|
/* |
/* |
Line 1060 sys_mlockall(p, v, retval) |
|
Line 978 sys_mlockall(p, v, retval) |
|
|
|
error = uvm_map_pageable_all(&p->p_vmspace->vm_map, flags, |
error = uvm_map_pageable_all(&p->p_vmspace->vm_map, flags, |
p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); |
p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); |
switch (error) { |
|
case KERN_SUCCESS: |
|
error = 0; |
|
break; |
|
|
|
case KERN_NO_SPACE: /* XXX overloaded */ |
|
error = ENOMEM; |
|
break; |
|
|
|
default: |
|
/* |
|
* "Some or all of the memory could not be locked when |
|
* the call was made." |
|
*/ |
|
error = EAGAIN; |
|
} |
|
|
|
return (error); |
return (error); |
} |
} |
|
|
Line 1111 uvm_mmap(map, addr, size, prot, maxprot, |
|
Line 1012 uvm_mmap(map, addr, size, prot, maxprot, |
|
vsize_t size; |
vsize_t size; |
vm_prot_t prot, maxprot; |
vm_prot_t prot, maxprot; |
int flags; |
int flags; |
caddr_t handle; /* XXX: VNODE? */ |
void *handle; |
vaddr_t foff; |
voff_t foff; |
vsize_t locklimit; |
vsize_t locklimit; |
{ |
{ |
struct uvm_object *uobj; |
struct uvm_object *uobj; |
struct vnode *vp; |
struct vnode *vp; |
int retval; |
int error; |
int advice = UVM_ADV_NORMAL; |
int advice = UVM_ADV_NORMAL; |
uvm_flag_t uvmflag = 0; |
uvm_flag_t uvmflag = 0; |
|
|
Line 1140 uvm_mmap(map, addr, size, prot, maxprot, |
|
Line 1041 uvm_mmap(map, addr, size, prot, maxprot, |
|
if ((flags & MAP_FIXED) == 0) { |
if ((flags & MAP_FIXED) == 0) { |
*addr = round_page(*addr); /* round */ |
*addr = round_page(*addr); /* round */ |
} else { |
} else { |
|
|
if (*addr & PAGE_MASK) |
if (*addr & PAGE_MASK) |
return(EINVAL); |
return(EINVAL); |
uvmflag |= UVM_FLAG_FIXED; |
uvmflag |= UVM_FLAG_FIXED; |
Line 1153 uvm_mmap(map, addr, size, prot, maxprot, |
|
Line 1053 uvm_mmap(map, addr, size, prot, maxprot, |
|
*/ |
*/ |
|
|
if (flags & MAP_ANON) { |
if (flags & MAP_ANON) { |
|
foff = UVM_UNKNOWN_OFFSET; |
foff = UVM_UNKNOWN_OFFSET; |
|
uobj = NULL; |
uobj = NULL; |
if ((flags & MAP_SHARED) == 0) |
if ((flags & MAP_SHARED) == 0) |
/* XXX: defer amap create */ |
/* XXX: defer amap create */ |
Line 1164 uvm_mmap(map, addr, size, prot, maxprot, |
|
Line 1063 uvm_mmap(map, addr, size, prot, maxprot, |
|
uvmflag |= UVM_FLAG_OVERLAY; |
uvmflag |= UVM_FLAG_OVERLAY; |
|
|
} else { |
} else { |
|
vp = (struct vnode *)handle; |
vp = (struct vnode *) handle; /* get vnode */ |
|
if (vp->v_type != VCHR) { |
if (vp->v_type != VCHR) { |
uobj = uvn_attach((void *) vp, (flags & MAP_SHARED) ? |
uobj = uvn_attach((void *)vp, (flags & MAP_SHARED) ? |
maxprot : (maxprot & ~VM_PROT_WRITE)); |
maxprot : (maxprot & ~VM_PROT_WRITE)); |
|
|
|
/* XXX for now, attach doesn't gain a ref */ |
|
VREF(vp); |
|
} else { |
|
uobj = udv_attach((void *) &vp->v_rdev, |
|
(flags & MAP_SHARED) ? maxprot : |
|
(maxprot & ~VM_PROT_WRITE), foff, size); |
/* |
/* |
* XXXCDC: hack from old code |
* XXX Some devices don't like to be mapped with |
* don't allow vnodes which have been mapped |
* XXX PROT_EXEC, but we don't really have a |
* shared-writeable to persist [forces them to be |
* XXX better way of handling this, right now |
* flushed out when last reference goes]. |
|
* XXXCDC: interesting side effect: avoids a bug. |
|
* note that in WRITE [ufs_readwrite.c] that we |
|
* allocate buffer, uncache, and then do the write. |
|
* the problem with this is that if the uncache causes |
|
* VM data to be flushed to the same area of the file |
|
* we are writing to... in that case we've got the |
|
* buffer locked and our process goes to sleep forever. |
|
* |
|
* XXXCDC: checking maxprot protects us from the |
|
* "persistbug" program but this is not a long term |
|
* solution. |
|
* |
|
* XXXCDC: we don't bother calling uncache with the vp |
|
* VOP_LOCKed since we know that we are already |
|
* holding a valid reference to the uvn (from the |
|
* uvn_attach above), and thus it is impossible for |
|
* the uncache to kill the uvn and trigger I/O. |
|
*/ |
*/ |
if (flags & MAP_SHARED) { |
if (uobj == NULL && (prot & PROT_EXEC) == 0) { |
if ((prot & VM_PROT_WRITE) || |
maxprot &= ~VM_PROT_EXECUTE; |
(maxprot & VM_PROT_WRITE)) { |
uobj = udv_attach((void *)&vp->v_rdev, |
uvm_vnp_uncache(vp); |
(flags & MAP_SHARED) ? maxprot : |
} |
(maxprot & ~VM_PROT_WRITE), foff, size); |
} |
} |
|
|
} else { |
|
uobj = udv_attach((void *) &vp->v_rdev, |
|
(flags & MAP_SHARED) ? |
|
maxprot : (maxprot & ~VM_PROT_WRITE), foff, size); |
|
advice = UVM_ADV_RANDOM; |
advice = UVM_ADV_RANDOM; |
} |
} |
|
|
if (uobj == NULL) |
if (uobj == NULL) |
return((vp->v_type == VREG) ? ENOMEM : EINVAL); |
return((vp->v_type == VREG) ? ENOMEM : EINVAL); |
|
|
if ((flags & MAP_SHARED) == 0) |
if ((flags & MAP_SHARED) == 0) |
uvmflag |= UVM_FLAG_COPYONW; |
uvmflag |= UVM_FLAG_COPYONW; |
} |
} |
|
|
/* |
|
* set up mapping flags |
|
*/ |
|
|
|
uvmflag = UVM_MAPFLAG(prot, maxprot, |
uvmflag = UVM_MAPFLAG(prot, maxprot, |
(flags & MAP_SHARED) ? UVM_INH_SHARE : UVM_INH_COPY, |
(flags & MAP_SHARED) ? UVM_INH_SHARE : UVM_INH_COPY, |
advice, uvmflag); |
advice, uvmflag); |
|
error = uvm_map(map, addr, size, uobj, foff, 0, uvmflag); |
|
if (error) { |
|
if (uobj) |
|
uobj->pgops->pgo_detach(uobj); |
|
return error; |
|
} |
|
|
/* |
/* |
* do it! |
* POSIX 1003.1b -- if our address space was configured |
|
* to lock all future mappings, wire the one we just made. |
*/ |
*/ |
|
|
retval = uvm_map(map, addr, size, uobj, foff, uvmflag); |
if (prot == VM_PROT_NONE) { |
|
|
if (retval == KERN_SUCCESS) { |
|
/* |
/* |
* POSIX 1003.1b -- if our address space was configured |
* No more work to do in this case. |
* to lock all future mappings, wire the one we just made. |
|
*/ |
*/ |
if (prot == VM_PROT_NONE) { |
|
/* |
|
* No more work to do in this case. |
|
*/ |
|
return (0); |
|
} |
|
|
|
vm_map_lock(map); |
|
|
|
if (map->flags & VM_MAP_WIREFUTURE) { |
return (0); |
/* |
} |
* uvm_map_pageable() always returns the map |
vm_map_lock(map); |
* unlocked. |
if (map->flags & VM_MAP_WIREFUTURE) { |
*/ |
if ((atop(size) + uvmexp.wired) > uvmexp.wiredmax |
if ((atop(size) + uvmexp.wired) > uvmexp.wiredmax |
|
#ifdef pmap_wired_count |
#ifdef pmap_wired_count |
|| (locklimit != 0 && (size + |
|| (locklimit != 0 && (size + |
ptoa(pmap_wired_count(vm_map_pmap(map)))) > |
ptoa(pmap_wired_count(vm_map_pmap(map)))) > |
locklimit) |
locklimit) |
#endif |
#endif |
) { |
) { |
retval = KERN_RESOURCE_SHORTAGE; |
vm_map_unlock(map); |
/* unmap the region! */ |
uvm_unmap(map, *addr, *addr + size); |
(void) uvm_unmap(map, *addr, *addr + size); |
return ENOMEM; |
goto bad; |
|
} |
|
retval = uvm_map_pageable(map, *addr, *addr + size, |
|
FALSE, UVM_LK_ENTER); |
|
if (retval != KERN_SUCCESS) { |
|
/* unmap the region! */ |
|
(void) uvm_unmap(map, *addr, *addr + size); |
|
goto bad; |
|
} |
|
return (0); |
|
} |
} |
|
|
vm_map_unlock(map); |
/* |
|
* uvm_map_pageable() always returns the map unlocked. |
|
*/ |
|
|
|
error = uvm_map_pageable(map, *addr, *addr + size, |
|
FALSE, UVM_LK_ENTER); |
|
if (error) { |
|
uvm_unmap(map, *addr, *addr + size); |
|
return error; |
|
} |
return (0); |
return (0); |
} |
} |
|
vm_map_unlock(map); |
/* |
return 0; |
* errors: first detach from the uobj, if any. |
|
*/ |
|
|
|
if (uobj) |
|
uobj->pgops->pgo_detach(uobj); |
|
|
|
bad: |
|
switch (retval) { |
|
case KERN_INVALID_ADDRESS: |
|
case KERN_NO_SPACE: |
|
return(ENOMEM); |
|
case KERN_RESOURCE_SHORTAGE: |
|
return (EAGAIN); |
|
case KERN_PROTECTION_FAILURE: |
|
return(EACCES); |
|
} |
|
return(EINVAL); |
|
} |
} |