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