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 }
|