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.
segspt_ops can be static
There is nothing that needs access to this structure outside of the spt
segment driver itself.
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 capable segop as a shorthand for no-capabilities
Instead of forcing every segment driver to implement a dummy "return 0"
function, handle NULL capable segop function pointer as "no copabilities
supported" shorthand.
seg_inherit_notsup is redundant since segop_inherit checks for NULL properly
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
remove xhat
The xhat infrastructure was added to support hardware such as the zulu
graphics card - hardware which had on-board MMUs.  The VM used the xhat code
to keep the CPU's and Zulu's page tables in-sync.  Since the only xhat user
was zulu (which is gone), we can safely remove it simplifying the whole VM
subsystem.
Assorted notes:
- AS_BUSY flag was used solely by xhat


  59 
  60 /*
  61  * segspt_minfree is the memory left for system after ISM
  62  * locked its pages; it is set up to 5% of availrmem in
  63  * sptcreate when ISM is created.  ISM should not use more
  64  * than ~90% of availrmem; if it does, then the performance
  65  * of the system may decrease. Machines with large memories may
  66  * be able to use up more memory for ISM so we set the default
  67  * segspt_minfree to 5% (which gives ISM max 95% of availrmem.
  68  * If somebody wants even more memory for ISM (risking hanging
  69  * the system) they can patch the segspt_minfree to smaller number.
  70  */
  71 pgcnt_t segspt_minfree = 0;
  72 
  73 static int segspt_create(struct seg *seg, caddr_t argsp);
  74 static int segspt_unmap(struct seg *seg, caddr_t raddr, size_t ssize);
  75 static void segspt_free(struct seg *seg);
  76 static void segspt_free_pages(struct seg *seg, caddr_t addr, size_t len);
  77 static lgrp_mem_policy_info_t *segspt_getpolicy(struct seg *seg, caddr_t addr);
  78 
  79 static void
  80 segspt_badop()
  81 {
  82         panic("segspt_badop called");
  83         /*NOTREACHED*/
  84 }
  85 
  86 #define SEGSPT_BADOP(t) (t(*)())segspt_badop
  87 
  88 struct seg_ops segspt_ops = {
  89         SEGSPT_BADOP(int),              /* dup */
  90         segspt_unmap,
  91         segspt_free,
  92         SEGSPT_BADOP(int),              /* fault */
  93         SEGSPT_BADOP(faultcode_t),      /* faulta */
  94         SEGSPT_BADOP(int),              /* setprot */
  95         SEGSPT_BADOP(int),              /* checkprot */
  96         SEGSPT_BADOP(int),              /* kluster */
  97         SEGSPT_BADOP(size_t),           /* swapout */
  98         SEGSPT_BADOP(int),              /* sync */
  99         SEGSPT_BADOP(size_t),           /* incore */
 100         SEGSPT_BADOP(int),              /* lockop */
 101         SEGSPT_BADOP(int),              /* getprot */
 102         SEGSPT_BADOP(u_offset_t),       /* getoffset */
 103         SEGSPT_BADOP(int),              /* gettype */
 104         SEGSPT_BADOP(int),              /* getvp */
 105         SEGSPT_BADOP(int),              /* advise */
 106         SEGSPT_BADOP(void),             /* dump */
 107         SEGSPT_BADOP(int),              /* pagelock */
 108         SEGSPT_BADOP(int),              /* setpgsz */
 109         SEGSPT_BADOP(int),              /* getmemid */
 110         segspt_getpolicy,               /* getpolicy */
 111         SEGSPT_BADOP(int),              /* capable */
 112         seg_inherit_notsup              /* inherit */
 113 };
 114 
 115 static int segspt_shmdup(struct seg *seg, struct seg *newseg);
 116 static int segspt_shmunmap(struct seg *seg, caddr_t raddr, size_t ssize);
 117 static void segspt_shmfree(struct seg *seg);
 118 static faultcode_t segspt_shmfault(struct hat *hat, struct seg *seg,
 119                 caddr_t addr, size_t len, enum fault_type type, enum seg_rw rw);
 120 static faultcode_t segspt_shmfaulta(struct seg *seg, caddr_t addr);
 121 static int segspt_shmsetprot(register struct seg *seg, register caddr_t addr,
 122                         register size_t len, register uint_t prot);
 123 static int segspt_shmcheckprot(struct seg *seg, caddr_t addr, size_t size,
 124                         uint_t prot);
 125 static int      segspt_shmkluster(struct seg *seg, caddr_t addr, ssize_t delta);
 126 static size_t   segspt_shmswapout(struct seg *seg);
 127 static size_t segspt_shmincore(struct seg *seg, caddr_t addr, size_t len,
 128                         register char *vec);
 129 static int segspt_shmsync(struct seg *seg, register caddr_t addr, size_t len,
 130                         int attr, uint_t flags);
 131 static int segspt_shmlockop(struct seg *seg, caddr_t addr, size_t len,
 132                         int attr, int op, ulong_t *lockmap, size_t pos);
 133 static int segspt_shmgetprot(struct seg *seg, caddr_t addr, size_t len,
 134                         uint_t *protv);
 135 static u_offset_t segspt_shmgetoffset(struct seg *seg, caddr_t addr);
 136 static int segspt_shmgettype(struct seg *seg, caddr_t addr);
 137 static int segspt_shmgetvp(struct seg *seg, caddr_t addr, struct vnode **vpp);
 138 static int segspt_shmadvise(struct seg *seg, caddr_t addr, size_t len,
 139                         uint_t behav);
 140 static void segspt_shmdump(struct seg *seg);
 141 static int segspt_shmpagelock(struct seg *, caddr_t, size_t,
 142                         struct page ***, enum lock_type, enum seg_rw);
 143 static int segspt_shmsetpgsz(struct seg *, caddr_t, size_t, uint_t);
 144 static int segspt_shmgetmemid(struct seg *, caddr_t, memid_t *);
 145 static lgrp_mem_policy_info_t *segspt_shmgetpolicy(struct seg *, caddr_t);
 146 static int segspt_shmcapable(struct seg *, segcapability_t);
 147 
 148 struct seg_ops segspt_shmops = {
 149         segspt_shmdup,
 150         segspt_shmunmap,
 151         segspt_shmfree,
 152         segspt_shmfault,
 153         segspt_shmfaulta,
 154         segspt_shmsetprot,
 155         segspt_shmcheckprot,
 156         segspt_shmkluster,
 157         segspt_shmswapout,
 158         segspt_shmsync,
 159         segspt_shmincore,
 160         segspt_shmlockop,
 161         segspt_shmgetprot,
 162         segspt_shmgetoffset,
 163         segspt_shmgettype,
 164         segspt_shmgetvp,
 165         segspt_shmadvise,       /* advise */
 166         segspt_shmdump,
 167         segspt_shmpagelock,
 168         segspt_shmsetpgsz,
 169         segspt_shmgetmemid,
 170         segspt_shmgetpolicy,
 171         segspt_shmcapable,
 172         seg_inherit_notsup
 173 };
 174 
 175 static void segspt_purge(struct seg *seg);
 176 static int segspt_reclaim(void *, caddr_t, size_t, struct page **,
 177                 enum seg_rw, int);
 178 static int spt_anon_getpages(struct seg *seg, caddr_t addr, size_t len,
 179                 page_t **ppa);
 180 
 181 
 182 
 183 /*ARGSUSED*/
 184 int
 185 sptcreate(size_t size, struct seg **sptseg, struct anon_map *amp,
 186         uint_t prot, uint_t flags, uint_t share_szc)
 187 {
 188         int     err;
 189         struct  as      *newas;
 190         struct  segspt_crargs sptcargs;
 191 
 192 #ifdef DEBUG


1907                                 atomic_add_long((ulong_t *)(
1908                                     &(shmd->shm_softlockcnt)), -npages);
1909                         }
1910                         goto dism_err;
1911                 }
1912                 AS_LOCK_ENTER(sptseg->s_as, &sptseg->s_as->a_lock, RW_READER);
1913                 a = segspt_addr;
1914                 pidx = 0;
1915                 if (type == F_SOFTLOCK) {
1916 
1917                         /*
1918                          * Load up the translation keeping it
1919                          * locked and don't unlock the page.
1920                          */
1921                         for (; pidx < npages; a += pgsz, pidx += pgcnt) {
1922                                 hat_memload_array(sptseg->s_as->a_hat,
1923                                     a, pgsz, &ppa[pidx], sptd->spt_prot,
1924                                     HAT_LOAD_LOCK | HAT_LOAD_SHARE);
1925                         }
1926                 } else {
1927                         if (hat == seg->s_as->a_hat) {
1928 
1929                                 /*
1930                                  * Migrate pages marked for migration
1931                                  */
1932                                 if (lgrp_optimizations())
1933                                         page_migrate(seg, shm_addr, ppa,
1934                                             npages);
1935 
1936                                 /* CPU HAT */
1937                                 for (; pidx < npages;
1938                                     a += pgsz, pidx += pgcnt) {
1939                                         hat_memload_array(sptseg->s_as->a_hat,
1940                                             a, pgsz, &ppa[pidx],
1941                                             sptd->spt_prot,
1942                                             HAT_LOAD_SHARE);
1943                                 }
1944                         } else {
1945                                 /* XHAT. Pass real address */
1946                                 hat_memload_array(hat, shm_addr,
1947                                     size, ppa, sptd->spt_prot, HAT_LOAD_SHARE);
1948                         }
1949 
1950                         /*
1951                          * And now drop the SE_SHARED lock(s).
1952                          */
1953                         if (dyn_ism_unmap) {
1954                                 for (i = 0; i < npages; i++) {
1955                                         page_unlock(ppa[i]);
1956                                 }
1957                         }
1958                 }
1959 
1960                 if (!dyn_ism_unmap) {
1961                         if (hat_share(seg->s_as->a_hat, shm_addr,
1962                             curspt->a_hat, segspt_addr, ptob(npages),
1963                             seg->s_szc) != 0) {
1964                                 panic("hat_share err in DISM fault");
1965                                 /* NOTREACHED */
1966                         }
1967                         if (type == F_INVAL) {
1968                                 for (i = 0; i < npages; i++) {


2167                  * We are already holding the as->a_lock on the user's
2168                  * real segment, but we need to hold the a_lock on the
2169                  * underlying dummy as. This is mostly to satisfy the
2170                  * underlying HAT layer.
2171                  */
2172                 AS_LOCK_ENTER(sptseg->s_as, &sptseg->s_as->a_lock, RW_READER);
2173                 a = sptseg_addr;
2174                 pidx = 0;
2175                 if (type == F_SOFTLOCK) {
2176                         /*
2177                          * Load up the translation keeping it
2178                          * locked and don't unlock the page.
2179                          */
2180                         for (; pidx < npages; a += pgsz, pidx += pgcnt) {
2181                                 sz = MIN(pgsz, ptob(npages - pidx));
2182                                 hat_memload_array(sptseg->s_as->a_hat, a,
2183                                     sz, &ppa[pidx], sptd->spt_prot,
2184                                     HAT_LOAD_LOCK | HAT_LOAD_SHARE);
2185                         }
2186                 } else {
2187                         if (hat == seg->s_as->a_hat) {
2188 
2189                                 /*
2190                                  * Migrate pages marked for migration.
2191                                  */
2192                                 if (lgrp_optimizations())
2193                                         page_migrate(seg, shm_addr, ppa,
2194                                             npages);
2195 
2196                                 /* CPU HAT */
2197                                 for (; pidx < npages;
2198                                     a += pgsz, pidx += pgcnt) {
2199                                         sz = MIN(pgsz, ptob(npages - pidx));
2200                                         hat_memload_array(sptseg->s_as->a_hat,
2201                                             a, sz, &ppa[pidx],
2202                                             sptd->spt_prot, HAT_LOAD_SHARE);
2203                                 }
2204                         } else {
2205                                 /* XHAT. Pass real address */
2206                                 hat_memload_array(hat, shm_addr,
2207                                     ptob(npages), ppa, sptd->spt_prot,
2208                                     HAT_LOAD_SHARE);
2209                         }
2210 
2211                         /*
2212                          * And now drop the SE_SHARED lock(s).
2213                          */
2214                         for (i = 0; i < npages; i++)
2215                                 page_unlock(ppa[i]);
2216                 }
2217                 AS_LOCK_EXIT(sptseg->s_as, &sptseg->s_as->a_lock);
2218 
2219                 kmem_free(ppa, sizeof (page_t *) * npages);
2220                 return (0);
2221         case F_SOFTUNLOCK:
2222 
2223                 /*
2224                  * This is a bit ugly, we pass in the real seg pointer,
2225                  * but the sptseg_addr is the virtual address within the
2226                  * dummy seg.
2227                  */
2228                 segspt_softunlock(seg, sptseg_addr, ptob(npages), rw);
2229                 return (0);


2247                 cmn_err(CE_WARN, "segspt_shmfault default type?");
2248 #endif
2249                 return (FC_NOMAP);
2250         }
2251 }
2252 
2253 /*ARGSUSED*/
2254 static faultcode_t
2255 segspt_shmfaulta(struct seg *seg, caddr_t addr)
2256 {
2257         return (0);
2258 }
2259 
2260 /*ARGSUSED*/
2261 static int
2262 segspt_shmkluster(struct seg *seg, caddr_t addr, ssize_t delta)
2263 {
2264         return (0);
2265 }
2266 
2267 /*ARGSUSED*/
2268 static size_t
2269 segspt_shmswapout(struct seg *seg)
2270 {
2271         return (0);
2272 }
2273 
2274 /*
2275  * duplicate the shared page tables
2276  */
2277 int
2278 segspt_shmdup(struct seg *seg, struct seg *newseg)
2279 {
2280         struct shm_data         *shmd = (struct shm_data *)seg->s_data;
2281         struct anon_map         *amp = shmd->shm_amp;
2282         struct shm_data         *shmd_new;
2283         struct seg              *spt_seg = shmd->shm_sptseg;
2284         struct spt_data         *sptd = spt_seg->s_data;
2285         int                     error = 0;
2286 
2287         ASSERT(seg->s_as && AS_WRITE_HELD(seg->s_as, &seg->s_as->a_lock));
2288 
2289         shmd_new = kmem_zalloc((sizeof (*shmd_new)), KM_SLEEP);
2290         newseg->s_data = (void *)shmd_new;
2291         shmd_new->shm_sptas = shmd->shm_sptas;
2292         shmd_new->shm_amp = amp;
2293         shmd_new->shm_sptseg = shmd->shm_sptseg;


2997                  * don't bother reapplying it.
2998                  */
2999                 if (already_set && !LGRP_MEM_POLICY_REAPPLICABLE(policy))
3000                         return (0);
3001 
3002                 /*
3003                  * Mark any existing pages in the given range for
3004                  * migration, flushing the I/O page cache, and using
3005                  * underlying segment to calculate anon index and get
3006                  * anonmap and vnode pointer from
3007                  */
3008                 if (shmd->shm_softlockcnt > 0)
3009                         segspt_purge(seg);
3010 
3011                 page_mark_migrate(seg, shm_addr, size, amp, 0, NULL, 0, 0);
3012         }
3013 
3014         return (0);
3015 }
3016 
3017 /*ARGSUSED*/
3018 void
3019 segspt_shmdump(struct seg *seg)
3020 {
3021         /* no-op for ISM segment */
3022 }
3023 
3024 /*ARGSUSED*/
3025 static faultcode_t
3026 segspt_shmsetpgsz(struct seg *seg, caddr_t addr, size_t len, uint_t szc)
3027 {
3028         return (ENOTSUP);
3029 }
3030 
3031 /*
3032  * get a memory ID for an addr in a given segment
3033  */
3034 static int
3035 segspt_shmgetmemid(struct seg *seg, caddr_t addr, memid_t *memidp)
3036 {
3037         struct shm_data *shmd = (struct shm_data *)seg->s_data;
3038         struct anon     *ap;
3039         size_t          anon_index;
3040         struct anon_map *amp = shmd->shm_amp;
3041         struct spt_data *sptd = shmd->shm_sptseg->s_data;
3042         struct seg      *sptseg = shmd->shm_sptseg;
3043         anon_sync_obj_t cookie;
3044 
3045         anon_index = seg_page(seg, addr);
3046 
3047         if (addr > (seg->s_base + sptd->spt_realsize)) {
3048                 return (EFAULT);
3049         }
3050 


3090          * Assume that no lock needs to be held on anon_map, since
3091          * it should be protected by its reference count which must be
3092          * nonzero for an existing segment
3093          * Need to grab readers lock on policy tree though
3094          */
3095         shm_data = (struct shm_data *)seg->s_data;
3096         if (shm_data == NULL)
3097                 return (NULL);
3098         amp = shm_data->shm_amp;
3099         ASSERT(amp->refcnt != 0);
3100 
3101         /*
3102          * Get policy info
3103          *
3104          * Assume starting anon index of 0
3105          */
3106         anon_index = seg_page(seg, addr);
3107         policy_info = lgrp_shm_policy_get(amp, anon_index, NULL, 0);
3108 
3109         return (policy_info);
3110 }
3111 
3112 /*ARGSUSED*/
3113 static int
3114 segspt_shmcapable(struct seg *seg, segcapability_t capability)
3115 {
3116         return (0);
3117 }


  59 
  60 /*
  61  * segspt_minfree is the memory left for system after ISM
  62  * locked its pages; it is set up to 5% of availrmem in
  63  * sptcreate when ISM is created.  ISM should not use more
  64  * than ~90% of availrmem; if it does, then the performance
  65  * of the system may decrease. Machines with large memories may
  66  * be able to use up more memory for ISM so we set the default
  67  * segspt_minfree to 5% (which gives ISM max 95% of availrmem.
  68  * If somebody wants even more memory for ISM (risking hanging
  69  * the system) they can patch the segspt_minfree to smaller number.
  70  */
  71 pgcnt_t segspt_minfree = 0;
  72 
  73 static int segspt_create(struct seg *seg, caddr_t argsp);
  74 static int segspt_unmap(struct seg *seg, caddr_t raddr, size_t ssize);
  75 static void segspt_free(struct seg *seg);
  76 static void segspt_free_pages(struct seg *seg, caddr_t addr, size_t len);
  77 static lgrp_mem_policy_info_t *segspt_getpolicy(struct seg *seg, caddr_t addr);
  78 
  79 static const struct seg_ops segspt_ops = {
  80         .unmap          = segspt_unmap,
  81         .free           = segspt_free,
  82         .getpolicy      = segspt_getpolicy,






























  83 };
  84 
  85 static int segspt_shmdup(struct seg *seg, struct seg *newseg);
  86 static int segspt_shmunmap(struct seg *seg, caddr_t raddr, size_t ssize);
  87 static void segspt_shmfree(struct seg *seg);
  88 static faultcode_t segspt_shmfault(struct hat *hat, struct seg *seg,
  89                 caddr_t addr, size_t len, enum fault_type type, enum seg_rw rw);
  90 static faultcode_t segspt_shmfaulta(struct seg *seg, caddr_t addr);
  91 static int segspt_shmsetprot(register struct seg *seg, register caddr_t addr,
  92                         register size_t len, register uint_t prot);
  93 static int segspt_shmcheckprot(struct seg *seg, caddr_t addr, size_t size,
  94                         uint_t prot);
  95 static int      segspt_shmkluster(struct seg *seg, caddr_t addr, ssize_t delta);

  96 static size_t segspt_shmincore(struct seg *seg, caddr_t addr, size_t len,
  97                         register char *vec);
  98 static int segspt_shmsync(struct seg *seg, register caddr_t addr, size_t len,
  99                         int attr, uint_t flags);
 100 static int segspt_shmlockop(struct seg *seg, caddr_t addr, size_t len,
 101                         int attr, int op, ulong_t *lockmap, size_t pos);
 102 static int segspt_shmgetprot(struct seg *seg, caddr_t addr, size_t len,
 103                         uint_t *protv);
 104 static u_offset_t segspt_shmgetoffset(struct seg *seg, caddr_t addr);
 105 static int segspt_shmgettype(struct seg *seg, caddr_t addr);
 106 static int segspt_shmgetvp(struct seg *seg, caddr_t addr, struct vnode **vpp);
 107 static int segspt_shmadvise(struct seg *seg, caddr_t addr, size_t len,
 108                         uint_t behav);

 109 static int segspt_shmpagelock(struct seg *, caddr_t, size_t,
 110                         struct page ***, enum lock_type, enum seg_rw);

 111 static int segspt_shmgetmemid(struct seg *, caddr_t, memid_t *);
 112 static lgrp_mem_policy_info_t *segspt_shmgetpolicy(struct seg *, caddr_t);

 113 
 114 const struct seg_ops segspt_shmops = {
 115         .dup            = segspt_shmdup,
 116         .unmap          = segspt_shmunmap,
 117         .free           = segspt_shmfree,
 118         .fault          = segspt_shmfault,
 119         .faulta         = segspt_shmfaulta,
 120         .setprot        = segspt_shmsetprot,
 121         .checkprot      = segspt_shmcheckprot,
 122         .kluster        = segspt_shmkluster,
 123         .sync           = segspt_shmsync,
 124         .incore         = segspt_shmincore,
 125         .lockop         = segspt_shmlockop,
 126         .getprot        = segspt_shmgetprot,
 127         .getoffset      = segspt_shmgetoffset,
 128         .gettype        = segspt_shmgettype,
 129         .getvp          = segspt_shmgetvp,
 130         .advise         = segspt_shmadvise,
 131         .pagelock       = segspt_shmpagelock,
 132         .getmemid       = segspt_shmgetmemid,
 133         .getpolicy      = segspt_shmgetpolicy,





 134 };
 135 
 136 static void segspt_purge(struct seg *seg);
 137 static int segspt_reclaim(void *, caddr_t, size_t, struct page **,
 138                 enum seg_rw, int);
 139 static int spt_anon_getpages(struct seg *seg, caddr_t addr, size_t len,
 140                 page_t **ppa);
 141 
 142 
 143 
 144 /*ARGSUSED*/
 145 int
 146 sptcreate(size_t size, struct seg **sptseg, struct anon_map *amp,
 147         uint_t prot, uint_t flags, uint_t share_szc)
 148 {
 149         int     err;
 150         struct  as      *newas;
 151         struct  segspt_crargs sptcargs;
 152 
 153 #ifdef DEBUG


1868                                 atomic_add_long((ulong_t *)(
1869                                     &(shmd->shm_softlockcnt)), -npages);
1870                         }
1871                         goto dism_err;
1872                 }
1873                 AS_LOCK_ENTER(sptseg->s_as, &sptseg->s_as->a_lock, RW_READER);
1874                 a = segspt_addr;
1875                 pidx = 0;
1876                 if (type == F_SOFTLOCK) {
1877 
1878                         /*
1879                          * Load up the translation keeping it
1880                          * locked and don't unlock the page.
1881                          */
1882                         for (; pidx < npages; a += pgsz, pidx += pgcnt) {
1883                                 hat_memload_array(sptseg->s_as->a_hat,
1884                                     a, pgsz, &ppa[pidx], sptd->spt_prot,
1885                                     HAT_LOAD_LOCK | HAT_LOAD_SHARE);
1886                         }
1887                 } else {


1888                         /*
1889                          * Migrate pages marked for migration
1890                          */
1891                         if (lgrp_optimizations())
1892                                 page_migrate(seg, shm_addr, ppa, npages);

1893 
1894                         for (; pidx < npages; a += pgsz, pidx += pgcnt) {


1895                                 hat_memload_array(sptseg->s_as->a_hat,
1896                                     a, pgsz, &ppa[pidx],
1897                                     sptd->spt_prot,
1898                                     HAT_LOAD_SHARE);
1899                         }





1900 
1901                         /*
1902                          * And now drop the SE_SHARED lock(s).
1903                          */
1904                         if (dyn_ism_unmap) {
1905                                 for (i = 0; i < npages; i++) {
1906                                         page_unlock(ppa[i]);
1907                                 }
1908                         }
1909                 }
1910 
1911                 if (!dyn_ism_unmap) {
1912                         if (hat_share(seg->s_as->a_hat, shm_addr,
1913                             curspt->a_hat, segspt_addr, ptob(npages),
1914                             seg->s_szc) != 0) {
1915                                 panic("hat_share err in DISM fault");
1916                                 /* NOTREACHED */
1917                         }
1918                         if (type == F_INVAL) {
1919                                 for (i = 0; i < npages; i++) {


2118                  * We are already holding the as->a_lock on the user's
2119                  * real segment, but we need to hold the a_lock on the
2120                  * underlying dummy as. This is mostly to satisfy the
2121                  * underlying HAT layer.
2122                  */
2123                 AS_LOCK_ENTER(sptseg->s_as, &sptseg->s_as->a_lock, RW_READER);
2124                 a = sptseg_addr;
2125                 pidx = 0;
2126                 if (type == F_SOFTLOCK) {
2127                         /*
2128                          * Load up the translation keeping it
2129                          * locked and don't unlock the page.
2130                          */
2131                         for (; pidx < npages; a += pgsz, pidx += pgcnt) {
2132                                 sz = MIN(pgsz, ptob(npages - pidx));
2133                                 hat_memload_array(sptseg->s_as->a_hat, a,
2134                                     sz, &ppa[pidx], sptd->spt_prot,
2135                                     HAT_LOAD_LOCK | HAT_LOAD_SHARE);
2136                         }
2137                 } else {


2138                         /*
2139                          * Migrate pages marked for migration.
2140                          */
2141                         if (lgrp_optimizations())
2142                                 page_migrate(seg, shm_addr, ppa, npages);

2143 
2144                         for (; pidx < npages; a += pgsz, pidx += pgcnt) {


2145                                 sz = MIN(pgsz, ptob(npages - pidx));
2146                                 hat_memload_array(sptseg->s_as->a_hat,
2147                                     a, sz, &ppa[pidx],
2148                                     sptd->spt_prot, HAT_LOAD_SHARE);
2149                         }






2150 
2151                         /*
2152                          * And now drop the SE_SHARED lock(s).
2153                          */
2154                         for (i = 0; i < npages; i++)
2155                                 page_unlock(ppa[i]);
2156                 }
2157                 AS_LOCK_EXIT(sptseg->s_as, &sptseg->s_as->a_lock);
2158 
2159                 kmem_free(ppa, sizeof (page_t *) * npages);
2160                 return (0);
2161         case F_SOFTUNLOCK:
2162 
2163                 /*
2164                  * This is a bit ugly, we pass in the real seg pointer,
2165                  * but the sptseg_addr is the virtual address within the
2166                  * dummy seg.
2167                  */
2168                 segspt_softunlock(seg, sptseg_addr, ptob(npages), rw);
2169                 return (0);


2187                 cmn_err(CE_WARN, "segspt_shmfault default type?");
2188 #endif
2189                 return (FC_NOMAP);
2190         }
2191 }
2192 
2193 /*ARGSUSED*/
2194 static faultcode_t
2195 segspt_shmfaulta(struct seg *seg, caddr_t addr)
2196 {
2197         return (0);
2198 }
2199 
2200 /*ARGSUSED*/
2201 static int
2202 segspt_shmkluster(struct seg *seg, caddr_t addr, ssize_t delta)
2203 {
2204         return (0);
2205 }
2206 







2207 /*
2208  * duplicate the shared page tables
2209  */
2210 int
2211 segspt_shmdup(struct seg *seg, struct seg *newseg)
2212 {
2213         struct shm_data         *shmd = (struct shm_data *)seg->s_data;
2214         struct anon_map         *amp = shmd->shm_amp;
2215         struct shm_data         *shmd_new;
2216         struct seg              *spt_seg = shmd->shm_sptseg;
2217         struct spt_data         *sptd = spt_seg->s_data;
2218         int                     error = 0;
2219 
2220         ASSERT(seg->s_as && AS_WRITE_HELD(seg->s_as, &seg->s_as->a_lock));
2221 
2222         shmd_new = kmem_zalloc((sizeof (*shmd_new)), KM_SLEEP);
2223         newseg->s_data = (void *)shmd_new;
2224         shmd_new->shm_sptas = shmd->shm_sptas;
2225         shmd_new->shm_amp = amp;
2226         shmd_new->shm_sptseg = shmd->shm_sptseg;


2930                  * don't bother reapplying it.
2931                  */
2932                 if (already_set && !LGRP_MEM_POLICY_REAPPLICABLE(policy))
2933                         return (0);
2934 
2935                 /*
2936                  * Mark any existing pages in the given range for
2937                  * migration, flushing the I/O page cache, and using
2938                  * underlying segment to calculate anon index and get
2939                  * anonmap and vnode pointer from
2940                  */
2941                 if (shmd->shm_softlockcnt > 0)
2942                         segspt_purge(seg);
2943 
2944                 page_mark_migrate(seg, shm_addr, size, amp, 0, NULL, 0, 0);
2945         }
2946 
2947         return (0);
2948 }
2949 














