xref: /illumos-gate/usr/src/uts/common/vm/seg_umap.c (revision 284ce987)
12428aad8SPatrick Mooney /*
22428aad8SPatrick Mooney  * This file and its contents are supplied under the terms of the
32428aad8SPatrick Mooney  * Common Development and Distribution License ("CDDL"), version 1.0.
42428aad8SPatrick Mooney  * You may only use this file in accordance with the terms of version
52428aad8SPatrick Mooney  * 1.0 of the CDDL.
62428aad8SPatrick Mooney  *
72428aad8SPatrick Mooney  * A full copy of the text of the CDDL should have accompanied this
82428aad8SPatrick Mooney  * source.  A copy of the CDDL is also available via the Internet at
92428aad8SPatrick Mooney  * http://www.illumos.org/license/CDDL.
102428aad8SPatrick Mooney  */
112428aad8SPatrick Mooney 
122428aad8SPatrick Mooney /*
13*284ce987SPatrick Mooney  * Copyright 2018 Joyent, Inc.
142428aad8SPatrick Mooney  */
152428aad8SPatrick Mooney 
162428aad8SPatrick Mooney /*
172428aad8SPatrick Mooney  * VM - Kernel-to-user mapping segment
182428aad8SPatrick Mooney  *
192428aad8SPatrick Mooney  * The umap segment driver was primarily designed to facilitate the comm page:
202428aad8SPatrick Mooney  * a portion of kernel memory shared with userspace so that certain (namely
212428aad8SPatrick Mooney  * clock-related) actions could operate without making an expensive trip into
222428aad8SPatrick Mooney  * the kernel.
232428aad8SPatrick Mooney  *
242428aad8SPatrick Mooney  * Since the initial requirements for the comm page are slim, advanced features
252428aad8SPatrick Mooney  * of the segment driver such as per-page protection have been left
262428aad8SPatrick Mooney  * unimplemented at this time.
272428aad8SPatrick Mooney  */
282428aad8SPatrick Mooney 
292428aad8SPatrick Mooney 
302428aad8SPatrick Mooney #include <sys/types.h>
312428aad8SPatrick Mooney #include <sys/param.h>
322428aad8SPatrick Mooney #include <sys/errno.h>
332428aad8SPatrick Mooney #include <sys/cred.h>
342428aad8SPatrick Mooney #include <sys/kmem.h>
352428aad8SPatrick Mooney #include <sys/lgrp.h>
362428aad8SPatrick Mooney #include <sys/mman.h>
372428aad8SPatrick Mooney 
382428aad8SPatrick Mooney #include <vm/hat.h>
392428aad8SPatrick Mooney #include <vm/as.h>
402428aad8SPatrick Mooney #include <vm/seg.h>
412428aad8SPatrick Mooney #include <vm/seg_kmem.h>
422428aad8SPatrick Mooney #include <vm/seg_umap.h>
432428aad8SPatrick Mooney 
442428aad8SPatrick Mooney 
452428aad8SPatrick Mooney static boolean_t segumap_verify_safe(caddr_t, size_t);
462428aad8SPatrick Mooney static int segumap_dup(struct seg *, struct seg *);
472428aad8SPatrick Mooney static int segumap_unmap(struct seg *, caddr_t, size_t);
482428aad8SPatrick Mooney static void segumap_free(struct seg *);
492428aad8SPatrick Mooney static faultcode_t segumap_fault(struct hat *, struct seg *, caddr_t, size_t,
502428aad8SPatrick Mooney     enum fault_type, enum seg_rw);
512428aad8SPatrick Mooney static faultcode_t segumap_faulta(struct seg *, caddr_t);
522428aad8SPatrick Mooney static int segumap_setprot(struct seg *, caddr_t, size_t, uint_t);
532428aad8SPatrick Mooney static int segumap_checkprot(struct seg *, caddr_t, size_t, uint_t);
542428aad8SPatrick Mooney static int segumap_sync(struct seg *, caddr_t, size_t, int, uint_t);
552428aad8SPatrick Mooney static size_t segumap_incore(struct seg *, caddr_t, size_t, char *);
562428aad8SPatrick Mooney static int segumap_lockop(struct seg *, caddr_t, size_t, int, int, ulong_t *,
572428aad8SPatrick Mooney     size_t);
582428aad8SPatrick Mooney static int segumap_getprot(struct seg *, caddr_t, size_t, uint_t *);
592428aad8SPatrick Mooney static u_offset_t segumap_getoffset(struct seg *, caddr_t);
602428aad8SPatrick Mooney static int segumap_gettype(struct seg *, caddr_t);
612428aad8SPatrick Mooney static int segumap_getvp(struct seg *, caddr_t, struct vnode **);
622428aad8SPatrick Mooney static int segumap_advise(struct seg *, caddr_t, size_t, uint_t);
632428aad8SPatrick Mooney static void segumap_dump(struct seg *);
642428aad8SPatrick Mooney static int segumap_pagelock(struct seg *, caddr_t, size_t, struct page ***,
652428aad8SPatrick Mooney     enum lock_type, enum seg_rw);
662428aad8SPatrick Mooney static int segumap_setpagesize(struct seg *, caddr_t, size_t, uint_t);
672428aad8SPatrick Mooney static int segumap_getmemid(struct seg *, caddr_t, memid_t *);
682428aad8SPatrick Mooney static int segumap_capable(struct seg *, segcapability_t);
692428aad8SPatrick Mooney 
702428aad8SPatrick Mooney static struct seg_ops segumap_ops = {
712428aad8SPatrick Mooney 	segumap_dup,
722428aad8SPatrick Mooney 	segumap_unmap,
732428aad8SPatrick Mooney 	segumap_free,
742428aad8SPatrick Mooney 	segumap_fault,
752428aad8SPatrick Mooney 	segumap_faulta,
762428aad8SPatrick Mooney 	segumap_setprot,
772428aad8SPatrick Mooney 	segumap_checkprot,
782428aad8SPatrick Mooney 	NULL,			/* kluster: disabled */
792428aad8SPatrick Mooney 	NULL,			/* swapout: disabled */
802428aad8SPatrick Mooney 	segumap_sync,
812428aad8SPatrick Mooney 	segumap_incore,
822428aad8SPatrick Mooney 	segumap_lockop,
832428aad8SPatrick Mooney 	segumap_getprot,
842428aad8SPatrick Mooney 	segumap_getoffset,
852428aad8SPatrick Mooney 	segumap_gettype,
862428aad8SPatrick Mooney 	segumap_getvp,
872428aad8SPatrick Mooney 	segumap_advise,
882428aad8SPatrick Mooney 	segumap_dump,
892428aad8SPatrick Mooney 	segumap_pagelock,
902428aad8SPatrick Mooney 	segumap_setpagesize,
912428aad8SPatrick Mooney 	segumap_getmemid,
922428aad8SPatrick Mooney 	NULL,			/* getpolicy: disabled */
932428aad8SPatrick Mooney 	segumap_capable,
942428aad8SPatrick Mooney 	seg_inherit_notsup
952428aad8SPatrick Mooney };
962428aad8SPatrick Mooney 
972428aad8SPatrick Mooney 
982428aad8SPatrick Mooney /*
992428aad8SPatrick Mooney  * Create a kernel/user-mapped segment.
1002428aad8SPatrick Mooney  */
1012428aad8SPatrick Mooney int
segumap_create(struct seg ** segpp,void * argsp)102*284ce987SPatrick Mooney segumap_create(struct seg **segpp, void *argsp)
1032428aad8SPatrick Mooney {
104*284ce987SPatrick Mooney 	struct seg *seg = *segpp;
1052428aad8SPatrick Mooney 	segumap_crargs_t *a = (struct segumap_crargs *)argsp;
1062428aad8SPatrick Mooney 	segumap_data_t *data;
1072428aad8SPatrick Mooney 
1082428aad8SPatrick Mooney 	ASSERT((uintptr_t)a->kaddr > _userlimit);
1092428aad8SPatrick Mooney 
1102428aad8SPatrick Mooney 	/*
1112428aad8SPatrick Mooney 	 * Check several aspects of the mapping request to ensure validity:
1122428aad8SPatrick Mooney 	 * - kernel pages must reside entirely in kernel space
1132428aad8SPatrick Mooney 	 * - target protection must be user-accessible
1142428aad8SPatrick Mooney 	 * - kernel address must be page-aligned
1152428aad8SPatrick Mooney 	 * - kernel address must reside inside a "safe" segment
1162428aad8SPatrick Mooney 	 */
1172428aad8SPatrick Mooney 	if ((uintptr_t)a->kaddr <= _userlimit ||
1182428aad8SPatrick Mooney 	    ((uintptr_t)a->kaddr + seg->s_size) < (uintptr_t)a->kaddr ||
1192428aad8SPatrick Mooney 	    (a->prot & PROT_USER) == 0 ||
1202428aad8SPatrick Mooney 	    ((uintptr_t)a->kaddr & PAGEOFFSET) != 0 ||
1212428aad8SPatrick Mooney 	    !segumap_verify_safe(a->kaddr, seg->s_size)) {
1222428aad8SPatrick Mooney 		return (EINVAL);
1232428aad8SPatrick Mooney 	}
1242428aad8SPatrick Mooney 
1252428aad8SPatrick Mooney 	data = kmem_zalloc(sizeof (*data), KM_SLEEP);
1262428aad8SPatrick Mooney 	rw_init(&data->sud_lock, NULL, RW_DEFAULT, NULL);
1272428aad8SPatrick Mooney 	data->sud_kaddr = a->kaddr;
1282428aad8SPatrick Mooney 	data->sud_prot = a->prot;
1292428aad8SPatrick Mooney 
1302428aad8SPatrick Mooney 	seg->s_ops = &segumap_ops;
1312428aad8SPatrick Mooney 	seg->s_data = data;
1322428aad8SPatrick Mooney 	return (0);
1332428aad8SPatrick Mooney }
1342428aad8SPatrick Mooney 
1352428aad8SPatrick Mooney static boolean_t
segumap_verify_safe(caddr_t kaddr,size_t len)1362428aad8SPatrick Mooney segumap_verify_safe(caddr_t kaddr, size_t len)
1372428aad8SPatrick Mooney {
1382428aad8SPatrick Mooney 	struct seg *seg;
1392428aad8SPatrick Mooney 
1402428aad8SPatrick Mooney 	/*
1412428aad8SPatrick Mooney 	 * Presently, only pages which are backed by segkmem are allowed to be
1422428aad8SPatrick Mooney 	 * shared with userspace.  This prevents nasty paging behavior with
1432428aad8SPatrick Mooney 	 * other drivers such as seg_kp.  Furthermore, the backing kernel
1442428aad8SPatrick Mooney 	 * segment must completely contain the region to be mapped.
1452428aad8SPatrick Mooney 	 *
1462428aad8SPatrick Mooney 	 * Failing these checks is fatal for now since such mappings are done
1472428aad8SPatrick Mooney 	 * in a very limited context from the kernel.
1482428aad8SPatrick Mooney 	 */
1492428aad8SPatrick Mooney 	AS_LOCK_ENTER(&kas, RW_READER);
1502428aad8SPatrick Mooney 	seg = as_segat(&kas, kaddr);
1512428aad8SPatrick Mooney 	VERIFY(seg != NULL);
1522428aad8SPatrick Mooney 	VERIFY(seg->s_base + seg->s_size >= kaddr + len);
1532428aad8SPatrick Mooney 	VERIFY(seg->s_ops == &segkmem_ops);
1542428aad8SPatrick Mooney 	AS_LOCK_EXIT(&kas);
1552428aad8SPatrick Mooney 
1562428aad8SPatrick Mooney 	return (B_TRUE);
1572428aad8SPatrick Mooney }
1582428aad8SPatrick Mooney 
1592428aad8SPatrick Mooney static int
segumap_dup(struct seg * seg,struct seg * newseg)1602428aad8SPatrick Mooney segumap_dup(struct seg *seg, struct seg *newseg)
1612428aad8SPatrick Mooney {
1622428aad8SPatrick Mooney 	segumap_data_t *sud = (segumap_data_t *)seg->s_data;
1632428aad8SPatrick Mooney 	segumap_data_t *newsud;
1642428aad8SPatrick Mooney 
1652428aad8SPatrick Mooney 	ASSERT(seg->s_as && AS_WRITE_HELD(seg->s_as));
1662428aad8SPatrick Mooney 
1672428aad8SPatrick Mooney 	newsud = kmem_zalloc(sizeof (segumap_data_t), KM_SLEEP);
1682428aad8SPatrick Mooney 	rw_init(&newsud->sud_lock, NULL, RW_DEFAULT, NULL);
1692428aad8SPatrick Mooney 	newsud->sud_kaddr = sud->sud_kaddr;
1702428aad8SPatrick Mooney 	newsud->sud_prot = sud->sud_prot;
1712428aad8SPatrick Mooney 
1722428aad8SPatrick Mooney 	newseg->s_ops = seg->s_ops;
1732428aad8SPatrick Mooney 	newseg->s_data = newsud;
1742428aad8SPatrick Mooney 	return (0);
1752428aad8SPatrick Mooney }
1762428aad8SPatrick Mooney 
1772428aad8SPatrick Mooney static int
segumap_unmap(struct seg * seg,caddr_t addr,size_t len)1782428aad8SPatrick Mooney segumap_unmap(struct seg *seg, caddr_t addr, size_t len)
1792428aad8SPatrick Mooney {
1802428aad8SPatrick Mooney 	segumap_data_t *sud = (segumap_data_t *)seg->s_data;
1812428aad8SPatrick Mooney 
1822428aad8SPatrick Mooney 	ASSERT(seg->s_as && AS_WRITE_HELD(seg->s_as));
1832428aad8SPatrick Mooney 
1842428aad8SPatrick Mooney 	/* Only allow unmap of entire segment */
1852428aad8SPatrick Mooney 	if (addr != seg->s_base || len != seg->s_size) {
1862428aad8SPatrick Mooney 		return (EINVAL);
1872428aad8SPatrick Mooney 	}
1882428aad8SPatrick Mooney 	if (sud->sud_softlockcnt != 0) {
1892428aad8SPatrick Mooney 		return (EAGAIN);
1902428aad8SPatrick Mooney 	}
1912428aad8SPatrick Mooney 
1922428aad8SPatrick Mooney 	/*
1932428aad8SPatrick Mooney 	 * Unconditionally unload the entire segment range.
1942428aad8SPatrick Mooney 	 */
1952428aad8SPatrick Mooney 	hat_unload(seg->s_as->a_hat, addr, len, HAT_UNLOAD_UNMAP);
1962428aad8SPatrick Mooney 
1972428aad8SPatrick Mooney 	seg_free(seg);
1982428aad8SPatrick Mooney 	return (0);
1992428aad8SPatrick Mooney }
2002428aad8SPatrick Mooney 
2012428aad8SPatrick Mooney static void
segumap_free(struct seg * seg)2022428aad8SPatrick Mooney segumap_free(struct seg *seg)
2032428aad8SPatrick Mooney {
2042428aad8SPatrick Mooney 	segumap_data_t *data = (segumap_data_t *)seg->s_data;
2052428aad8SPatrick Mooney 
2062428aad8SPatrick Mooney 	ASSERT(data != NULL);
2072428aad8SPatrick Mooney 
2082428aad8SPatrick Mooney 	rw_destroy(&data->sud_lock);
2092428aad8SPatrick Mooney 	VERIFY(data->sud_softlockcnt == 0);
2102428aad8SPatrick Mooney 	kmem_free(data, sizeof (*data));
2112428aad8SPatrick Mooney 	seg->s_data = NULL;
2122428aad8SPatrick Mooney }
2132428aad8SPatrick Mooney 
2142428aad8SPatrick Mooney /* ARGSUSED */
2152428aad8SPatrick Mooney static faultcode_t
segumap_fault(struct hat * hat,struct seg * seg,caddr_t addr,size_t len,enum fault_type type,enum seg_rw tw)2162428aad8SPatrick Mooney segumap_fault(struct hat *hat, struct seg *seg, caddr_t addr, size_t len,
2172428aad8SPatrick Mooney     enum fault_type type, enum seg_rw tw)
2182428aad8SPatrick Mooney {
2192428aad8SPatrick Mooney 	segumap_data_t *sud = (segumap_data_t *)seg->s_data;
2202428aad8SPatrick Mooney 
2212428aad8SPatrick Mooney 	ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
2222428aad8SPatrick Mooney 
2232428aad8SPatrick Mooney 	if (type == F_PROT) {
2242428aad8SPatrick Mooney 		/*
2252428aad8SPatrick Mooney 		 * Since protection on the segment is fixed, there is nothing
2262428aad8SPatrick Mooney 		 * to do but report an error for protection faults.
2272428aad8SPatrick Mooney 		 */
2282428aad8SPatrick Mooney 		return (FC_PROT);
2292428aad8SPatrick Mooney 	} else if (type == F_SOFTUNLOCK) {
2302428aad8SPatrick Mooney 		size_t plen = btop(len);
2312428aad8SPatrick Mooney 
2322428aad8SPatrick Mooney 		rw_enter(&sud->sud_lock, RW_WRITER);
2332428aad8SPatrick Mooney 		VERIFY(sud->sud_softlockcnt >= plen);
2342428aad8SPatrick Mooney 		sud->sud_softlockcnt -= plen;
2352428aad8SPatrick Mooney 		rw_exit(&sud->sud_lock);
2362428aad8SPatrick Mooney 		return (0);
2372428aad8SPatrick Mooney 	}
2382428aad8SPatrick Mooney 
2392428aad8SPatrick Mooney 	ASSERT(type == F_INVAL || type == F_SOFTLOCK);
2402428aad8SPatrick Mooney 	rw_enter(&sud->sud_lock, RW_WRITER);
2412428aad8SPatrick Mooney 
2422428aad8SPatrick Mooney 	if (type == F_INVAL ||
2432428aad8SPatrick Mooney 	    (type == F_SOFTLOCK && sud->sud_softlockcnt == 0)) {
2442428aad8SPatrick Mooney 		/*
2452428aad8SPatrick Mooney 		 * Load the (entire) segment into the HAT.
2462428aad8SPatrick Mooney 		 *
2472428aad8SPatrick Mooney 		 * It's possible that threads racing into as_fault will cause
2482428aad8SPatrick Mooney 		 * seg_umap to load the same range multiple times in quick
2492428aad8SPatrick Mooney 		 * succession.  Redundant hat_devload operations are safe.
2502428aad8SPatrick Mooney 		 */
2512428aad8SPatrick Mooney 		for (uintptr_t i = 0; i < seg->s_size; i += PAGESIZE) {
2522428aad8SPatrick Mooney 			pfn_t pfn;
2532428aad8SPatrick Mooney 
2542428aad8SPatrick Mooney 			pfn = hat_getpfnum(kas.a_hat, sud->sud_kaddr + i);
2552428aad8SPatrick Mooney 			VERIFY(pfn != PFN_INVALID);
2562428aad8SPatrick Mooney 			hat_devload(seg->s_as->a_hat, seg->s_base + i,
2572428aad8SPatrick Mooney 			    PAGESIZE, pfn, sud->sud_prot, HAT_LOAD);
2582428aad8SPatrick Mooney 		}
2592428aad8SPatrick Mooney 	}
2602428aad8SPatrick Mooney 	if (type == F_SOFTLOCK) {
2612428aad8SPatrick Mooney 		size_t nval = sud->sud_softlockcnt + btop(len);
2622428aad8SPatrick Mooney 
2632428aad8SPatrick Mooney 		if (sud->sud_softlockcnt >= nval) {
2642428aad8SPatrick Mooney 			rw_exit(&sud->sud_lock);
2652428aad8SPatrick Mooney 			return (FC_MAKE_ERR(EOVERFLOW));
2662428aad8SPatrick Mooney 		}
2672428aad8SPatrick Mooney 		sud->sud_softlockcnt = nval;
2682428aad8SPatrick Mooney 	}
2692428aad8SPatrick Mooney 
2702428aad8SPatrick Mooney 	rw_exit(&sud->sud_lock);
2712428aad8SPatrick Mooney 	return (0);
2722428aad8SPatrick Mooney }
2732428aad8SPatrick Mooney 
2742428aad8SPatrick Mooney /* ARGSUSED */
2752428aad8SPatrick Mooney static faultcode_t
segumap_faulta(struct seg * seg,caddr_t addr)2762428aad8SPatrick Mooney segumap_faulta(struct seg *seg, caddr_t addr)
2772428aad8SPatrick Mooney {
2782428aad8SPatrick Mooney 	/* Do nothing since asynch pagefault should not load translation. */
2792428aad8SPatrick Mooney 	return (0);
2802428aad8SPatrick Mooney }
2812428aad8SPatrick Mooney 
2822428aad8SPatrick Mooney /* ARGSUSED */
2832428aad8SPatrick Mooney static int
segumap_setprot(struct seg * seg,caddr_t addr,size_t len,uint_t prot)2842428aad8SPatrick Mooney segumap_setprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot)
2852428aad8SPatrick Mooney {
2862428aad8SPatrick Mooney 	ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
2872428aad8SPatrick Mooney 
2882428aad8SPatrick Mooney 	/*
2892428aad8SPatrick Mooney 	 * The seg_umap driver does not yet allow protection to be changed.
2902428aad8SPatrick Mooney 	 */
2912428aad8SPatrick Mooney 	return (EACCES);
2922428aad8SPatrick Mooney }
2932428aad8SPatrick Mooney 
2942428aad8SPatrick Mooney /* ARGSUSED */
2952428aad8SPatrick Mooney static int
segumap_checkprot(struct seg * seg,caddr_t addr,size_t len,uint_t prot)2962428aad8SPatrick Mooney segumap_checkprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot)
2972428aad8SPatrick Mooney {
2982428aad8SPatrick Mooney 	segumap_data_t *sud = (segumap_data_t *)seg->s_data;
2992428aad8SPatrick Mooney 	int error = 0;
3002428aad8SPatrick Mooney 
3012428aad8SPatrick Mooney 	ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
3022428aad8SPatrick Mooney 
3032428aad8SPatrick Mooney 	rw_enter(&sud->sud_lock, RW_READER);
3042428aad8SPatrick Mooney 	if ((sud->sud_prot & prot) != prot) {
3052428aad8SPatrick Mooney 		error = EACCES;
3062428aad8SPatrick Mooney 	}
3072428aad8SPatrick Mooney 	rw_exit(&sud->sud_lock);
3082428aad8SPatrick Mooney 	return (error);
3092428aad8SPatrick Mooney }
3102428aad8SPatrick Mooney 
3112428aad8SPatrick Mooney /* ARGSUSED */
3122428aad8SPatrick Mooney static int
segumap_sync(struct seg * seg,caddr_t addr,size_t len,int attr,uint_t flags)3132428aad8SPatrick Mooney segumap_sync(struct seg *seg, caddr_t addr, size_t len, int attr, uint_t flags)
3142428aad8SPatrick Mooney {
3152428aad8SPatrick Mooney 	/* Always succeed since there are no backing store to sync */
3162428aad8SPatrick Mooney 	return (0);
3172428aad8SPatrick Mooney }
3182428aad8SPatrick Mooney 
3192428aad8SPatrick Mooney /* ARGSUSED */
3202428aad8SPatrick Mooney static size_t
segumap_incore(struct seg * seg,caddr_t addr,size_t len,char * vec)3212428aad8SPatrick Mooney segumap_incore(struct seg *seg, caddr_t addr, size_t len, char *vec)
3222428aad8SPatrick Mooney {
3232428aad8SPatrick Mooney 	size_t sz = 0;
3242428aad8SPatrick Mooney 
3252428aad8SPatrick Mooney 	ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
3262428aad8SPatrick Mooney 
3272428aad8SPatrick Mooney 	len = (len + PAGEOFFSET) & PAGEMASK;
3282428aad8SPatrick Mooney 	while (len > 0) {
3292428aad8SPatrick Mooney 		*vec = 1;
3302428aad8SPatrick Mooney 		sz += PAGESIZE;
3312428aad8SPatrick Mooney 		vec++;
3322428aad8SPatrick Mooney 		len -= PAGESIZE;
3332428aad8SPatrick Mooney 	}
3342428aad8SPatrick Mooney 	return (sz);
3352428aad8SPatrick Mooney }
3362428aad8SPatrick Mooney 
3372428aad8SPatrick Mooney /* ARGSUSED */
3382428aad8SPatrick Mooney static int
segumap_lockop(struct seg * seg,caddr_t addr,size_t len,int attr,int op,ulong_t * lockmap,size_t pos)3392428aad8SPatrick Mooney segumap_lockop(struct seg *seg, caddr_t addr, size_t len, int attr, int op,
3402428aad8SPatrick Mooney     ulong_t *lockmap, size_t pos)
3412428aad8SPatrick Mooney {
3422428aad8SPatrick Mooney 	/* Report success since kernel pages are always in memory. */
3432428aad8SPatrick Mooney 	return (0);
3442428aad8SPatrick Mooney }
3452428aad8SPatrick Mooney 
3462428aad8SPatrick Mooney static int
segumap_getprot(struct seg * seg,caddr_t addr,size_t len,uint_t * protv)3472428aad8SPatrick Mooney segumap_getprot(struct seg *seg, caddr_t addr, size_t len, uint_t *protv)
3482428aad8SPatrick Mooney {
3492428aad8SPatrick Mooney 	segumap_data_t *sud = (segumap_data_t *)seg->s_data;
3502428aad8SPatrick Mooney 	size_t pgno;
3512428aad8SPatrick Mooney 	uint_t prot;
3522428aad8SPatrick Mooney 
3532428aad8SPatrick Mooney 	ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
3542428aad8SPatrick Mooney 
3552428aad8SPatrick Mooney 	rw_enter(&sud->sud_lock, RW_READER);
3562428aad8SPatrick Mooney 	prot = sud->sud_prot;
3572428aad8SPatrick Mooney 	rw_exit(&sud->sud_lock);
3582428aad8SPatrick Mooney 
3592428aad8SPatrick Mooney 	/*
3602428aad8SPatrick Mooney 	 * Reporting protection is simple since it is not tracked per-page.
3612428aad8SPatrick Mooney 	 */
3622428aad8SPatrick Mooney 	pgno = seg_page(seg, addr + len) - seg_page(seg, addr) + 1;
3632428aad8SPatrick Mooney 	while (pgno > 0) {
3642428aad8SPatrick Mooney 		protv[--pgno] = prot;
3652428aad8SPatrick Mooney 	}
3662428aad8SPatrick Mooney 	return (0);
3672428aad8SPatrick Mooney }
3682428aad8SPatrick Mooney 
3692428aad8SPatrick Mooney /* ARGSUSED */
3702428aad8SPatrick Mooney static u_offset_t
segumap_getoffset(struct seg * seg,caddr_t addr)3712428aad8SPatrick Mooney segumap_getoffset(struct seg *seg, caddr_t addr)
3722428aad8SPatrick Mooney {
3732428aad8SPatrick Mooney 	/*
3742428aad8SPatrick Mooney 	 * To avoid leaking information about the layout of the kernel address
3752428aad8SPatrick Mooney 	 * space, always report '0' as the offset.
3762428aad8SPatrick Mooney 	 */
3772428aad8SPatrick Mooney 	return (0);
3782428aad8SPatrick Mooney }
3792428aad8SPatrick Mooney 
3802428aad8SPatrick Mooney /* ARGSUSED */
3812428aad8SPatrick Mooney static int
segumap_gettype(struct seg * seg,caddr_t addr)3822428aad8SPatrick Mooney segumap_gettype(struct seg *seg, caddr_t addr)
3832428aad8SPatrick Mooney {
3842428aad8SPatrick Mooney 	/*
3852428aad8SPatrick Mooney 	 * Since already-existing kernel pages are being mapped into userspace,
3862428aad8SPatrick Mooney 	 * always report the segment type as shared.
3872428aad8SPatrick Mooney 	 */
3882428aad8SPatrick Mooney 	return (MAP_SHARED);
3892428aad8SPatrick Mooney }
3902428aad8SPatrick Mooney 
3912428aad8SPatrick Mooney /* ARGSUSED */
3922428aad8SPatrick Mooney static int
segumap_getvp(struct seg * seg,caddr_t addr,struct vnode ** vpp)3932428aad8SPatrick Mooney segumap_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp)
3942428aad8SPatrick Mooney {
3952428aad8SPatrick Mooney 	ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
3962428aad8SPatrick Mooney 
3972428aad8SPatrick Mooney 	*vpp = NULL;
3982428aad8SPatrick Mooney 	return (0);
3992428aad8SPatrick Mooney }
4002428aad8SPatrick Mooney 
4012428aad8SPatrick Mooney /* ARGSUSED */
4022428aad8SPatrick Mooney static int
segumap_advise(struct seg * seg,caddr_t addr,size_t len,uint_t behav)4032428aad8SPatrick Mooney segumap_advise(struct seg *seg, caddr_t addr, size_t len, uint_t behav)
4042428aad8SPatrick Mooney {
4052428aad8SPatrick Mooney 	if (behav == MADV_PURGE) {
4062428aad8SPatrick Mooney 		/* Purge does not make sense for this mapping */
4072428aad8SPatrick Mooney 		return (EINVAL);
4082428aad8SPatrick Mooney 	}
4092428aad8SPatrick Mooney 	/* Indicate success for everything else. */
4102428aad8SPatrick Mooney 	return (0);
4112428aad8SPatrick Mooney }
4122428aad8SPatrick Mooney 
4132428aad8SPatrick Mooney /* ARGSUSED */
4142428aad8SPatrick Mooney static void
segumap_dump(struct seg * seg)4152428aad8SPatrick Mooney segumap_dump(struct seg *seg)
4162428aad8SPatrick Mooney {
4172428aad8SPatrick Mooney 	/*
4182428aad8SPatrick Mooney 	 * Since this is a mapping to share kernel data with userspace, nothing
4192428aad8SPatrick Mooney 	 * additional should be dumped.
4202428aad8SPatrick Mooney 	 */
4212428aad8SPatrick Mooney }
4222428aad8SPatrick Mooney 
4232428aad8SPatrick Mooney /* ARGSUSED */
4242428aad8SPatrick Mooney static int
segumap_pagelock(struct seg * seg,caddr_t addr,size_t len,struct page *** ppp,enum lock_type type,enum seg_rw rw)4252428aad8SPatrick Mooney segumap_pagelock(struct seg *seg, caddr_t addr, size_t len, struct page ***ppp,
4262428aad8SPatrick Mooney     enum lock_type type, enum seg_rw rw)
4272428aad8SPatrick Mooney {
4282428aad8SPatrick Mooney 	return (ENOTSUP);
4292428aad8SPatrick Mooney }
4302428aad8SPatrick Mooney 
4312428aad8SPatrick Mooney /* ARGSUSED */
4322428aad8SPatrick Mooney static int
segumap_setpagesize(struct seg * seg,caddr_t addr,size_t len,uint_t szc)4332428aad8SPatrick Mooney segumap_setpagesize(struct seg *seg, caddr_t addr, size_t len, uint_t szc)
4342428aad8SPatrick Mooney {
4352428aad8SPatrick Mooney 	return (ENOTSUP);
4362428aad8SPatrick Mooney }
4372428aad8SPatrick Mooney 
4382428aad8SPatrick Mooney static int
segumap_getmemid(struct seg * seg,caddr_t addr,memid_t * memidp)4392428aad8SPatrick Mooney segumap_getmemid(struct seg *seg, caddr_t addr, memid_t *memidp)
4402428aad8SPatrick Mooney {
4412428aad8SPatrick Mooney 	segumap_data_t *sud = (segumap_data_t *)seg->s_data;
4422428aad8SPatrick Mooney 
4432428aad8SPatrick Mooney 	memidp->val[0] = (uintptr_t)sud->sud_kaddr;
4442428aad8SPatrick Mooney 	memidp->val[1] = (uintptr_t)(addr - seg->s_base);
4452428aad8SPatrick Mooney 	return (0);
4462428aad8SPatrick Mooney }
4472428aad8SPatrick Mooney 
4482428aad8SPatrick Mooney /* ARGSUSED */
4492428aad8SPatrick Mooney static int
segumap_capable(struct seg * seg,segcapability_t capability)4502428aad8SPatrick Mooney segumap_capable(struct seg *seg, segcapability_t capability)
4512428aad8SPatrick Mooney {
4522428aad8SPatrick Mooney 	/* no special capablities */
4532428aad8SPatrick Mooney 	return (0);
4542428aad8SPatrick Mooney }
455