Print this page
use NULL dump segop as a shorthand for no-op
Instead of forcing every segment driver to implement a dummy function that
does nothing, handle NULL dump segop function pointer as a no-op shorthand.
const-ify make segment ops structures
There is no reason to keep the segment ops structures writable.
use NULL setpagesize segop as a shorthand for ENOTSUP
Instead of forcing every segment driver to implement a dummp function to
return (hopefully) ENOTSUP, handle NULL setpagesize segop function pointer
as "return ENOTSUP" shorthand.
use NULL getmemid segop as a shorthand for ENODEV
Instead of forcing every segment driver to implement a dummy function to
return (hopefully) ENODEV, handle NULL getmemid segop function pointer as
"return ENODEV" shorthand.
segop_getpolicy already checks for a NULL op
no need for bad-op segment op functions
The segment drivers have a number of bad-op functions that simply panic.
Keeping the function pointer NULL will accomplish the same thing in most
cases.  In other cases, keeping the function pointer NULL will result in
proper error code being returned.
use C99 initializers in segment ops structures
remove whole-process swapping
Long before Unix supported paging, it used process swapping to reclaim
memory.  The code is there and in theory it runs when we get *extremely* low
on memory.  In practice, it never runs since the definition of low-on-memory
is antiquated. (XXX: define what antiquated means)
You can check the number of swapout/swapin events with kstats:
$ kstat -p ::vm:swapin ::vm:swapout


  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  27 /* All Rights Reserved */
  28 
  29 /*
  30  * Portions of this source code were derived from Berkeley 4.3 BSD
  31  * under license from the Regents of the University of California.
  32  */
  33 
  34 #pragma ident   "%Z%%M% %I%     %E% SMI"
  35 
  36 /*
  37  * VM - segment for non-faulting loads.
  38  */
  39 
  40 #include <sys/types.h>
  41 #include <sys/t_lock.h>
  42 #include <sys/param.h>
  43 #include <sys/mman.h>
  44 #include <sys/errno.h>
  45 #include <sys/kmem.h>
  46 #include <sys/cmn_err.h>
  47 #include <sys/vnode.h>
  48 #include <sys/proc.h>
  49 #include <sys/conf.h>
  50 #include <sys/debug.h>
  51 #include <sys/archsystm.h>
  52 #include <sys/lgrp.h>
  53 
  54 #include <vm/page.h>
  55 #include <vm/hat.h>
  56 #include <vm/as.h>
  57 #include <vm/seg.h>
  58 #include <vm/vpage.h>
  59 
  60 /*
  61  * Private seg op routines.
  62  */
  63 static int      segnf_dup(struct seg *seg, struct seg *newseg);
  64 static int      segnf_unmap(struct seg *seg, caddr_t addr, size_t len);
  65 static void     segnf_free(struct seg *seg);
  66 static faultcode_t segnf_nomap(void);
  67 static int      segnf_setprot(struct seg *seg, caddr_t addr,
  68                     size_t len, uint_t prot);
  69 static int      segnf_checkprot(struct seg *seg, caddr_t addr,
  70                     size_t len, uint_t prot);
  71 static void     segnf_badop(void);
  72 static int      segnf_nop(void);
  73 static int      segnf_getprot(struct seg *seg, caddr_t addr,
  74                     size_t len, uint_t *protv);
  75 static u_offset_t segnf_getoffset(struct seg *seg, caddr_t addr);
  76 static int      segnf_gettype(struct seg *seg, caddr_t addr);
  77 static int      segnf_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp);
  78 static void     segnf_dump(struct seg *seg);
  79 static int      segnf_pagelock(struct seg *seg, caddr_t addr, size_t len,
  80                     struct page ***ppp, enum lock_type type, enum seg_rw rw);
  81 static int      segnf_setpagesize(struct seg *seg, caddr_t addr, size_t len,
  82                     uint_t szc);
  83 static int      segnf_getmemid(struct seg *seg, caddr_t addr, memid_t *memidp);
  84 static lgrp_mem_policy_info_t   *segnf_getpolicy(struct seg *seg,
  85     caddr_t addr);
  86 
  87 
  88 struct seg_ops segnf_ops = {
  89         segnf_dup,
  90         segnf_unmap,
  91         segnf_free,
  92         (faultcode_t (*)(struct hat *, struct seg *, caddr_t, size_t,
  93             enum fault_type, enum seg_rw))
  94                 segnf_nomap,            /* fault */
  95         (faultcode_t (*)(struct seg *, caddr_t))
  96                 segnf_nomap,            /* faulta */
  97         segnf_setprot,
  98         segnf_checkprot,
  99         (int (*)())segnf_badop,         /* kluster */
 100         (size_t (*)(struct seg *))NULL, /* swapout */
 101         (int (*)(struct seg *, caddr_t, size_t, int, uint_t))
 102                 segnf_nop,              /* sync */
 103         (size_t (*)(struct seg *, caddr_t, size_t, char *))
 104                 segnf_nop,              /* incore */
 105         (int (*)(struct seg *, caddr_t, size_t, int, int, ulong_t *, size_t))
 106                 segnf_nop,              /* lockop */
 107         segnf_getprot,
 108         segnf_getoffset,
 109         segnf_gettype,
 110         segnf_getvp,
 111         (int (*)(struct seg *, caddr_t, size_t, uint_t))
 112                 segnf_nop,              /* advise */
 113         segnf_dump,
 114         segnf_pagelock,
 115         segnf_setpagesize,
 116         segnf_getmemid,
 117         segnf_getpolicy,
 118 };
 119 
 120 /*
 121  * vnode and page for the page of zeros we use for the nf mappings.
 122  */
 123 static kmutex_t segnf_lock;
 124 static struct vnode nfvp;
 125 static struct page **nfpp;
 126 
 127 #define addr_to_vcolor(addr)                                            \
 128         (shm_alignment) ?                                               \
 129         ((int)(((uintptr_t)(addr) & (shm_alignment - 1)) >> PAGESHIFT)) : 0
 130 
 131 /*
 132  * We try to limit the number of Non-fault segments created.
 133  * Non fault segments are created to optimize sparc V9 code which uses
 134  * the sparc nonfaulting load ASI (ASI_PRIMARY_NOFAULT).
 135  *
 136  * There are several reasons why creating too many non-fault segments
 137  * could cause problems.


 389 
 390 /* ARGSUSED */
 391 static int
 392 segnf_setprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot)
 393 {
 394         ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
 395         return (EACCES);
 396 }
 397 
 398 /* ARGSUSED */
 399 static int
 400 segnf_checkprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot)
 401 {
 402         uint_t sprot;
 403         ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
 404 
 405         sprot = seg->s_as == &kas ?  PROT_READ : PROT_READ|PROT_USER;
 406         return ((prot & sprot) == prot ? 0 : EACCES);
 407 }
 408 
 409 static void
 410 segnf_badop(void)
 411 {
 412         panic("segnf_badop");
 413         /*NOTREACHED*/
 414 }
 415 
 416 static int
 417 segnf_nop(void)
 418 {
 419         return (0);
 420 }
 421 
 422 static int
 423 segnf_getprot(struct seg *seg, caddr_t addr, size_t len, uint_t *protv)
 424 {
 425         size_t pgno = seg_page(seg, addr + len) - seg_page(seg, addr) + 1;
 426         size_t p;
 427         ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
 428 
 429         for (p = 0; p < pgno; ++p)
 430                 protv[p] = PROT_READ;
 431         return (0);
 432 }
 433 
 434 /* ARGSUSED */
 435 static u_offset_t


 442 
 443 /* ARGSUSED */
 444 static int
 445 segnf_gettype(struct seg *seg, caddr_t addr)
 446 {
 447         ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
 448 
 449         return (MAP_SHARED);
 450 }
 451 
 452 /* ARGSUSED */
 453 static int
 454 segnf_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp)
 455 {
 456         ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
 457 
 458         *vpp = &nfvp;
 459         return (0);
 460 }
 461 
 462 /*
 463  * segnf pages are not dumped, so we just return
 464  */
 465 /* ARGSUSED */
 466 static void
 467 segnf_dump(struct seg *seg)
 468 {}
 469 
 470 /*ARGSUSED*/
 471 static int
 472 segnf_pagelock(struct seg *seg, caddr_t addr, size_t len,
 473     struct page ***ppp, enum lock_type type, enum seg_rw rw)
 474 {
 475         return (ENOTSUP);
 476 }
 477 
 478 /*ARGSUSED*/
 479 static int
 480 segnf_setpagesize(struct seg *seg, caddr_t addr, size_t len,
 481     uint_t szc)
 482 {
 483         return (ENOTSUP);
 484 }
 485 
 486 /*ARGSUSED*/
 487 static int
 488 segnf_getmemid(struct seg *seg, caddr_t addr, memid_t *memidp)
 489 {
 490         return (ENODEV);
 491 }
 492 
 493 /*ARGSUSED*/
 494 static lgrp_mem_policy_info_t *
 495 segnf_getpolicy(struct seg *seg, caddr_t addr)
 496 {
 497         return (NULL);
 498 }


  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  27 /* All Rights Reserved */
  28 
  29 /*
  30  * Portions of this source code were derived from Berkeley 4.3 BSD
  31  * under license from the Regents of the University of California.
  32  */
  33 


  34 /*
  35  * VM - segment for non-faulting loads.
  36  */
  37 
  38 #include <sys/types.h>
  39 #include <sys/t_lock.h>
  40 #include <sys/param.h>
  41 #include <sys/mman.h>
  42 #include <sys/errno.h>
  43 #include <sys/kmem.h>
  44 #include <sys/cmn_err.h>
  45 #include <sys/vnode.h>
  46 #include <sys/proc.h>
  47 #include <sys/conf.h>
  48 #include <sys/debug.h>
  49 #include <sys/archsystm.h>
  50 #include <sys/lgrp.h>
  51 
  52 #include <vm/page.h>
  53 #include <vm/hat.h>
  54 #include <vm/as.h>
  55 #include <vm/seg.h>
  56 #include <vm/vpage.h>
  57 
  58 /*
  59  * Private seg op routines.
  60  */
  61 static int      segnf_dup(struct seg *seg, struct seg *newseg);
  62 static int      segnf_unmap(struct seg *seg, caddr_t addr, size_t len);
  63 static void     segnf_free(struct seg *seg);
  64 static faultcode_t segnf_nomap(void);
  65 static int      segnf_setprot(struct seg *seg, caddr_t addr,
  66                     size_t len, uint_t prot);
  67 static int      segnf_checkprot(struct seg *seg, caddr_t addr,
  68                     size_t len, uint_t prot);

  69 static int      segnf_nop(void);
  70 static int      segnf_getprot(struct seg *seg, caddr_t addr,
  71                     size_t len, uint_t *protv);
  72 static u_offset_t segnf_getoffset(struct seg *seg, caddr_t addr);
  73 static int      segnf_gettype(struct seg *seg, caddr_t addr);
  74 static int      segnf_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp);

  75 static int      segnf_pagelock(struct seg *seg, caddr_t addr, size_t len,
  76                     struct page ***ppp, enum lock_type type, enum seg_rw rw);
  77 
  78 
  79 const struct seg_ops segnf_ops = {
  80         .dup            = segnf_dup,
  81         .unmap          = segnf_unmap,
  82         .free           = segnf_free,
  83         .fault          = (faultcode_t (*)(struct hat *, struct seg *, caddr_t,
  84             size_t, enum fault_type, enum seg_rw))segnf_nomap,
  85         .faulta         = (faultcode_t (*)(struct seg *, caddr_t)) segnf_nomap,
  86         .setprot        = segnf_setprot,
  87         .checkprot      = segnf_checkprot,
  88         .sync           = (int (*)(struct seg *, caddr_t, size_t, int, uint_t))
  89                 segnf_nop,
  90         .incore         = (size_t (*)(struct seg *, caddr_t, size_t, char *))
  91                 segnf_nop,
  92         .lockop         = (int (*)(struct seg *, caddr_t, size_t, int, int,
  93             ulong_t *, size_t))segnf_nop,
  94         .getprot        = segnf_getprot,
  95         .getoffset      = segnf_getoffset,
  96         .gettype        = segnf_gettype,
  97         .getvp          = segnf_getvp,
  98         .advise         = (int (*)(struct seg *, caddr_t, size_t, uint_t))
  99                 segnf_nop,
 100         .pagelock       = segnf_pagelock,













 101 };
 102 
 103 /*
 104  * vnode and page for the page of zeros we use for the nf mappings.
 105  */
 106 static kmutex_t segnf_lock;
 107 static struct vnode nfvp;
 108 static struct page **nfpp;
 109 
 110 #define addr_to_vcolor(addr)                                            \
 111         (shm_alignment) ?                                               \
 112         ((int)(((uintptr_t)(addr) & (shm_alignment - 1)) >> PAGESHIFT)) : 0
 113 
 114 /*
 115  * We try to limit the number of Non-fault segments created.
 116  * Non fault segments are created to optimize sparc V9 code which uses
 117  * the sparc nonfaulting load ASI (ASI_PRIMARY_NOFAULT).
 118  *
 119  * There are several reasons why creating too many non-fault segments
 120  * could cause problems.


 372 
 373 /* ARGSUSED */
 374 static int
 375 segnf_setprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot)
 376 {
 377         ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
 378         return (EACCES);
 379 }
 380 
 381 /* ARGSUSED */
 382 static int
 383 segnf_checkprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot)
 384 {
 385         uint_t sprot;
 386         ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
 387 
 388         sprot = seg->s_as == &kas ?  PROT_READ : PROT_READ|PROT_USER;
 389         return ((prot & sprot) == prot ? 0 : EACCES);
 390 }
 391 







 392 static int
 393 segnf_nop(void)
 394 {
 395         return (0);
 396 }
 397 
 398 static int
 399 segnf_getprot(struct seg *seg, caddr_t addr, size_t len, uint_t *protv)
 400 {
 401         size_t pgno = seg_page(seg, addr + len) - seg_page(seg, addr) + 1;
 402         size_t p;
 403         ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
 404 
 405         for (p = 0; p < pgno; ++p)
 406                 protv[p] = PROT_READ;
 407         return (0);
 408 }
 409 
 410 /* ARGSUSED */
 411 static u_offset_t


 418 
 419 /* ARGSUSED */
 420 static int
 421 segnf_gettype(struct seg *seg, caddr_t addr)
 422 {
 423         ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
 424 
 425         return (MAP_SHARED);
 426 }
 427 
 428 /* ARGSUSED */
 429 static int
 430 segnf_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp)
 431 {
 432         ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
 433 
 434         *vpp = &nfvp;
 435         return (0);
 436 }
 437 








 438 /*ARGSUSED*/
 439 static int
 440 segnf_pagelock(struct seg *seg, caddr_t addr, size_t len,
 441     struct page ***ppp, enum lock_type type, enum seg_rw rw)
 442 {
 443         return (ENOTSUP);






















 444 }