1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1991, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$ 39 * 40 * @(#)vm_mmap.c 8.4 (Berkeley) 1/12/94 41 * $Id: vm_mmap.c,v 1.67 1997/08/30 18:50:06 peter Exp $ 42 */ 43 44 /* 45 * Mapped file (mmap) interface to VM 46 */ 47 48 #include "opt_rlimit.h" 49 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/sysproto.h> 53 #include <sys/filedesc.h> 54 #include <sys/proc.h> 55 #include <sys/vnode.h> 56 #include <sys/fcntl.h> 57 #include <sys/file.h> 58 #include <sys/mman.h> 59 #include <sys/conf.h> 60 #include <sys/vmmeter.h> 61 62 #include <miscfs/specfs/specdev.h> 63 64 #include <vm/vm.h> 65 #include <vm/vm_param.h> 66 #include <vm/vm_prot.h> 67 #include <vm/vm_inherit.h> 68 #include <sys/lock.h> 69 #include <vm/pmap.h> 70 #include <vm/vm_map.h> 71 #include <vm/vm_object.h> 72 #include <vm/vm_pager.h> 73 #include <vm/vm_pageout.h> 74 #include <vm/vm_extern.h> 75 #include <vm/vm_page.h> 76 77 #ifndef _SYS_SYSPROTO_H_ 78 struct sbrk_args { 79 int incr; 80 }; 81 #endif 82 83 /* ARGSUSED */ 84 int 85 sbrk(p, uap, retval) 86 struct proc *p; 87 struct sbrk_args *uap; 88 int *retval; 89 { 90 91 /* Not yet implemented */ 92 return (EOPNOTSUPP); 93 } 94 95 #ifndef _SYS_SYSPROTO_H_ 96 struct sstk_args { 97 int incr; 98 }; 99 #endif 100 101 /* ARGSUSED */ 102 int 103 sstk(p, uap, retval) 104 struct proc *p; 105 struct sstk_args *uap; 106 int *retval; 107 { 108 109 /* Not yet implemented */ 110 return (EOPNOTSUPP); 111 } 112 113 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 114 #ifndef _SYS_SYSPROTO_H_ 115 struct getpagesize_args { 116 int dummy; 117 }; 118 #endif 119 120 /* ARGSUSED */ 121 int 122 ogetpagesize(p, uap, retval) 123 struct proc *p; 124 struct getpagesize_args *uap; 125 int *retval; 126 { 127 128 *retval = PAGE_SIZE; 129 return (0); 130 } 131 #endif /* COMPAT_43 || COMPAT_SUNOS */ 132 133 134 /* 135 * Memory Map (mmap) system call. Note that the file offset 136 * and address are allowed to be NOT page aligned, though if 137 * the MAP_FIXED flag it set, both must have the same remainder 138 * modulo the PAGE_SIZE (POSIX 1003.1b). If the address is not 139 * page-aligned, the actual mapping starts at trunc_page(addr) 140 * and the return value is adjusted up by the page offset. 141 */ 142 #ifndef _SYS_SYSPROTO_H_ 143 struct mmap_args { 144 caddr_t addr; 145 size_t len; 146 int prot; 147 int flags; 148 int fd; 149 long pad; 150 off_t pos; 151 }; 152 #endif 153 154 int 155 mmap(p, uap, retval) 156 struct proc *p; 157 register struct mmap_args *uap; 158 int *retval; 159 { 160 register struct filedesc *fdp = p->p_fd; 161 register struct file *fp; 162 struct vnode *vp; 163 vm_offset_t addr; 164 vm_size_t size, pageoff; 165 vm_prot_t prot, maxprot; 166 caddr_t handle; 167 int flags, error; 168 off_t pos; 169 170 addr = (vm_offset_t) uap->addr; 171 size = uap->len; 172 prot = uap->prot & VM_PROT_ALL; 173 flags = uap->flags; 174 pos = uap->pos; 175 176 /* make sure mapping fits into numeric range etc */ 177 if ((pos + size > (vm_offset_t)-PAGE_SIZE) || 178 (ssize_t) uap->len < 0 || 179 ((flags & MAP_ANON) && uap->fd != -1)) 180 return (EINVAL); 181 182 /* 183 * Align the file position to a page boundary, 184 * and save its page offset component. 185 */ 186 pageoff = (pos & PAGE_MASK); 187 pos -= pageoff; 188 189 /* Adjust size for rounding (on both ends). */ 190 size += pageoff; /* low end... */ 191 size = (vm_size_t) round_page(size); /* hi end */ 192 193 /* 194 * Check for illegal addresses. Watch out for address wrap... Note 195 * that VM_*_ADDRESS are not constants due to casts (argh). 196 */ 197 if (flags & MAP_FIXED) { 198 /* 199 * The specified address must have the same remainder 200 * as the file offset taken modulo PAGE_SIZE, so it 201 * should be aligned after adjustment by pageoff. 202 */ 203 addr -= pageoff; 204 if (addr & PAGE_MASK) 205 return (EINVAL); 206 /* Address range must be all in user VM space. */ 207 if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS) 208 return (EINVAL); 209 #ifndef i386 210 if (VM_MIN_ADDRESS > 0 && addr < VM_MIN_ADDRESS) 211 return (EINVAL); 212 #endif 213 if (addr + size < addr) 214 return (EINVAL); 215 } 216 /* 217 * XXX for non-fixed mappings where no hint is provided or 218 * the hint would fall in the potential heap space, 219 * place it after the end of the largest possible heap. 220 * 221 * There should really be a pmap call to determine a reasonable 222 * location. 223 */ 224 else if (addr < round_page(p->p_vmspace->vm_daddr + MAXDSIZ)) 225 addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ); 226 227 if (flags & MAP_ANON) { 228 /* 229 * Mapping blank space is trivial. 230 */ 231 handle = NULL; 232 maxprot = VM_PROT_ALL; 233 pos = 0; 234 } else { 235 /* 236 * Mapping file, get fp for validation. Obtain vnode and make 237 * sure it is of appropriate type. 238 */ 239 if (((unsigned) uap->fd) >= fdp->fd_nfiles || 240 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 241 return (EBADF); 242 if (fp->f_type != DTYPE_VNODE) 243 return (EINVAL); 244 vp = (struct vnode *) fp->f_data; 245 if (vp->v_type != VREG && vp->v_type != VCHR) 246 return (EINVAL); 247 /* 248 * XXX hack to handle use of /dev/zero to map anon memory (ala 249 * SunOS). 250 */ 251 if (vp->v_type == VCHR && iszerodev(vp->v_rdev)) { 252 handle = NULL; 253 maxprot = VM_PROT_ALL; 254 flags |= MAP_ANON; 255 pos = 0; 256 } else { 257 /* 258 * Ensure that file and memory protections are 259 * compatible. Note that we only worry about 260 * writability if mapping is shared; in this case, 261 * current and max prot are dictated by the open file. 262 * XXX use the vnode instead? Problem is: what 263 * credentials do we use for determination? What if 264 * proc does a setuid? 265 */ 266 maxprot = VM_PROT_EXECUTE; /* ??? */ 267 if (fp->f_flag & FREAD) 268 maxprot |= VM_PROT_READ; 269 else if (prot & PROT_READ) 270 return (EACCES); 271 if (flags & MAP_SHARED) { 272 if (fp->f_flag & FWRITE) 273 maxprot |= VM_PROT_WRITE; 274 else if (prot & PROT_WRITE) 275 return (EACCES); 276 } else 277 maxprot |= VM_PROT_WRITE; 278 handle = (caddr_t) vp; 279 } 280 } 281 error = vm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot, 282 flags, handle, pos); 283 if (error == 0) 284 *retval = (int) (addr + pageoff); 285 return (error); 286 } 287 288 #ifdef COMPAT_43 289 #ifndef _SYS_SYSPROTO_H_ 290 struct ommap_args { 291 caddr_t addr; 292 int len; 293 int prot; 294 int flags; 295 int fd; 296 long pos; 297 }; 298 #endif 299 int 300 ommap(p, uap, retval) 301 struct proc *p; 302 register struct ommap_args *uap; 303 int *retval; 304 { 305 struct mmap_args nargs; 306 static const char cvtbsdprot[8] = { 307 0, 308 PROT_EXEC, 309 PROT_WRITE, 310 PROT_EXEC | PROT_WRITE, 311 PROT_READ, 312 PROT_EXEC | PROT_READ, 313 PROT_WRITE | PROT_READ, 314 PROT_EXEC | PROT_WRITE | PROT_READ, 315 }; 316 317 #define OMAP_ANON 0x0002 318 #define OMAP_COPY 0x0020 319 #define OMAP_SHARED 0x0010 320 #define OMAP_FIXED 0x0100 321 #define OMAP_INHERIT 0x0800 322 323 nargs.addr = uap->addr; 324 nargs.len = uap->len; 325 nargs.prot = cvtbsdprot[uap->prot & 0x7]; 326 nargs.flags = 0; 327 if (uap->flags & OMAP_ANON) 328 nargs.flags |= MAP_ANON; 329 if (uap->flags & OMAP_COPY) 330 nargs.flags |= MAP_COPY; 331 if (uap->flags & OMAP_SHARED) 332 nargs.flags |= MAP_SHARED; 333 else 334 nargs.flags |= MAP_PRIVATE; 335 if (uap->flags & OMAP_FIXED) 336 nargs.flags |= MAP_FIXED; 337 if (uap->flags & OMAP_INHERIT) 338 nargs.flags |= MAP_INHERIT; 339 nargs.fd = uap->fd; 340 nargs.pos = uap->pos; 341 return (mmap(p, &nargs, retval)); 342 } 343 #endif /* COMPAT_43 */ 344 345 346 #ifndef _SYS_SYSPROTO_H_ 347 struct msync_args { 348 caddr_t addr; 349 int len; 350 int flags; 351 }; 352 #endif 353 int 354 msync(p, uap, retval) 355 struct proc *p; 356 struct msync_args *uap; 357 int *retval; 358 { 359 vm_offset_t addr; 360 vm_size_t size, pageoff; 361 int flags; 362 vm_map_t map; 363 int rv; 364 365 addr = (vm_offset_t) uap->addr; 366 size = uap->len; 367 flags = uap->flags; 368 369 pageoff = (addr & PAGE_MASK); 370 addr -= pageoff; 371 size += pageoff; 372 size = (vm_size_t) round_page(size); 373 if (addr + size < addr) 374 return(EINVAL); 375 376 if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE)) 377 return (EINVAL); 378 379 map = &p->p_vmspace->vm_map; 380 381 /* 382 * XXX Gak! If size is zero we are supposed to sync "all modified 383 * pages with the region containing addr". Unfortunately, we don't 384 * really keep track of individual mmaps so we approximate by flushing 385 * the range of the map entry containing addr. This can be incorrect 386 * if the region splits or is coalesced with a neighbor. 387 */ 388 if (size == 0) { 389 vm_map_entry_t entry; 390 391 vm_map_lock_read(map); 392 rv = vm_map_lookup_entry(map, addr, &entry); 393 vm_map_unlock_read(map); 394 if (rv == FALSE) 395 return (EINVAL); 396 addr = entry->start; 397 size = entry->end - entry->start; 398 } 399 400 /* 401 * Clean the pages and interpret the return value. 402 */ 403 rv = vm_map_clean(map, addr, addr + size, (flags & MS_ASYNC) == 0, 404 (flags & MS_INVALIDATE) != 0); 405 406 switch (rv) { 407 case KERN_SUCCESS: 408 break; 409 case KERN_INVALID_ADDRESS: 410 return (EINVAL); /* Sun returns ENOMEM? */ 411 case KERN_FAILURE: 412 return (EIO); 413 default: 414 return (EINVAL); 415 } 416 417 return (0); 418 } 419 420 #ifndef _SYS_SYSPROTO_H_ 421 struct munmap_args { 422 caddr_t addr; 423 size_t len; 424 }; 425 #endif 426 int 427 munmap(p, uap, retval) 428 register struct proc *p; 429 register struct munmap_args *uap; 430 int *retval; 431 { 432 vm_offset_t addr; 433 vm_size_t size, pageoff; 434 vm_map_t map; 435 436 addr = (vm_offset_t) uap->addr; 437 size = uap->len; 438 439 pageoff = (addr & PAGE_MASK); 440 addr -= pageoff; 441 size += pageoff; 442 size = (vm_size_t) round_page(size); 443 if (addr + size < addr) 444 return(EINVAL); 445 446 if (size == 0) 447 return (0); 448 449 /* 450 * Check for illegal addresses. Watch out for address wrap... Note 451 * that VM_*_ADDRESS are not constants due to casts (argh). 452 */ 453 if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS) 454 return (EINVAL); 455 #ifndef i386 456 if (VM_MIN_ADDRESS > 0 && addr < VM_MIN_ADDRESS) 457 return (EINVAL); 458 #endif 459 map = &p->p_vmspace->vm_map; 460 /* 461 * Make sure entire range is allocated. 462 */ 463 if (!vm_map_check_protection(map, addr, addr + size, VM_PROT_NONE)) 464 return (EINVAL); 465 /* returns nothing but KERN_SUCCESS anyway */ 466 (void) vm_map_remove(map, addr, addr + size); 467 return (0); 468 } 469 470 void 471 munmapfd(p, fd) 472 struct proc *p; 473 int fd; 474 { 475 /* 476 * XXX should unmap any regions mapped to this file 477 */ 478 p->p_fd->fd_ofileflags[fd] &= ~UF_MAPPED; 479 } 480 481 #ifndef _SYS_SYSPROTO_H_ 482 struct mprotect_args { 483 caddr_t addr; 484 size_t len; 485 int prot; 486 }; 487 #endif 488 int 489 mprotect(p, uap, retval) 490 struct proc *p; 491 struct mprotect_args *uap; 492 int *retval; 493 { 494 vm_offset_t addr; 495 vm_size_t size, pageoff; 496 register vm_prot_t prot; 497 498 addr = (vm_offset_t) uap->addr; 499 size = uap->len; 500 prot = uap->prot & VM_PROT_ALL; 501 #if defined(VM_PROT_READ_IS_EXEC) 502 if (prot & VM_PROT_READ) 503 prot |= VM_PROT_EXECUTE; 504 #endif 505 506 pageoff = (addr & PAGE_MASK); 507 addr -= pageoff; 508 size += pageoff; 509 size = (vm_size_t) round_page(size); 510 if (addr + size < addr) 511 return(EINVAL); 512 513 switch (vm_map_protect(&p->p_vmspace->vm_map, addr, addr + size, prot, 514 FALSE)) { 515 case KERN_SUCCESS: 516 return (0); 517 case KERN_PROTECTION_FAILURE: 518 return (EACCES); 519 } 520 return (EINVAL); 521 } 522 523 #ifndef _SYS_SYSPROTO_H_ 524 struct minherit_args { 525 caddr_t addr; 526 size_t len; 527 int inherit; 528 }; 529 #endif 530 int 531 minherit(p, uap, retval) 532 struct proc *p; 533 struct minherit_args *uap; 534 int *retval; 535 { 536 vm_offset_t addr; 537 vm_size_t size, pageoff; 538 register vm_inherit_t inherit; 539 540 addr = (vm_offset_t)uap->addr; 541 size = uap->len; 542 inherit = uap->inherit; 543 544 pageoff = (addr & PAGE_MASK); 545 addr -= pageoff; 546 size += pageoff; 547 size = (vm_size_t) round_page(size); 548 if (addr + size < addr) 549 return(EINVAL); 550 551 switch (vm_map_inherit(&p->p_vmspace->vm_map, addr, addr+size, 552 inherit)) { 553 case KERN_SUCCESS: 554 return (0); 555 case KERN_PROTECTION_FAILURE: 556 return (EACCES); 557 } 558 return (EINVAL); 559 } 560 561 #ifndef _SYS_SYSPROTO_H_ 562 struct madvise_args { 563 caddr_t addr; 564 size_t len; 565 int behav; 566 }; 567 #endif 568 569 /* ARGSUSED */ 570 int 571 madvise(p, uap, retval) 572 struct proc *p; 573 struct madvise_args *uap; 574 int *retval; 575 { 576 vm_map_t map; 577 pmap_t pmap; 578 vm_offset_t start, end; 579 /* 580 * Check for illegal addresses. Watch out for address wrap... Note 581 * that VM_*_ADDRESS are not constants due to casts (argh). 582 */ 583 if (VM_MAXUSER_ADDRESS > 0 && 584 ((vm_offset_t) uap->addr + uap->len) > VM_MAXUSER_ADDRESS) 585 return (EINVAL); 586 #ifndef i386 587 if (VM_MIN_ADDRESS > 0 && uap->addr < VM_MIN_ADDRESS) 588 return (EINVAL); 589 #endif 590 if (((vm_offset_t) uap->addr + uap->len) < (vm_offset_t) uap->addr) 591 return (EINVAL); 592 593 /* 594 * Since this routine is only advisory, we default to conservative 595 * behavior. 596 */ 597 start = trunc_page((vm_offset_t) uap->addr); 598 end = round_page((vm_offset_t) uap->addr + uap->len); 599 600 map = &p->p_vmspace->vm_map; 601 pmap = &p->p_vmspace->vm_pmap; 602 603 vm_map_madvise(map, pmap, start, end, uap->behav); 604 605 return (0); 606 } 607 608 #ifndef _SYS_SYSPROTO_H_ 609 struct mincore_args { 610 caddr_t addr; 611 size_t len; 612 char *vec; 613 }; 614 #endif 615 616 /* ARGSUSED */ 617 int 618 mincore(p, uap, retval) 619 struct proc *p; 620 struct mincore_args *uap; 621 int *retval; 622 { 623 vm_offset_t addr, first_addr; 624 vm_offset_t end, cend; 625 pmap_t pmap; 626 vm_map_t map; 627 char *vec; 628 int error; 629 int vecindex, lastvecindex; 630 register vm_map_entry_t current; 631 vm_map_entry_t entry; 632 int mincoreinfo; 633 634 /* 635 * Make sure that the addresses presented are valid for user 636 * mode. 637 */ 638 first_addr = addr = trunc_page((vm_offset_t) uap->addr); 639 end = addr + (vm_size_t)round_page(uap->len); 640 if (VM_MAXUSER_ADDRESS > 0 && end > VM_MAXUSER_ADDRESS) 641 return (EINVAL); 642 if (end < addr) 643 return (EINVAL); 644 645 /* 646 * Address of byte vector 647 */ 648 vec = uap->vec; 649 650 map = &p->p_vmspace->vm_map; 651 pmap = &p->p_vmspace->vm_pmap; 652 653 vm_map_lock(map); 654 655 /* 656 * Not needed here 657 */ 658 #if 0 659 VM_MAP_RANGE_CHECK(map, addr, end); 660 #endif 661 662 if (!vm_map_lookup_entry(map, addr, &entry)) 663 entry = entry->next; 664 665 /* 666 * Do this on a map entry basis so that if the pages are not 667 * in the current processes address space, we can easily look 668 * up the pages elsewhere. 669 */ 670 lastvecindex = -1; 671 for(current = entry; 672 (current != &map->header) && (current->start < end); 673 current = current->next) { 674 675 /* 676 * ignore submaps (for now) or null objects 677 */ 678 if ((current->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) || 679 current->object.vm_object == NULL) 680 continue; 681 682 /* 683 * limit this scan to the current map entry and the 684 * limits for the mincore call 685 */ 686 if (addr < current->start) 687 addr = current->start; 688 cend = current->end; 689 if (cend > end) 690 cend = end; 691 692 /* 693 * scan this entry one page at a time 694 */ 695 while(addr < cend) { 696 /* 697 * Check pmap first, it is likely faster, also 698 * it can provide info as to whether we are the 699 * one referencing or modifying the page. 700 */ 701 mincoreinfo = pmap_mincore(pmap, addr); 702 if (!mincoreinfo) { 703 vm_pindex_t pindex; 704 vm_ooffset_t offset; 705 vm_page_t m; 706 /* 707 * calculate the page index into the object 708 */ 709 offset = current->offset + (addr - current->start); 710 pindex = OFF_TO_IDX(offset); 711 m = vm_page_lookup(current->object.vm_object, 712 pindex); 713 /* 714 * if the page is resident, then gather information about 715 * it. 716 */ 717 if (m) { 718 mincoreinfo = MINCORE_INCORE; 719 if (m->dirty || 720 pmap_is_modified(VM_PAGE_TO_PHYS(m))) 721 mincoreinfo |= MINCORE_MODIFIED_OTHER; 722 if ((m->flags & PG_REFERENCED) || 723 pmap_ts_referenced(VM_PAGE_TO_PHYS(m))) { 724 m->flags |= PG_REFERENCED; 725 mincoreinfo |= MINCORE_REFERENCED_OTHER; 726 } 727 } 728 } 729 730 /* 731 * calculate index into user supplied byte vector 732 */ 733 vecindex = OFF_TO_IDX(addr - first_addr); 734 735 /* 736 * If we have skipped map entries, we need to make sure that 737 * the byte vector is zeroed for those skipped entries. 738 */ 739 while((lastvecindex + 1) < vecindex) { 740 error = subyte( vec + lastvecindex, 0); 741 if (error) { 742 vm_map_unlock(map); 743 return (EFAULT); 744 } 745 ++lastvecindex; 746 } 747 748 /* 749 * Pass the page information to the user 750 */ 751 error = subyte( vec + vecindex, mincoreinfo); 752 if (error) { 753 vm_map_unlock(map); 754 return (EFAULT); 755 } 756 lastvecindex = vecindex; 757 addr += PAGE_SIZE; 758 } 759 } 760 761 /* 762 * Zero the last entries in the byte vector. 763 */ 764 vecindex = OFF_TO_IDX(end - first_addr); 765 while((lastvecindex + 1) < vecindex) { 766 error = subyte( vec + lastvecindex, 0); 767 if (error) { 768 vm_map_unlock(map); 769 return (EFAULT); 770 } 771 ++lastvecindex; 772 } 773 774 vm_map_unlock(map); 775 return (0); 776 } 777 778 #ifndef _SYS_SYSPROTO_H_ 779 struct mlock_args { 780 caddr_t addr; 781 size_t len; 782 }; 783 #endif 784 int 785 mlock(p, uap, retval) 786 struct proc *p; 787 struct mlock_args *uap; 788 int *retval; 789 { 790 vm_offset_t addr; 791 vm_size_t size, pageoff; 792 int error; 793 794 addr = (vm_offset_t) uap->addr; 795 size = uap->len; 796 797 pageoff = (addr & PAGE_MASK); 798 addr -= pageoff; 799 size += pageoff; 800 size = (vm_size_t) round_page(size); 801 802 /* disable wrap around */ 803 if (addr + size < addr) 804 return (EINVAL); 805 806 if (atop(size) + cnt.v_wire_count > vm_page_max_wired) 807 return (EAGAIN); 808 809 #ifdef pmap_wired_count 810 if (size + ptoa(pmap_wired_count(vm_map_pmap(&p->p_vmspace->vm_map))) > 811 p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur) 812 return (ENOMEM); 813 #else 814 error = suser(p->p_ucred, &p->p_acflag); 815 if (error) 816 return (error); 817 #endif 818 819 error = vm_map_user_pageable(&p->p_vmspace->vm_map, addr, addr + size, FALSE); 820 return (error == KERN_SUCCESS ? 0 : ENOMEM); 821 } 822 823 #ifndef _SYS_SYSPROTO_H_ 824 struct mlockall_args { 825 int how; 826 }; 827 #endif 828 829 int 830 mlockall(p, uap, retval) 831 struct proc *p; 832 struct mlockall_args *uap; 833 int *retval; 834 { 835 return 0; 836 } 837 838 #ifndef _SYS_SYSPROTO_H_ 839 struct mlockall_args { 840 int how; 841 }; 842 #endif 843 844 int 845 munlockall(p, uap, retval) 846 struct proc *p; 847 struct munlockall_args *uap; 848 int *retval; 849 { 850 return 0; 851 } 852 853 #ifndef _SYS_SYSPROTO_H_ 854 struct munlock_args { 855 caddr_t addr; 856 size_t len; 857 }; 858 #endif 859 int 860 munlock(p, uap, retval) 861 struct proc *p; 862 struct munlock_args *uap; 863 int *retval; 864 { 865 vm_offset_t addr; 866 vm_size_t size, pageoff; 867 int error; 868 869 addr = (vm_offset_t) uap->addr; 870 size = uap->len; 871 872 pageoff = (addr & PAGE_MASK); 873 addr -= pageoff; 874 size += pageoff; 875 size = (vm_size_t) round_page(size); 876 877 /* disable wrap around */ 878 if (addr + size < addr) 879 return (EINVAL); 880 881 #ifndef pmap_wired_count 882 error = suser(p->p_ucred, &p->p_acflag); 883 if (error) 884 return (error); 885 #endif 886 887 error = vm_map_user_pageable(&p->p_vmspace->vm_map, addr, addr + size, TRUE); 888 return (error == KERN_SUCCESS ? 0 : ENOMEM); 889 } 890 891 /* 892 * Internal version of mmap. 893 * Currently used by mmap, exec, and sys5 shared memory. 894 * Handle is either a vnode pointer or NULL for MAP_ANON. 895 */ 896 int 897 vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, 898 vm_prot_t maxprot, int flags, 899 caddr_t handle, /* XXX should be vp */ 900 vm_ooffset_t foff) 901 { 902 boolean_t fitit; 903 vm_object_t object; 904 struct vnode *vp = NULL; 905 objtype_t type; 906 int rv = KERN_SUCCESS; 907 vm_ooffset_t objsize; 908 int docow; 909 struct proc *p = curproc; 910 911 if (size == 0) 912 return (0); 913 914 objsize = size = round_page(size); 915 916 /* 917 * We currently can only deal with page aligned file offsets. 918 * The check is here rather than in the syscall because the 919 * kernel calls this function internally for other mmaping 920 * operations (such as in exec) and non-aligned offsets will 921 * cause pmap inconsistencies...so we want to be sure to 922 * disallow this in all cases. 923 */ 924 if (foff & PAGE_MASK) 925 return (EINVAL); 926 927 if ((flags & MAP_FIXED) == 0) { 928 fitit = TRUE; 929 *addr = round_page(*addr); 930 } else { 931 if (*addr != trunc_page(*addr)) 932 return (EINVAL); 933 fitit = FALSE; 934 (void) vm_map_remove(map, *addr, *addr + size); 935 } 936 937 /* 938 * Lookup/allocate object. 939 */ 940 if (flags & MAP_ANON) { 941 type = OBJT_DEFAULT; 942 /* 943 * Unnamed anonymous regions always start at 0. 944 */ 945 if (handle == 0) 946 foff = 0; 947 } else { 948 vp = (struct vnode *) handle; 949 if (vp->v_type == VCHR) { 950 type = OBJT_DEVICE; 951 handle = (caddr_t) vp->v_rdev; 952 } else { 953 struct vattr vat; 954 int error; 955 956 error = VOP_GETATTR(vp, &vat, p->p_ucred, p); 957 if (error) 958 return (error); 959 objsize = round_page(vat.va_size); 960 type = OBJT_VNODE; 961 } 962 } 963 964 if (handle == NULL) { 965 object = NULL; 966 } else { 967 object = vm_pager_allocate(type, 968 handle, OFF_TO_IDX(objsize), prot, foff); 969 if (object == NULL) 970 return (type == OBJT_DEVICE ? EINVAL : ENOMEM); 971 } 972 973 /* 974 * Force device mappings to be shared. 975 */ 976 if (type == OBJT_DEVICE) { 977 flags &= ~(MAP_PRIVATE|MAP_COPY); 978 flags |= MAP_SHARED; 979 } 980 981 docow = 0; 982 if ((flags & (MAP_ANON|MAP_SHARED)) == 0) { 983 docow = MAP_COPY_ON_WRITE | MAP_COPY_NEEDED; 984 } 985 986 #if defined(VM_PROT_READ_IS_EXEC) 987 if (prot & VM_PROT_READ) 988 prot |= VM_PROT_EXECUTE; 989 990 if (maxprot & VM_PROT_READ) 991 maxprot |= VM_PROT_EXECUTE; 992 #endif 993 994 if (fitit) { 995 *addr = pmap_addr_hint(object, *addr, size); 996 } 997 998 rv = vm_map_find(map, object, foff, addr, size, fitit, 999 prot, maxprot, docow); 1000 1001 if (rv != KERN_SUCCESS) { 1002 /* 1003 * Lose the object reference. Will destroy the 1004 * object if it's an unnamed anonymous mapping 1005 * or named anonymous without other references. 1006 */ 1007 vm_object_deallocate(object); 1008 goto out; 1009 } 1010 1011 /* 1012 * "Pre-fault" resident pages. 1013 */ 1014 if ((map->pmap != NULL) && (object != NULL)) { 1015 pmap_object_init_pt(map->pmap, *addr, 1016 object, (vm_pindex_t) OFF_TO_IDX(foff), size, 1); 1017 } 1018 1019 /* 1020 * Shared memory is also shared with children. 1021 */ 1022 if (flags & (MAP_SHARED|MAP_INHERIT)) { 1023 rv = vm_map_inherit(map, *addr, *addr + size, VM_INHERIT_SHARE); 1024 if (rv != KERN_SUCCESS) { 1025 (void) vm_map_remove(map, *addr, *addr + size); 1026 goto out; 1027 } 1028 } 1029 out: 1030 switch (rv) { 1031 case KERN_SUCCESS: 1032 return (0); 1033 case KERN_INVALID_ADDRESS: 1034 case KERN_NO_SPACE: 1035 return (ENOMEM); 1036 case KERN_PROTECTION_FAILURE: 1037 return (EACCES); 1038 default: 1039 return (EINVAL); 1040 } 1041 } 1042