3897b4211095f2ed5ed6069e6c4a22adfdbc3b00
[dragonfly.git] / sys / kern / kern_memio.c
1 /*-
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department, and code derived from software contributed to
9  * Berkeley by William Jolitz.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *      from: Utah $Hdr: mem.c 1.13 89/10/08$
36  *      from: @(#)mem.c 7.2 (Berkeley) 5/9/91
37  * $FreeBSD: src/sys/i386/i386/mem.c,v 1.79.2.9 2003/01/04 22:58:01 njl Exp $
38  */
39
40 /*
41  * Memory special file
42  */
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/buf.h>
47 #include <sys/conf.h>
48 #include <sys/fcntl.h>
49 #include <sys/filio.h>
50 #include <sys/interrupt.h>
51 #include <sys/kernel.h>
52 #include <sys/malloc.h>
53 #include <sys/memrange.h>
54 #include <sys/proc.h>
55 #include <sys/caps.h>
56 #include <sys/queue.h>
57 #include <sys/random.h>
58 #include <sys/signalvar.h>
59 #include <sys/uio.h>
60 #include <sys/vnode.h>
61 #include <sys/sysctl.h>
62
63 #include <sys/signal2.h>
64 #include <sys/spinlock2.h>
65
66 #include <vm/vm.h>
67 #include <vm/pmap.h>
68 #include <vm/vm_map.h>
69 #include <vm/vm_extern.h>
70
71
72 static  d_open_t        mmopen;
73 static  d_close_t       mmclose;
74 static  d_read_t        mmread;
75 static  d_write_t       mmwrite;
76 static  d_ioctl_t       mmioctl;
77 #if 0
78 static  d_mmap_t        memmmap;
79 #endif
80 static  d_kqfilter_t    mmkqfilter;
81 static int memuksmap(vm_map_backing_t ba, int op, cdev_t dev, vm_page_t fake);
82
83 #define CDEV_MAJOR 2
84 static struct dev_ops mem_ops = {
85         { "mem", 0, D_MPSAFE | D_QUICK },
86         .d_open =       mmopen,
87         .d_close =      mmclose,
88         .d_read =       mmread,
89         .d_write =      mmwrite,
90         .d_ioctl =      mmioctl,
91         .d_kqfilter =   mmkqfilter,
92 #if 0
93         .d_mmap =       memmmap,
94 #endif
95         .d_uksmap =     memuksmap
96 };
97
98 static struct dev_ops mem_ops_mem = {
99         { "mem", 0, D_MEM | D_MPSAFE | D_QUICK },
100         .d_open =       mmopen,
101         .d_close =      mmclose,
102         .d_read =       mmread,
103         .d_write =      mmwrite,
104         .d_ioctl =      mmioctl,
105         .d_kqfilter =   mmkqfilter,
106 #if 0
107         .d_mmap =       memmmap,
108 #endif
109         .d_uksmap =     memuksmap
110 };
111
112 static struct dev_ops mem_ops_noq = {
113         { "mem", 0, D_MPSAFE },
114         .d_open =       mmopen,
115         .d_close =      mmclose,
116         .d_read =       mmread,
117         .d_write =      mmwrite,
118         .d_ioctl =      mmioctl,
119         .d_kqfilter =   mmkqfilter,
120 #if 0
121         .d_mmap =       memmmap,
122 #endif
123         .d_uksmap =     memuksmap
124 };
125
126 static int rand_bolt;
127 static caddr_t  zbuf;
128 static cdev_t   zerodev = NULL;
129 static struct lock mem_lock = LOCK_INITIALIZER("memlk", 0, 0);
130
131 MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors");
132 static int mem_ioctl (cdev_t, u_long, caddr_t, int, struct ucred *);
133 static int random_ioctl (cdev_t, u_long, caddr_t, int, struct ucred *);
134
135 struct mem_range_softc mem_range_softc;
136
137 static int seedenable;
138 SYSCTL_INT(_kern, OID_AUTO, seedenable, CTLFLAG_RW, &seedenable, 0, "");
139
140 static int
141 mmopen(struct dev_open_args *ap)
142 {
143         cdev_t dev = ap->a_head.a_dev;
144         int error;
145
146         switch (minor(dev)) {
147         case 0:
148         case 1:
149                 /*
150                  * /dev/mem and /dev/kmem
151                  */
152                 error = caps_priv_check(ap->a_cred, SYSCAP_RESTRICTEDROOT |
153                                                     __SYSCAP_NOROOTTEST);
154                 if (error == 0) {
155                         if (ap->a_oflags & FWRITE) {
156                                 if (securelevel > 0 || kernel_mem_readonly)
157                                         error = EPERM;
158                         }
159                 }
160                 break;
161         case 3:
162         case 4:
163                 /*
164                  * /dev/random
165                  * /dev/urandom
166                  *
167                  * Cannot be written to from RESTRICTEDROOT environments.
168                  */
169                 error = 0;
170                 if (ap->a_oflags & FWRITE) {
171                         error = caps_priv_check(ap->a_cred,
172                                                 SYSCAP_RESTRICTEDROOT |
173                                                 __SYSCAP_NOROOTTEST);
174                 }
175                 break;
176         case 6:
177                 /*
178                  * /dev/kpmap can only be opened for reading.
179                  */
180                 error = 0;
181                 if (ap->a_oflags & FWRITE)
182                         error = EPERM;
183                 break;
184         case 14:
185                 /*
186                  * /dev/io
187                  */
188                 error = caps_priv_check(ap->a_cred, SYSCAP_RESTRICTEDROOT);
189                 if (error == 0) {
190                         if (securelevel > 0 || kernel_mem_readonly)
191                                 error = EPERM;
192                         else
193                                 error = cpu_set_iopl();
194                 }
195                 break;
196         default:
197                 error = 0;
198                 break;
199         }
200         return (error);
201 }
202
203 static int
204 mmclose(struct dev_close_args *ap)
205 {
206         cdev_t dev = ap->a_head.a_dev;
207         int error;
208
209         switch (minor(dev)) {
210         case 14:
211                 error = cpu_clr_iopl();
212                 break;
213         default:
214                 error = 0;
215                 break;
216         }
217         return (error);
218 }
219
220
221 static int
222 mmrw(cdev_t dev, struct uio *uio, int flags)
223 {
224         int o;
225         u_int c;
226         u_int poolsize;
227         u_long v;
228         struct iovec *iov;
229         int error = 0;
230         caddr_t buf = NULL;
231
232         while (uio->uio_resid > 0 && error == 0) {
233                 iov = uio->uio_iov;
234                 if (iov->iov_len == 0) {
235                         uio->uio_iov++;
236                         uio->uio_iovcnt--;
237                         if (uio->uio_iovcnt < 0)
238                                 panic("mmrw");
239                         continue;
240                 }
241                 switch (minor(dev)) {
242                 case 0:
243                         /*
244                          * minor device 0 is physical memory, /dev/mem 
245                          */
246                         v = uio->uio_offset;
247                         v &= ~(long)PAGE_MASK;
248                         pmap_kenter((vm_offset_t)ptvmmap, v);
249                         o = (int)uio->uio_offset & PAGE_MASK;
250                         c = (u_int)(PAGE_SIZE - ((uintptr_t)iov->iov_base & PAGE_MASK));
251                         c = min(c, (u_int)(PAGE_SIZE - o));
252                         c = min(c, (u_int)iov->iov_len);
253                         error = uiomove((caddr_t)&ptvmmap[o], (int)c, uio);
254                         pmap_kremove((vm_offset_t)ptvmmap);
255                         continue;
256
257                 case 1: {
258                         /*
259                          * minor device 1 is kernel memory, /dev/kmem 
260                          */
261                         vm_offset_t saddr, eaddr;
262                         int prot;
263
264                         c = iov->iov_len;
265
266                         /*
267                          * Make sure that all of the pages are currently 
268                          * resident so that we don't create any zero-fill
269                          * pages.
270                          */
271                         saddr = trunc_page(uio->uio_offset);
272                         eaddr = round_page(uio->uio_offset + c);
273                         if (saddr > eaddr)
274                                 return EFAULT;
275
276                         /*
277                          * Make sure the kernel addresses are mapped.
278                          * platform_direct_mapped() can be used to bypass
279                          * default mapping via the page table (virtual kernels
280                          * contain a lot of out-of-band data).
281                          */
282                         prot = VM_PROT_READ;
283                         if (uio->uio_rw != UIO_READ)
284                                 prot |= VM_PROT_WRITE;
285                         error = kvm_access_check(saddr, eaddr, prot);
286                         if (error)
287                                 return (error);
288                         error = uiomove((caddr_t)(vm_offset_t)uio->uio_offset,
289                                         (int)c, uio);
290                         continue;
291                 }
292                 case 2:
293                         /*
294                          * minor device 2 (/dev/null) is EOF/RATHOLE
295                          */
296                         if (uio->uio_rw == UIO_READ)
297                                 return (0);
298                         c = iov->iov_len;
299                         break;
300                 case 3:
301                         /*
302                          * minor device 3 (/dev/random) is source of filth
303                          * on read, seeder on write
304                          */
305                         if (buf == NULL)
306                                 buf = kmalloc(PAGE_SIZE, M_TEMP, M_WAITOK);
307                         c = min(iov->iov_len, PAGE_SIZE);
308                         if (uio->uio_rw == UIO_WRITE) {
309                                 error = uiomove(buf, (int)c, uio);
310                                 if (error == 0 &&
311                                     seedenable &&
312                                     securelevel <= 0)
313                                 {
314                                         error = add_buffer_randomness_src(buf, c, RAND_SRC_SEEDING);
315                                 } else if (error == 0) {
316                                         error = EPERM;
317                                 }
318                         } else {
319                                 poolsize = read_random(buf, c, 0);
320                                 if (poolsize == 0) {
321                                         if (buf)
322                                                 kfree(buf, M_TEMP);
323                                         if ((flags & IO_NDELAY) != 0)
324                                                 return (EWOULDBLOCK);
325                                         return (0);
326                                 }
327                                 c = min(c, poolsize);
328                                 error = uiomove(buf, (int)c, uio);
329                         }
330                         continue;
331                 case 4:
332                         /*
333                          * minor device 4 (/dev/urandom) is source of muck
334                          * on read, writes are disallowed.
335                          */
336                         c = min(iov->iov_len, PAGE_SIZE);
337                         if (uio->uio_rw == UIO_WRITE) {
338                                 error = EPERM;
339                                 break;
340                         }
341                         if (CURSIG(curthread->td_lwp) != 0) {
342                                 /*
343                                  * Use tsleep() to get the error code right.
344                                  * It should return immediately.
345                                  */
346                                 error = tsleep(&rand_bolt, PCATCH, "urand", 1);
347                                 if (error != 0 && error != EWOULDBLOCK)
348                                         continue;
349                         }
350                         if (buf == NULL)
351                                 buf = kmalloc(PAGE_SIZE, M_TEMP, M_WAITOK);
352                         poolsize = read_random(buf, c, 1);
353                         c = min(c, poolsize);
354                         error = uiomove(buf, (int)c, uio);
355                         continue;
356                 /* case 5: read/write not supported, mmap only */
357                 /* case 6: read/write not supported, mmap only */
358                 case 12:
359                         /*
360                          * minor device 12 (/dev/zero) is source of nulls 
361                          * on read, write are disallowed.
362                          */
363                         if (uio->uio_rw == UIO_WRITE) {
364                                 c = iov->iov_len;
365                                 break;
366                         }
367                         if (zbuf == NULL) {
368                                 zbuf = (caddr_t)kmalloc(PAGE_SIZE, M_TEMP,
369                                     M_WAITOK | M_ZERO);
370                         }
371                         c = min(iov->iov_len, PAGE_SIZE);
372                         error = uiomove(zbuf, (int)c, uio);
373                         continue;
374                 default:
375                         return (ENODEV);
376                 }
377                 if (error)
378                         break;
379                 iov->iov_base = (char *)iov->iov_base + c;
380                 iov->iov_len -= c;
381                 uio->uio_offset += c;
382                 uio->uio_resid -= c;
383         }
384         if (buf)
385                 kfree(buf, M_TEMP);
386         return (error);
387 }
388
389 static int
390 mmread(struct dev_read_args *ap)
391 {
392         return(mmrw(ap->a_head.a_dev, ap->a_uio, ap->a_ioflag));
393 }
394
395 static int
396 mmwrite(struct dev_write_args *ap)
397 {
398         return(mmrw(ap->a_head.a_dev, ap->a_uio, ap->a_ioflag));
399 }
400
401 /*******************************************************\
402 * allow user processes to MMAP some memory sections     *
403 * instead of going through read/write                   *
404 \*******************************************************/
405
406 static int user_kernel_mapping(vm_map_backing_t ba, int num,
407                         vm_ooffset_t offset, vm_ooffset_t *resultp);
408
409 static int
410 memuksmap(vm_map_backing_t ba, int op, cdev_t dev, vm_page_t fake)
411 {
412         vm_ooffset_t result;
413         int error;
414         struct lwp *lp;
415
416         error = 0;
417
418         switch(op) {
419         case UKSMAPOP_ADD:
420                 /*
421                  * We only need to track mappings for /dev/lpmap, all process
422                  * mappings will be deleted when the process exits and we
423                  * do not need to track kernel mappings.
424                  */
425                 if (minor(dev) == 7) {
426                         lp = ba->aux_info;
427                         spin_lock(&lp->lwp_spin);
428                         TAILQ_INSERT_TAIL(&lp->lwp_lpmap_backing_list,
429                                           ba, entry);
430                         spin_unlock(&lp->lwp_spin);
431                 }
432                 break;
433         case UKSMAPOP_REM:
434                 /*
435                  * We only need to track mappings for /dev/lpmap, all process
436                  * mappings will be deleted when the process exits and we
437                  * do not need to track kernel mappings.
438                  */
439                 if (minor(dev) == 7) {
440                         lp = ba->aux_info;
441                         spin_lock(&lp->lwp_spin);
442                         TAILQ_REMOVE(&lp->lwp_lpmap_backing_list, ba, entry);
443                         spin_unlock(&lp->lwp_spin);
444                 }
445                 break;
446         case UKSMAPOP_FAULT:
447                 switch (minor(dev)) {
448                 case 0:
449                         /*
450                          * minor device 0 is physical memory
451                          */
452                         fake->phys_addr = ptoa(fake->pindex);
453                         break;
454                 case 1:
455                         /*
456                          * minor device 1 is kernel memory
457                          */
458                         fake->phys_addr = vtophys(ptoa(fake->pindex));
459                         break;
460                 case 5:
461                 case 6:
462                 case 7:
463                         /*
464                          * minor device 5 is /dev/upmap (see sys/upmap.h)
465                          * minor device 6 is /dev/kpmap (see sys/upmap.h)
466                          * minor device 7 is /dev/lpmap (see sys/upmap.h)
467                          */
468                         result = 0;
469                         error = user_kernel_mapping(ba,
470                                                     minor(dev),
471                                                     ptoa(fake->pindex),
472                                                     &result);
473                         fake->phys_addr = result;
474                         break;
475                 default:
476                         error = EINVAL;
477                         break;
478                 }
479                 break;
480         default:
481                 error = EINVAL;
482                 break;
483         }
484         return error;
485 }
486
487 static int
488 mmioctl(struct dev_ioctl_args *ap)
489 {
490         cdev_t dev = ap->a_head.a_dev;
491         int error;
492
493         lockmgr(&mem_lock, LK_EXCLUSIVE);
494
495         switch (minor(dev)) {
496         case 0:
497                 error = mem_ioctl(dev, ap->a_cmd, ap->a_data,
498                                   ap->a_fflag, ap->a_cred);
499                 break;
500         case 3:
501         case 4:
502                 error = random_ioctl(dev, ap->a_cmd, ap->a_data,
503                                      ap->a_fflag, ap->a_cred);
504                 break;
505         default:
506                 error = ENODEV;
507                 break;
508         }
509
510         lockmgr(&mem_lock, LK_RELEASE);
511
512         return (error);
513 }
514
515 /*
516  * Operations for changing memory attributes.
517  *
518  * This is basically just an ioctl shim for mem_range_attr_get
519  * and mem_range_attr_set.
520  */
521 static int 
522 mem_ioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, struct ucred *cred)
523 {
524         int nd, error = 0;
525         struct mem_range_op *mo = (struct mem_range_op *)data;
526         struct mem_range_desc *md;
527         
528         /* is this for us? */
529         if ((cmd != MEMRANGE_GET) &&
530             (cmd != MEMRANGE_SET))
531                 return (ENOTTY);
532
533         /* any chance we can handle this? */
534         if (mem_range_softc.mr_op == NULL)
535                 return (EOPNOTSUPP);
536
537         /* do we have any descriptors? */
538         if (mem_range_softc.mr_ndesc == 0)
539                 return (ENXIO);
540
541         switch (cmd) {
542         case MEMRANGE_GET:
543                 nd = imin(mo->mo_arg[0], mem_range_softc.mr_ndesc);
544                 if (nd > 0) {
545                         md = (struct mem_range_desc *)
546                                 kmalloc(nd * sizeof(struct mem_range_desc),
547                                        M_MEMDESC, M_WAITOK);
548                         error = mem_range_attr_get(md, &nd);
549                         if (!error)
550                                 error = copyout(md, mo->mo_desc, 
551                                         nd * sizeof(struct mem_range_desc));
552                         kfree(md, M_MEMDESC);
553                 } else {
554                         nd = mem_range_softc.mr_ndesc;
555                 }
556                 mo->mo_arg[0] = nd;
557                 break;
558                 
559         case MEMRANGE_SET:
560                 md = (struct mem_range_desc *)kmalloc(sizeof(struct mem_range_desc),
561                                                     M_MEMDESC, M_WAITOK);
562                 error = copyin(mo->mo_desc, md, sizeof(struct mem_range_desc));
563                 /* clamp description string */
564                 md->mr_owner[sizeof(md->mr_owner) - 1] = 0;
565                 if (error == 0)
566                         error = mem_range_attr_set(md, &mo->mo_arg[0]);
567                 kfree(md, M_MEMDESC);
568                 break;
569         }
570         return (error);
571 }
572
573 /*
574  * Implementation-neutral, kernel-callable functions for manipulating
575  * memory range attributes.
576  */
577 int
578 mem_range_attr_get(struct mem_range_desc *mrd, int *arg)
579 {
580         /* can we handle this? */
581         if (mem_range_softc.mr_op == NULL)
582                 return (EOPNOTSUPP);
583
584         if (*arg == 0) {
585                 *arg = mem_range_softc.mr_ndesc;
586         } else {
587                 bcopy(mem_range_softc.mr_desc, mrd, (*arg) * sizeof(struct mem_range_desc));
588         }
589         return (0);
590 }
591
592 int
593 mem_range_attr_set(struct mem_range_desc *mrd, int *arg)
594 {
595         /* can we handle this? */
596         if (mem_range_softc.mr_op == NULL)
597                 return (EOPNOTSUPP);
598
599         return (mem_range_softc.mr_op->set(&mem_range_softc, mrd, arg));
600 }
601
602 void
603 mem_range_AP_init(void)
604 {
605         if (mem_range_softc.mr_op && mem_range_softc.mr_op->initAP)
606                 mem_range_softc.mr_op->initAP(&mem_range_softc);
607 }
608
609 static int 
610 random_ioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, struct ucred *cred)
611 {
612         int error;
613         int intr;
614         
615         /*
616          * Even inspecting the state is privileged, since it gives a hint
617          * about how easily the randomness might be guessed.
618          */
619         error = 0;
620
621         switch (cmd) {
622         /* Really handled in upper layer */
623         case FIOASYNC:
624                 break;
625         case MEM_SETIRQ:
626                 intr = *(int16_t *)data;
627                 if ((error = caps_priv_check(cred, SYSCAP_RESTRICTEDROOT)) != 0)
628                         break;
629                 if (intr < 0 || intr >= MAX_INTS)
630                         return (EINVAL);
631                 register_randintr(intr);
632                 break;
633         case MEM_CLEARIRQ:
634                 intr = *(int16_t *)data;
635                 if ((error = caps_priv_check(cred, SYSCAP_RESTRICTEDROOT)) != 0)
636                         break;
637                 if (intr < 0 || intr >= MAX_INTS)
638                         return (EINVAL);
639                 unregister_randintr(intr);
640                 break;
641         case MEM_RETURNIRQ:
642                 error = ENOTSUP;
643                 break;
644         case MEM_FINDIRQ:
645                 intr = *(int16_t *)data;
646                 if ((error = caps_priv_check(cred, SYSCAP_RESTRICTEDROOT)) != 0)
647                         break;
648                 if (intr < 0 || intr >= MAX_INTS)
649                         return (EINVAL);
650                 intr = next_registered_randintr(intr);
651                 if (intr == MAX_INTS)
652                         return (ENOENT);
653                 *(u_int16_t *)data = intr;
654                 break;
655         default:
656                 error = ENOTSUP;
657                 break;
658         }
659         return (error);
660 }
661
662 static int
663 mm_filter_read(struct knote *kn, long hint)
664 {
665         return (1);
666 }
667
668 static int
669 mm_filter_write(struct knote *kn, long hint)
670 {
671         return (1);
672 }
673
674 static void
675 dummy_filter_detach(struct knote *kn) {}
676
677 /* Implemented in kern_nrandom.c */
678 static struct filterops random_read_filtops =
679         { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, dummy_filter_detach, random_filter_read };
680
681 static struct filterops mm_read_filtops =
682         { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, dummy_filter_detach, mm_filter_read };
683
684 static struct filterops mm_write_filtops =
685         { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, dummy_filter_detach, mm_filter_write };
686
687 static int
688 mmkqfilter(struct dev_kqfilter_args *ap)
689 {
690         struct knote *kn = ap->a_kn;
691         cdev_t dev = ap->a_head.a_dev;
692
693         ap->a_result = 0;
694         switch (kn->kn_filter) {
695         case EVFILT_READ:
696                 switch (minor(dev)) {
697                 case 3:
698                         kn->kn_fop = &random_read_filtops;
699                         break;
700                 default:
701                         kn->kn_fop = &mm_read_filtops;
702                         break;
703                 }
704                 break;
705         case EVFILT_WRITE:
706                 kn->kn_fop = &mm_write_filtops;
707                 break;
708         default:
709                 ap->a_result = EOPNOTSUPP;
710                 return (0);
711         }
712
713         return (0);
714 }
715
716 int
717 iszerodev(cdev_t dev)
718 {
719         return (zerodev == dev);
720 }
721
722 /*
723  * /dev/lpmap, /dev/upmap, /dev/kpmap.
724  */
725 static int
726 user_kernel_mapping(vm_map_backing_t ba, int num, vm_ooffset_t offset,
727                     vm_ooffset_t *resultp)
728 {
729         struct proc *p;
730         struct lwp *lp;
731         int error;
732         int invfork;
733
734         if (offset < 0)
735                 return (EINVAL);
736
737         error = EINVAL;
738
739         switch(num) {
740         case 5:
741                 /*
742                  * /dev/upmap - maps RW per-process shared user-kernel area.
743                  */
744
745                 /*
746                  * If this is a child currently in vfork the pmap is shared
747                  * with the parent!  We need to actually set-up the parent's
748                  * p_upmap, not the child's, and we need to set the invfork
749                  * flag.  Userland will probably adjust its static state so
750                  * it must be consistent with the parent or userland will be
751                  * really badly confused.
752                  *
753                  * (this situation can happen when user code in vfork() calls
754                  *  libc's getpid() or some other function which then decides
755                  *  it wants the upmap).
756                  */
757                 p = ba->aux_info;
758                 if (p == NULL)
759                         break;
760                 if (p->p_flags & P_PPWAIT) {
761                         p = p->p_pptr;
762                         if (p == NULL)
763                                 return (EINVAL);
764                         invfork = 1;
765                 } else {
766                         invfork = 0;
767                 }
768
769                 /*
770                  * Create the kernel structure as required, set the invfork
771                  * flag if we are faulting in on a vfork().
772                  */
773                 if (p->p_upmap == NULL)
774                         proc_usermap(p, invfork);
775                 if (p->p_upmap && invfork)
776                         p->p_upmap->invfork = invfork;
777
778                 /*
779                  * Extract address for pmap
780                  */
781                 if (p->p_upmap &&
782                     offset < roundup2(sizeof(*p->p_upmap), PAGE_SIZE)) {
783                         /* only good for current process */
784                         *resultp = pmap_kextract((vm_offset_t)p->p_upmap +
785                                                  offset);
786                         error = 0;
787                 }
788                 break;
789         case 6:
790                 /*
791                  * /dev/kpmap - maps RO shared kernel global page
792                  *
793                  * Extract address for pmap
794                  */
795                 if (kpmap &&
796                     offset < roundup2(sizeof(*kpmap), PAGE_SIZE)) {
797                         *resultp = pmap_kextract((vm_offset_t)kpmap + offset);
798                         error = 0;
799                 }
800                 break;
801         case 7:
802                 /*
803                  * /dev/lpmap - maps RW per-thread shared user-kernel area.
804                  */
805                 lp = ba->aux_info;
806                 if (lp == NULL)
807                         break;
808
809                 /*
810                  * Create the kernel structure as required
811                  */
812                 if (lp->lwp_lpmap == NULL)
813                         lwp_usermap(lp, -1);    /* second arg not yet XXX */
814
815                 /*
816                  * Extract address for pmap
817                  */
818                 if (lp->lwp_lpmap &&
819                     offset < roundup2(sizeof(*lp->lwp_lpmap), PAGE_SIZE)) {
820                         /* only good for current process */
821                         *resultp = pmap_kextract((vm_offset_t)lp->lwp_lpmap +
822                                                  offset);
823                         error = 0;
824                 }
825                 break;
826         default:
827                 break;
828         }
829         return error;
830 }
831
832 static void
833 mem_drvinit(void *unused)
834 {
835
836         /* Initialise memory range handling */
837         if (mem_range_softc.mr_op != NULL)
838                 mem_range_softc.mr_op->init(&mem_range_softc);
839
840         make_dev(&mem_ops_mem, 0, UID_ROOT, GID_KMEM, 0640, "mem");
841         make_dev(&mem_ops_mem, 1, UID_ROOT, GID_KMEM, 0640, "kmem");
842         make_dev(&mem_ops, 2, UID_ROOT, GID_WHEEL, 0666, "null");
843         make_dev(&mem_ops, 3, UID_ROOT, GID_WHEEL, 0644, "random");
844         make_dev(&mem_ops, 4, UID_ROOT, GID_WHEEL, 0644, "urandom");
845         make_dev(&mem_ops, 5, UID_ROOT, GID_WHEEL, 0666, "upmap");
846         make_dev(&mem_ops, 6, UID_ROOT, GID_WHEEL, 0444, "kpmap");
847         make_dev(&mem_ops, 7, UID_ROOT, GID_WHEEL, 0666, "lpmap");
848         zerodev = make_dev(&mem_ops, 12, UID_ROOT, GID_WHEEL, 0666, "zero");
849         make_dev(&mem_ops_noq, 14, UID_ROOT, GID_WHEEL, 0600, "io");
850 }
851
852 SYSINIT(memdev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, mem_drvinit,
853     NULL);
854