2950 /*
2951  * get a memory ID for an addr in a given segment
2952  */
2953 static int
2954 segspt_shmgetmemid(struct seg *seg, caddr_t addr, memid_t *memidp)
2955 {
2956         struct shm_data *shmd = (struct shm_data *)seg->s_data;
2957         struct anon     *ap;
2958         size_t          anon_index;
2959         struct anon_map *amp = shmd->shm_amp;
2960         struct spt_data *sptd = shmd->shm_sptseg->s_data;
2961         struct seg      *sptseg = shmd->shm_sptseg;
2962         anon_sync_obj_t cookie;
2963 
2964         anon_index = seg_page(seg, addr);
2965 
2966         if (addr > (seg->s_base + sptd->spt_realsize)) {
2967                 return (EFAULT);
2968         }
2969 


3009          * Assume that no lock needs to be held on anon_map, since
3010          * it should be protected by its reference count which must be
3011          * nonzero for an existing segment
3012          * Need to grab readers lock on policy tree though
3013          */
3014         shm_data = (struct shm_data *)seg->s_data;
3015         if (shm_data == NULL)
3016                 return (NULL);
3017         amp = shm_data->shm_amp;
3018         ASSERT(amp->refcnt != 0);
3019 
3020         /*
3021          * Get policy info
3022          *
3023          * Assume starting anon index of 0
3024          */
3025         anon_index = seg_page(seg, addr);
3026         policy_info = lgrp_shm_policy_get(amp, anon_index, NULL, 0);
3027 
3028         return (policy_info);







3029 }