3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
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 (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2018 Joyent, Inc.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
25 */
26
27 #include <sys/param.h>
28 #include <sys/user.h>
29 #include <sys/mman.h>
30 #include <sys/kmem.h>
31 #include <sys/sysmacros.h>
32 #include <sys/cmn_err.h>
33 #include <sys/systm.h>
34 #include <sys/tuneable.h>
35 #include <vm/hat.h>
36 #include <vm/seg.h>
37 #include <vm/as.h>
38 #include <vm/anon.h>
39 #include <vm/page.h>
40 #include <sys/buf.h>
41 #include <sys/swap.h>
42 #include <sys/atomic.h>
43 #include <vm/seg_spt.h>
44 #include <sys/debug.h>
45 #include <sys/vtrace.h>
46 #include <sys/shm.h>
47 #include <sys/shm_impl.h>
48 #include <sys/lgrp.h>
49 #include <sys/vmsystm.h>
50 #include <sys/policy.h>
51 #include <sys/project.h>
52 #include <sys/tnf_probe.h>
53 #include <sys/zone.h>
54
55 #define SEGSPTADDR (caddr_t)0x0
56
57 /*
58 * # pages used for spt
59 */
60 size_t spt_used;
61
62 /*
63 * segspt_minfree is the memory left for system after ISM
64 * locked its pages; it is set up to 5% of availrmem in
65 * sptcreate when ISM is created. ISM should not use more
66 * than ~90% of availrmem; if it does, then the performance
67 * of the system may decrease. Machines with large memories may
68 * be able to use up more memory for ISM so we set the default
69 * segspt_minfree to 5% (which gives ISM max 95% of availrmem.
70 * If somebody wants even more memory for ISM (risking hanging
71 * the system) they can patch the segspt_minfree to smaller number.
72 */
73 pgcnt_t segspt_minfree = 0;
74
75 static int segspt_create(struct seg **segpp, void *argsp);
76 static int segspt_unmap(struct seg *seg, caddr_t raddr, size_t ssize);
77 static void segspt_free(struct seg *seg);
78 static void segspt_free_pages(struct seg *seg, caddr_t addr, size_t len);
79 static lgrp_mem_policy_info_t *segspt_getpolicy(struct seg *seg, caddr_t addr);
80
81 /* ARGSUSED */
82 __NORETURN static int
83 segspt_badop_dup(struct seg *seg __unused, struct seg *newseg __unused)
84 {
85 panic("%s called", __func__);
86 }
87
88 /* ARGSUSED */
89 __NORETURN static faultcode_t
90 segspt_badop_fault(struct hat *hat, struct seg *seg, caddr_t addr,
91 size_t len, enum fault_type type, enum seg_rw rw)
92 {
93 panic("%s called", __func__);
299 segspt_shmgetprot,
300 segspt_shmgetoffset,
301 segspt_shmgettype,
302 segspt_shmgetvp,
303 segspt_shmadvise, /* advise */
304 segspt_shmdump,
305 segspt_shmpagelock,
306 segspt_shmsetpgsz,
307 segspt_shmgetmemid,
308 segspt_shmgetpolicy,
309 segspt_shmcapable,
310 seg_inherit_notsup
311 };
312
313 static void segspt_purge(struct seg *seg);
314 static int segspt_reclaim(void *, caddr_t, size_t, struct page **,
315 enum seg_rw, int);
316 static int spt_anon_getpages(struct seg *seg, caddr_t addr, size_t len,
317 page_t **ppa);
318
319
320
321 /*ARGSUSED*/
322 int
323 sptcreate(size_t size, struct seg **sptseg, struct anon_map *amp,
324 uint_t prot, uint_t flags, uint_t share_szc)
325 {
326 int err;
327 struct as *newas;
328 struct segspt_crargs sptcargs;
329
330 #ifdef DEBUG
331 TNF_PROBE_1(sptcreate, "spt", /* CSTYLED */,
332 tnf_ulong, size, size );
333 #endif
334 if (segspt_minfree == 0) /* leave min 5% of availrmem for */
335 segspt_minfree = availrmem/20; /* for the system */
336
337 if (!hat_supported(HAT_SHARED_PT, (void *)0))
338 return (EINVAL);
339
340 /*
341 * get a new as for this shared memory segment
342 */
343 newas = as_alloc();
344 newas->a_proc = NULL;
345 sptcargs.amp = amp;
346 sptcargs.prot = prot;
347 sptcargs.flags = flags;
348 sptcargs.szc = share_szc;
349 /*
350 * create a shared page table (spt) segment
351 */
352
353 if (err = as_map(newas, SEGSPTADDR, size, segspt_create, &sptcargs)) {
354 as_free(newas);
355 return (err);
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
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 (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2019 Joyent, Inc.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
25 */
26
27 #include <sys/param.h>
28 #include <sys/user.h>
29 #include <sys/mman.h>
30 #include <sys/kmem.h>
31 #include <sys/sysmacros.h>
32 #include <sys/cmn_err.h>
33 #include <sys/systm.h>
34 #include <sys/tuneable.h>
35 #include <vm/hat.h>
36 #include <vm/seg.h>
37 #include <vm/as.h>
38 #include <vm/anon.h>
39 #include <vm/page.h>
40 #include <sys/buf.h>
41 #include <sys/swap.h>
42 #include <sys/atomic.h>
43 #include <vm/seg_spt.h>
44 #include <sys/debug.h>
45 #include <sys/vtrace.h>
46 #include <sys/shm.h>
47 #include <sys/shm_impl.h>
48 #include <sys/lgrp.h>
49 #include <sys/vmsystm.h>
50 #include <sys/policy.h>
51 #include <sys/project.h>
52 #include <sys/tnf_probe.h>
53 #include <sys/zone.h>
54
55 #define SEGSPTADDR (caddr_t)0x0
56
57 /*
58 * # pages used for spt
59 */
60 size_t spt_used;
61
62 /*
63 * See spt_setminfree().
64 */
65 pgcnt_t segspt_minfree = 0;
66 size_t segspt_minfree_clamp = (1UL << 30); /* 1GB in bytes */
67
68 static int segspt_create(struct seg **segpp, void *argsp);
69 static int segspt_unmap(struct seg *seg, caddr_t raddr, size_t ssize);
70 static void segspt_free(struct seg *seg);
71 static void segspt_free_pages(struct seg *seg, caddr_t addr, size_t len);
72 static lgrp_mem_policy_info_t *segspt_getpolicy(struct seg *seg, caddr_t addr);
73
74 /* ARGSUSED */
75 __NORETURN static int
76 segspt_badop_dup(struct seg *seg __unused, struct seg *newseg __unused)
77 {
78 panic("%s called", __func__);
79 }
80
81 /* ARGSUSED */
82 __NORETURN static faultcode_t
83 segspt_badop_fault(struct hat *hat, struct seg *seg, caddr_t addr,
84 size_t len, enum fault_type type, enum seg_rw rw)
85 {
86 panic("%s called", __func__);
292 segspt_shmgetprot,
293 segspt_shmgetoffset,
294 segspt_shmgettype,
295 segspt_shmgetvp,
296 segspt_shmadvise, /* advise */
297 segspt_shmdump,
298 segspt_shmpagelock,
299 segspt_shmsetpgsz,
300 segspt_shmgetmemid,
301 segspt_shmgetpolicy,
302 segspt_shmcapable,
303 seg_inherit_notsup
304 };
305
306 static void segspt_purge(struct seg *seg);
307 static int segspt_reclaim(void *, caddr_t, size_t, struct page **,
308 enum seg_rw, int);
309 static int spt_anon_getpages(struct seg *seg, caddr_t addr, size_t len,
310 page_t **ppa);
311
312 /*
313 * This value corresponds to headroom in availrmem that ISM can never allocate
314 * (but others can). The original intent here was to prevent ISM from locking
315 * all of the remaining availrmem into memory, making forward progress
316 * difficult. It's not clear how much this matters on modern systems.
317 *
318 * The traditional default value of 5% of total memory is used, except on
319 * systems where that quickly gets ridiculous: in that case we clamp at a rather
320 * arbitrary value of 1GB.
321 *
322 * Note that since this is called lazily on the first sptcreate(), in theory,
323 * this could represent a very small value if the system is heavily loaded
324 * already. In practice, the first ISM user is pretty likely to come along
325 * earlier during the system's operation.
326 *
327 * This never gets re-figured.
328 */
329 static void
330 spt_setminfree(void)
331 {
332 segspt_minfree = availrmem / 20;
333
334 if (segspt_minfree_clamp != 0 &&
335 segspt_minfree > (segspt_minfree_clamp / PAGESIZE))
336 segspt_minfree = segspt_minfree_clamp / PAGESIZE;
337 }
338
339 int
340 sptcreate(size_t size, struct seg **sptseg, struct anon_map *amp,
341 uint_t prot, uint_t flags, uint_t share_szc)
342 {
343 int err;
344 struct as *newas;
345 struct segspt_crargs sptcargs;
346
347 #ifdef DEBUG
348 TNF_PROBE_1(sptcreate, "spt", /* CSTYLED */,
349 tnf_ulong, size, size );
350 #endif
351 if (segspt_minfree == 0)
352 spt_setminfree();
353
354 if (!hat_supported(HAT_SHARED_PT, (void *)0))
355 return (EINVAL);
356
357 /*
358 * get a new as for this shared memory segment
359 */
360 newas = as_alloc();
361 newas->a_proc = NULL;
362 sptcargs.amp = amp;
363 sptcargs.prot = prot;
364 sptcargs.flags = flags;
365 sptcargs.szc = share_szc;
366 /*
367 * create a shared page table (spt) segment
368 */
369
370 if (err = as_map(newas, SEGSPTADDR, size, segspt_create, &sptcargs)) {
371 as_free(newas);
372 return (err);
|