1*263f549eSPatrick Mooney /* 2*263f549eSPatrick Mooney * This file and its contents are supplied under the terms of the 3*263f549eSPatrick Mooney * Common Development and Distribution License ("CDDL"), version 1.0. 4*263f549eSPatrick Mooney * You may only use this file in accordance with the terms of version 5*263f549eSPatrick Mooney * 1.0 of the CDDL. 6*263f549eSPatrick Mooney * 7*263f549eSPatrick Mooney * A full copy of the text of the CDDL should have accompanied this 8*263f549eSPatrick Mooney * source. A copy of the CDDL is also available via the Internet at 9*263f549eSPatrick Mooney * http://www.illumos.org/license/CDDL. 10*263f549eSPatrick Mooney */ 11*263f549eSPatrick Mooney 12*263f549eSPatrick Mooney /* 13*263f549eSPatrick Mooney * Copyright 2016 Joyent, Inc. 14*263f549eSPatrick Mooney */ 15*263f549eSPatrick Mooney 16*263f549eSPatrick Mooney /* 17*263f549eSPatrick Mooney * VM - Kernel-to-user mapping segment 18*263f549eSPatrick Mooney * 19*263f549eSPatrick Mooney * The umap segment driver was primarily designed to facilitate the comm page: 20*263f549eSPatrick Mooney * a portion of kernel memory shared with userspace so that certain (namely 21*263f549eSPatrick Mooney * clock-related) actions could operate without making an expensive trip into 22*263f549eSPatrick Mooney * the kernel. 23*263f549eSPatrick Mooney * 24*263f549eSPatrick Mooney * Since the initial requirements for the comm page are slim, advanced features 25*263f549eSPatrick Mooney * of the segment driver such as per-page protection have been left 26*263f549eSPatrick Mooney * unimplemented at this time. 27*263f549eSPatrick Mooney */ 28*263f549eSPatrick Mooney 29*263f549eSPatrick Mooney 30*263f549eSPatrick Mooney #include <sys/types.h> 31*263f549eSPatrick Mooney #include <sys/param.h> 32*263f549eSPatrick Mooney #include <sys/errno.h> 33*263f549eSPatrick Mooney #include <sys/cred.h> 34*263f549eSPatrick Mooney #include <sys/kmem.h> 35*263f549eSPatrick Mooney #include <sys/lgrp.h> 36*263f549eSPatrick Mooney #include <sys/mman.h> 37*263f549eSPatrick Mooney 38*263f549eSPatrick Mooney #include <vm/hat.h> 39*263f549eSPatrick Mooney #include <vm/as.h> 40*263f549eSPatrick Mooney #include <vm/seg.h> 41*263f549eSPatrick Mooney #include <vm/seg_kmem.h> 42*263f549eSPatrick Mooney #include <vm/seg_umap.h> 43*263f549eSPatrick Mooney 44*263f549eSPatrick Mooney 45*263f549eSPatrick Mooney static boolean_t segumap_verify_safe(caddr_t, size_t); 46*263f549eSPatrick Mooney static int segumap_dup(struct seg *, struct seg *); 47*263f549eSPatrick Mooney static int segumap_unmap(struct seg *, caddr_t, size_t); 48*263f549eSPatrick Mooney static void segumap_free(struct seg *); 49*263f549eSPatrick Mooney static faultcode_t segumap_fault(struct hat *, struct seg *, caddr_t, size_t, 50*263f549eSPatrick Mooney enum fault_type, enum seg_rw); 51*263f549eSPatrick Mooney static faultcode_t segumap_faulta(struct seg *, caddr_t); 52*263f549eSPatrick Mooney static int segumap_setprot(struct seg *, caddr_t, size_t, uint_t); 53*263f549eSPatrick Mooney static int segumap_checkprot(struct seg *, caddr_t, size_t, uint_t); 54*263f549eSPatrick Mooney static int segumap_sync(struct seg *, caddr_t, size_t, int, uint_t); 55*263f549eSPatrick Mooney static size_t segumap_incore(struct seg *, caddr_t, size_t, char *); 56*263f549eSPatrick Mooney static int segumap_lockop(struct seg *, caddr_t, size_t, int, int, ulong_t *, 57*263f549eSPatrick Mooney size_t); 58*263f549eSPatrick Mooney static int segumap_getprot(struct seg *, caddr_t, size_t, uint_t *); 59*263f549eSPatrick Mooney static u_offset_t segumap_getoffset(struct seg *, caddr_t); 60*263f549eSPatrick Mooney static int segumap_gettype(struct seg *, caddr_t); 61*263f549eSPatrick Mooney static int segumap_getvp(struct seg *, caddr_t, struct vnode **); 62*263f549eSPatrick Mooney static int segumap_advise(struct seg *, caddr_t, size_t, uint_t); 63*263f549eSPatrick Mooney static void segumap_dump(struct seg *); 64*263f549eSPatrick Mooney static int segumap_pagelock(struct seg *, caddr_t, size_t, struct page ***, 65*263f549eSPatrick Mooney enum lock_type, enum seg_rw); 66*263f549eSPatrick Mooney static int segumap_setpagesize(struct seg *, caddr_t, size_t, uint_t); 67*263f549eSPatrick Mooney static int segumap_getmemid(struct seg *, caddr_t, memid_t *); 68*263f549eSPatrick Mooney static int segumap_capable(struct seg *, segcapability_t); 69*263f549eSPatrick Mooney 70*263f549eSPatrick Mooney static struct seg_ops segumap_ops = { 71*263f549eSPatrick Mooney segumap_dup, 72*263f549eSPatrick Mooney segumap_unmap, 73*263f549eSPatrick Mooney segumap_free, 74*263f549eSPatrick Mooney segumap_fault, 75*263f549eSPatrick Mooney segumap_faulta, 76*263f549eSPatrick Mooney segumap_setprot, 77*263f549eSPatrick Mooney segumap_checkprot, 78*263f549eSPatrick Mooney NULL, /* kluster: disabled */ 79*263f549eSPatrick Mooney NULL, /* swapout: disabled */ 80*263f549eSPatrick Mooney segumap_sync, 81*263f549eSPatrick Mooney segumap_incore, 82*263f549eSPatrick Mooney segumap_lockop, 83*263f549eSPatrick Mooney segumap_getprot, 84*263f549eSPatrick Mooney segumap_getoffset, 85*263f549eSPatrick Mooney segumap_gettype, 86*263f549eSPatrick Mooney segumap_getvp, 87*263f549eSPatrick Mooney segumap_advise, 88*263f549eSPatrick Mooney segumap_dump, 89*263f549eSPatrick Mooney segumap_pagelock, 90*263f549eSPatrick Mooney segumap_setpagesize, 91*263f549eSPatrick Mooney segumap_getmemid, 92*263f549eSPatrick Mooney NULL, /* getpolicy: disabled */ 93*263f549eSPatrick Mooney segumap_capable, 94*263f549eSPatrick Mooney seg_inherit_notsup 95*263f549eSPatrick Mooney }; 96*263f549eSPatrick Mooney 97*263f549eSPatrick Mooney 98*263f549eSPatrick Mooney /* 99*263f549eSPatrick Mooney * Create a kernel/user-mapped segment. 100*263f549eSPatrick Mooney */ 101*263f549eSPatrick Mooney int 102*263f549eSPatrick Mooney segumap_create(struct seg *seg, void *argsp) 103*263f549eSPatrick Mooney { 104*263f549eSPatrick Mooney segumap_crargs_t *a = (struct segumap_crargs *)argsp; 105*263f549eSPatrick Mooney segumap_data_t *data; 106*263f549eSPatrick Mooney 107*263f549eSPatrick Mooney ASSERT((uintptr_t)a->kaddr > _userlimit); 108*263f549eSPatrick Mooney 109*263f549eSPatrick Mooney /* 110*263f549eSPatrick Mooney * Check several aspects of the mapping request to ensure validity: 111*263f549eSPatrick Mooney * - kernel pages must reside entirely in kernel space 112*263f549eSPatrick Mooney * - target protection must be user-accessible 113*263f549eSPatrick Mooney * - kernel address must be page-aligned 114*263f549eSPatrick Mooney * - kernel address must reside inside a "safe" segment 115*263f549eSPatrick Mooney */ 116*263f549eSPatrick Mooney if ((uintptr_t)a->kaddr <= _userlimit || 117*263f549eSPatrick Mooney ((uintptr_t)a->kaddr + seg->s_size) < (uintptr_t)a->kaddr || 118*263f549eSPatrick Mooney (a->prot & PROT_USER) == 0 || 119*263f549eSPatrick Mooney ((uintptr_t)a->kaddr & PAGEOFFSET) != 0 || 120*263f549eSPatrick Mooney !segumap_verify_safe(a->kaddr, seg->s_size)) { 121*263f549eSPatrick Mooney return (EINVAL); 122*263f549eSPatrick Mooney } 123*263f549eSPatrick Mooney 124*263f549eSPatrick Mooney data = kmem_zalloc(sizeof (*data), KM_SLEEP); 125*263f549eSPatrick Mooney rw_init(&data->sud_lock, NULL, RW_DEFAULT, NULL); 126*263f549eSPatrick Mooney data->sud_kaddr = a->kaddr; 127*263f549eSPatrick Mooney data->sud_prot = a->prot; 128*263f549eSPatrick Mooney 129*263f549eSPatrick Mooney seg->s_ops = &segumap_ops; 130*263f549eSPatrick Mooney seg->s_data = data; 131*263f549eSPatrick Mooney return (0); 132*263f549eSPatrick Mooney } 133*263f549eSPatrick Mooney 134*263f549eSPatrick Mooney static boolean_t 135*263f549eSPatrick Mooney segumap_verify_safe(caddr_t kaddr, size_t len) 136*263f549eSPatrick Mooney { 137*263f549eSPatrick Mooney struct seg *seg; 138*263f549eSPatrick Mooney 139*263f549eSPatrick Mooney /* 140*263f549eSPatrick Mooney * Presently, only pages which are backed by segkmem are allowed to be 141*263f549eSPatrick Mooney * shared with userspace. This prevents nasty paging behavior with 142*263f549eSPatrick Mooney * other drivers such as seg_kp. Furthermore, the backing kernel 143*263f549eSPatrick Mooney * segment must completely contain the region to be mapped. 144*263f549eSPatrick Mooney * 145*263f549eSPatrick Mooney * Failing these checks is fatal for now since such mappings are done 146*263f549eSPatrick Mooney * in a very limited context from the kernel. 147*263f549eSPatrick Mooney */ 148*263f549eSPatrick Mooney AS_LOCK_ENTER(&kas, RW_READER); 149*263f549eSPatrick Mooney seg = as_segat(&kas, kaddr); 150*263f549eSPatrick Mooney VERIFY(seg != NULL); 151*263f549eSPatrick Mooney VERIFY(seg->s_base + seg->s_size >= kaddr + len); 152*263f549eSPatrick Mooney VERIFY(seg->s_ops == &segkmem_ops); 153*263f549eSPatrick Mooney AS_LOCK_EXIT(&kas); 154*263f549eSPatrick Mooney 155*263f549eSPatrick Mooney return (B_TRUE); 156*263f549eSPatrick Mooney } 157*263f549eSPatrick Mooney 158*263f549eSPatrick Mooney static int 159*263f549eSPatrick Mooney segumap_dup(struct seg *seg, struct seg *newseg) 160*263f549eSPatrick Mooney { 161*263f549eSPatrick Mooney segumap_data_t *sud = (segumap_data_t *)seg->s_data; 162*263f549eSPatrick Mooney segumap_data_t *newsud; 163*263f549eSPatrick Mooney 164*263f549eSPatrick Mooney ASSERT(seg->s_as && AS_WRITE_HELD(seg->s_as)); 165*263f549eSPatrick Mooney 166*263f549eSPatrick Mooney newsud = kmem_zalloc(sizeof (segumap_data_t), KM_SLEEP); 167*263f549eSPatrick Mooney rw_init(&newsud->sud_lock, NULL, RW_DEFAULT, NULL); 168*263f549eSPatrick Mooney newsud->sud_kaddr = sud->sud_kaddr; 169*263f549eSPatrick Mooney newsud->sud_prot = sud->sud_prot; 170*263f549eSPatrick Mooney 171*263f549eSPatrick Mooney newseg->s_ops = seg->s_ops; 172*263f549eSPatrick Mooney newseg->s_data = newsud; 173*263f549eSPatrick Mooney return (0); 174*263f549eSPatrick Mooney } 175*263f549eSPatrick Mooney 176*263f549eSPatrick Mooney static int 177*263f549eSPatrick Mooney segumap_unmap(struct seg *seg, caddr_t addr, size_t len) 178*263f549eSPatrick Mooney { 179*263f549eSPatrick Mooney segumap_data_t *sud = (segumap_data_t *)seg->s_data; 180*263f549eSPatrick Mooney 181*263f549eSPatrick Mooney ASSERT(seg->s_as && AS_WRITE_HELD(seg->s_as)); 182*263f549eSPatrick Mooney 183*263f549eSPatrick Mooney /* Only allow unmap of entire segment */ 184*263f549eSPatrick Mooney if (addr != seg->s_base || len != seg->s_size) { 185*263f549eSPatrick Mooney return (EINVAL); 186*263f549eSPatrick Mooney } 187*263f549eSPatrick Mooney if (sud->sud_softlockcnt != 0) { 188*263f549eSPatrick Mooney return (EAGAIN); 189*263f549eSPatrick Mooney } 190*263f549eSPatrick Mooney 191*263f549eSPatrick Mooney /* 192*263f549eSPatrick Mooney * Unconditionally unload the entire segment range. 193*263f549eSPatrick Mooney */ 194*263f549eSPatrick Mooney hat_unload(seg->s_as->a_hat, addr, len, HAT_UNLOAD_UNMAP); 195*263f549eSPatrick Mooney 196*263f549eSPatrick Mooney seg_free(seg); 197*263f549eSPatrick Mooney return (0); 198*263f549eSPatrick Mooney } 199*263f549eSPatrick Mooney 200*263f549eSPatrick Mooney static void 201*263f549eSPatrick Mooney segumap_free(struct seg *seg) 202*263f549eSPatrick Mooney { 203*263f549eSPatrick Mooney segumap_data_t *data = (segumap_data_t *)seg->s_data; 204*263f549eSPatrick Mooney 205*263f549eSPatrick Mooney ASSERT(data != NULL); 206*263f549eSPatrick Mooney 207*263f549eSPatrick Mooney rw_destroy(&data->sud_lock); 208*263f549eSPatrick Mooney VERIFY(data->sud_softlockcnt == 0); 209*263f549eSPatrick Mooney kmem_free(data, sizeof (*data)); 210*263f549eSPatrick Mooney seg->s_data = NULL; 211*263f549eSPatrick Mooney } 212*263f549eSPatrick Mooney 213*263f549eSPatrick Mooney /* ARGSUSED */ 214*263f549eSPatrick Mooney static faultcode_t 215*263f549eSPatrick Mooney segumap_fault(struct hat *hat, struct seg *seg, caddr_t addr, size_t len, 216*263f549eSPatrick Mooney enum fault_type type, enum seg_rw tw) 217*263f549eSPatrick Mooney { 218*263f549eSPatrick Mooney segumap_data_t *sud = (segumap_data_t *)seg->s_data; 219*263f549eSPatrick Mooney 220*263f549eSPatrick Mooney ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); 221*263f549eSPatrick Mooney 222*263f549eSPatrick Mooney if (type == F_PROT) { 223*263f549eSPatrick Mooney /* 224*263f549eSPatrick Mooney * Since protection on the segment is fixed, there is nothing 225*263f549eSPatrick Mooney * to do but report an error for protection faults. 226*263f549eSPatrick Mooney */ 227*263f549eSPatrick Mooney return (FC_PROT); 228*263f549eSPatrick Mooney } else if (type == F_SOFTUNLOCK) { 229*263f549eSPatrick Mooney size_t plen = btop(len); 230*263f549eSPatrick Mooney 231*263f549eSPatrick Mooney rw_enter(&sud->sud_lock, RW_WRITER); 232*263f549eSPatrick Mooney VERIFY(sud->sud_softlockcnt >= plen); 233*263f549eSPatrick Mooney sud->sud_softlockcnt -= plen; 234*263f549eSPatrick Mooney rw_exit(&sud->sud_lock); 235*263f549eSPatrick Mooney return (0); 236*263f549eSPatrick Mooney } 237*263f549eSPatrick Mooney 238*263f549eSPatrick Mooney ASSERT(type == F_INVAL || type == F_SOFTLOCK); 239*263f549eSPatrick Mooney rw_enter(&sud->sud_lock, RW_WRITER); 240*263f549eSPatrick Mooney 241*263f549eSPatrick Mooney if (type == F_INVAL || 242*263f549eSPatrick Mooney (type == F_SOFTLOCK && sud->sud_softlockcnt == 0)) { 243*263f549eSPatrick Mooney /* 244*263f549eSPatrick Mooney * Load the (entire) segment into the HAT. 245*263f549eSPatrick Mooney * 246*263f549eSPatrick Mooney * It's possible that threads racing into as_fault will cause 247*263f549eSPatrick Mooney * seg_umap to load the same range multiple times in quick 248*263f549eSPatrick Mooney * succession. Redundant hat_devload operations are safe. 249*263f549eSPatrick Mooney */ 250*263f549eSPatrick Mooney for (uintptr_t i = 0; i < seg->s_size; i += PAGESIZE) { 251*263f549eSPatrick Mooney pfn_t pfn; 252*263f549eSPatrick Mooney 253*263f549eSPatrick Mooney pfn = hat_getpfnum(kas.a_hat, sud->sud_kaddr + i); 254*263f549eSPatrick Mooney VERIFY(pfn != PFN_INVALID); 255*263f549eSPatrick Mooney hat_devload(seg->s_as->a_hat, seg->s_base + i, 256*263f549eSPatrick Mooney PAGESIZE, pfn, sud->sud_prot, HAT_LOAD); 257*263f549eSPatrick Mooney } 258*263f549eSPatrick Mooney } 259*263f549eSPatrick Mooney if (type == F_SOFTLOCK) { 260*263f549eSPatrick Mooney size_t nval = sud->sud_softlockcnt + btop(len); 261*263f549eSPatrick Mooney 262*263f549eSPatrick Mooney if (sud->sud_softlockcnt >= nval) { 263*263f549eSPatrick Mooney rw_exit(&sud->sud_lock); 264*263f549eSPatrick Mooney return (FC_MAKE_ERR(EOVERFLOW)); 265*263f549eSPatrick Mooney } 266*263f549eSPatrick Mooney sud->sud_softlockcnt = nval; 267*263f549eSPatrick Mooney } 268*263f549eSPatrick Mooney 269*263f549eSPatrick Mooney rw_exit(&sud->sud_lock); 270*263f549eSPatrick Mooney return (0); 271*263f549eSPatrick Mooney } 272*263f549eSPatrick Mooney 273*263f549eSPatrick Mooney /* ARGSUSED */ 274*263f549eSPatrick Mooney static faultcode_t 275*263f549eSPatrick Mooney segumap_faulta(struct seg *seg, caddr_t addr) 276*263f549eSPatrick Mooney { 277*263f549eSPatrick Mooney /* Do nothing since asynch pagefault should not load translation. */ 278*263f549eSPatrick Mooney return (0); 279*263f549eSPatrick Mooney } 280*263f549eSPatrick Mooney 281*263f549eSPatrick Mooney /* ARGSUSED */ 282*263f549eSPatrick Mooney static int 283*263f549eSPatrick Mooney segumap_setprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot) 284*263f549eSPatrick Mooney { 285*263f549eSPatrick Mooney ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); 286*263f549eSPatrick Mooney 287*263f549eSPatrick Mooney /* 288*263f549eSPatrick Mooney * The seg_umap driver does not yet allow protection to be changed. 289*263f549eSPatrick Mooney */ 290*263f549eSPatrick Mooney return (EACCES); 291*263f549eSPatrick Mooney } 292*263f549eSPatrick Mooney 293*263f549eSPatrick Mooney /* ARGSUSED */ 294*263f549eSPatrick Mooney static int 295*263f549eSPatrick Mooney segumap_checkprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot) 296*263f549eSPatrick Mooney { 297*263f549eSPatrick Mooney segumap_data_t *sud = (segumap_data_t *)seg->s_data; 298*263f549eSPatrick Mooney int error = 0; 299*263f549eSPatrick Mooney 300*263f549eSPatrick Mooney ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); 301*263f549eSPatrick Mooney 302*263f549eSPatrick Mooney rw_enter(&sud->sud_lock, RW_READER); 303*263f549eSPatrick Mooney if ((sud->sud_prot & prot) != prot) { 304*263f549eSPatrick Mooney error = EACCES; 305*263f549eSPatrick Mooney } 306*263f549eSPatrick Mooney rw_exit(&sud->sud_lock); 307*263f549eSPatrick Mooney return (error); 308*263f549eSPatrick Mooney } 309*263f549eSPatrick Mooney 310*263f549eSPatrick Mooney /* ARGSUSED */ 311*263f549eSPatrick Mooney static int 312*263f549eSPatrick Mooney segumap_sync(struct seg *seg, caddr_t addr, size_t len, int attr, uint_t flags) 313*263f549eSPatrick Mooney { 314*263f549eSPatrick Mooney /* Always succeed since there are no backing store to sync */ 315*263f549eSPatrick Mooney return (0); 316*263f549eSPatrick Mooney } 317*263f549eSPatrick Mooney 318*263f549eSPatrick Mooney /* ARGSUSED */ 319*263f549eSPatrick Mooney static size_t 320*263f549eSPatrick Mooney segumap_incore(struct seg *seg, caddr_t addr, size_t len, char *vec) 321*263f549eSPatrick Mooney { 322*263f549eSPatrick Mooney size_t sz = 0; 323*263f549eSPatrick Mooney 324*263f549eSPatrick Mooney ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); 325*263f549eSPatrick Mooney 326*263f549eSPatrick Mooney len = (len + PAGEOFFSET) & PAGEMASK; 327*263f549eSPatrick Mooney while (len > 0) { 328*263f549eSPatrick Mooney *vec = 1; 329*263f549eSPatrick Mooney sz += PAGESIZE; 330*263f549eSPatrick Mooney vec++; 331*263f549eSPatrick Mooney len -= PAGESIZE; 332*263f549eSPatrick Mooney } 333*263f549eSPatrick Mooney return (sz); 334*263f549eSPatrick Mooney } 335*263f549eSPatrick Mooney 336*263f549eSPatrick Mooney /* ARGSUSED */ 337*263f549eSPatrick Mooney static int 338*263f549eSPatrick Mooney segumap_lockop(struct seg *seg, caddr_t addr, size_t len, int attr, int op, 339*263f549eSPatrick Mooney ulong_t *lockmap, size_t pos) 340*263f549eSPatrick Mooney { 341*263f549eSPatrick Mooney /* Report success since kernel pages are always in memory. */ 342*263f549eSPatrick Mooney return (0); 343*263f549eSPatrick Mooney } 344*263f549eSPatrick Mooney 345*263f549eSPatrick Mooney static int 346*263f549eSPatrick Mooney segumap_getprot(struct seg *seg, caddr_t addr, size_t len, uint_t *protv) 347*263f549eSPatrick Mooney { 348*263f549eSPatrick Mooney segumap_data_t *sud = (segumap_data_t *)seg->s_data; 349*263f549eSPatrick Mooney size_t pgno; 350*263f549eSPatrick Mooney uint_t prot; 351*263f549eSPatrick Mooney 352*263f549eSPatrick Mooney ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); 353*263f549eSPatrick Mooney 354*263f549eSPatrick Mooney rw_enter(&sud->sud_lock, RW_READER); 355*263f549eSPatrick Mooney prot = sud->sud_prot; 356*263f549eSPatrick Mooney rw_exit(&sud->sud_lock); 357*263f549eSPatrick Mooney 358*263f549eSPatrick Mooney /* 359*263f549eSPatrick Mooney * Reporting protection is simple since it is not tracked per-page. 360*263f549eSPatrick Mooney */ 361*263f549eSPatrick Mooney pgno = seg_page(seg, addr + len) - seg_page(seg, addr) + 1; 362*263f549eSPatrick Mooney while (pgno > 0) { 363*263f549eSPatrick Mooney protv[--pgno] = prot; 364*263f549eSPatrick Mooney } 365*263f549eSPatrick Mooney return (0); 366*263f549eSPatrick Mooney } 367*263f549eSPatrick Mooney 368*263f549eSPatrick Mooney /* ARGSUSED */ 369*263f549eSPatrick Mooney static u_offset_t 370*263f549eSPatrick Mooney segumap_getoffset(struct seg *seg, caddr_t addr) 371*263f549eSPatrick Mooney { 372*263f549eSPatrick Mooney /* 373*263f549eSPatrick Mooney * To avoid leaking information about the layout of the kernel address 374*263f549eSPatrick Mooney * space, always report '0' as the offset. 375*263f549eSPatrick Mooney */ 376*263f549eSPatrick Mooney return (0); 377*263f549eSPatrick Mooney } 378*263f549eSPatrick Mooney 379*263f549eSPatrick Mooney /* ARGSUSED */ 380*263f549eSPatrick Mooney static int 381*263f549eSPatrick Mooney segumap_gettype(struct seg *seg, caddr_t addr) 382*263f549eSPatrick Mooney { 383*263f549eSPatrick Mooney /* 384*263f549eSPatrick Mooney * Since already-existing kernel pages are being mapped into userspace, 385*263f549eSPatrick Mooney * always report the segment type as shared. 386*263f549eSPatrick Mooney */ 387*263f549eSPatrick Mooney return (MAP_SHARED); 388*263f549eSPatrick Mooney } 389*263f549eSPatrick Mooney 390*263f549eSPatrick Mooney /* ARGSUSED */ 391*263f549eSPatrick Mooney static int 392*263f549eSPatrick Mooney segumap_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp) 393*263f549eSPatrick Mooney { 394*263f549eSPatrick Mooney ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); 395*263f549eSPatrick Mooney 396*263f549eSPatrick Mooney *vpp = NULL; 397*263f549eSPatrick Mooney return (0); 398*263f549eSPatrick Mooney } 399*263f549eSPatrick Mooney 400*263f549eSPatrick Mooney /* ARGSUSED */ 401*263f549eSPatrick Mooney static int 402*263f549eSPatrick Mooney segumap_advise(struct seg *seg, caddr_t addr, size_t len, uint_t behav) 403*263f549eSPatrick Mooney { 404*263f549eSPatrick Mooney if (behav == MADV_PURGE) { 405*263f549eSPatrick Mooney /* Purge does not make sense for this mapping */ 406*263f549eSPatrick Mooney return (EINVAL); 407*263f549eSPatrick Mooney } 408*263f549eSPatrick Mooney /* Indicate success for everything else. */ 409*263f549eSPatrick Mooney return (0); 410*263f549eSPatrick Mooney } 411*263f549eSPatrick Mooney 412*263f549eSPatrick Mooney /* ARGSUSED */ 413*263f549eSPatrick Mooney static void 414*263f549eSPatrick Mooney segumap_dump(struct seg *seg) 415*263f549eSPatrick Mooney { 416*263f549eSPatrick Mooney /* 417*263f549eSPatrick Mooney * Since this is a mapping to share kernel data with userspace, nothing 418*263f549eSPatrick Mooney * additional should be dumped. 419*263f549eSPatrick Mooney */ 420*263f549eSPatrick Mooney } 421*263f549eSPatrick Mooney 422*263f549eSPatrick Mooney /* ARGSUSED */ 423*263f549eSPatrick Mooney static int 424*263f549eSPatrick Mooney segumap_pagelock(struct seg *seg, caddr_t addr, size_t len, struct page ***ppp, 425*263f549eSPatrick Mooney enum lock_type type, enum seg_rw rw) 426*263f549eSPatrick Mooney { 427*263f549eSPatrick Mooney return (ENOTSUP); 428*263f549eSPatrick Mooney } 429*263f549eSPatrick Mooney 430*263f549eSPatrick Mooney /* ARGSUSED */ 431*263f549eSPatrick Mooney static int 432*263f549eSPatrick Mooney segumap_setpagesize(struct seg *seg, caddr_t addr, size_t len, uint_t szc) 433*263f549eSPatrick Mooney { 434*263f549eSPatrick Mooney return (ENOTSUP); 435*263f549eSPatrick Mooney } 436*263f549eSPatrick Mooney 437*263f549eSPatrick Mooney static int 438*263f549eSPatrick Mooney segumap_getmemid(struct seg *seg, caddr_t addr, memid_t *memidp) 439*263f549eSPatrick Mooney { 440*263f549eSPatrick Mooney segumap_data_t *sud = (segumap_data_t *)seg->s_data; 441*263f549eSPatrick Mooney 442*263f549eSPatrick Mooney memidp->val[0] = (uintptr_t)sud->sud_kaddr; 443*263f549eSPatrick Mooney memidp->val[1] = (uintptr_t)(addr - seg->s_base); 444*263f549eSPatrick Mooney return (0); 445*263f549eSPatrick Mooney } 446*263f549eSPatrick Mooney 447*263f549eSPatrick Mooney /* ARGSUSED */ 448*263f549eSPatrick Mooney static int 449*263f549eSPatrick Mooney segumap_capable(struct seg *seg, segcapability_t capability) 450*263f549eSPatrick Mooney { 451*263f549eSPatrick Mooney /* no special capablities */ 452*263f549eSPatrick Mooney return (0); 453*263f549eSPatrick Mooney } 454