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