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
segumap_create(struct seg * seg,void * argsp)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
segumap_verify_safe(caddr_t kaddr,size_t len)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
segumap_dup(struct seg * seg,struct seg * newseg)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
segumap_unmap(struct seg * seg,caddr_t addr,size_t len)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
segumap_free(struct seg * seg)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
segumap_fault(struct hat * hat,struct seg * seg,caddr_t addr,size_t len,enum fault_type type,enum seg_rw tw)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
segumap_faulta(struct seg * seg,caddr_t addr)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
segumap_setprot(struct seg * seg,caddr_t addr,size_t len,uint_t prot)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
segumap_checkprot(struct seg * seg,caddr_t addr,size_t len,uint_t prot)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
segumap_sync(struct seg * seg,caddr_t addr,size_t len,int attr,uint_t flags)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
segumap_incore(struct seg * seg,caddr_t addr,size_t len,char * vec)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
segumap_lockop(struct seg * seg,caddr_t addr,size_t len,int attr,int op,ulong_t * lockmap,size_t pos)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
segumap_getprot(struct seg * seg,caddr_t addr,size_t len,uint_t * protv)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
segumap_getoffset(struct seg * seg,caddr_t addr)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
segumap_gettype(struct seg * seg,caddr_t addr)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
segumap_getvp(struct seg * seg,caddr_t addr,struct vnode ** vpp)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
segumap_advise(struct seg * seg,caddr_t addr,size_t len,uint_t behav)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
segumap_dump(struct seg * seg)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
segumap_pagelock(struct seg * seg,caddr_t addr,size_t len,struct page *** ppp,enum lock_type type,enum seg_rw rw)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
segumap_setpagesize(struct seg * seg,caddr_t addr,size_t len,uint_t szc)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
segumap_getmemid(struct seg * seg,caddr_t addr,memid_t * memidp)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
segumap_capable(struct seg * seg,segcapability_t capability)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