2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
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.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * from: Utah $Hdr: mem.c 1.13 89/10/08$
40 * from: @(#)mem.c 7.2 (Berkeley) 5/9/91
41 * $FreeBSD: src/sys/i386/i386/mem.c,v 1.79.2.9 2003/01/04 22:58:01 njl Exp $
42 * $DragonFly: src/sys/kern/kern_memio.c,v 1.11 2004/05/19 22:52:57 dillon Exp $
49 #include <sys/param.h>
50 #include <sys/systm.h>
53 #include <sys/fcntl.h>
54 #include <sys/filio.h>
55 #include <sys/ioccom.h>
56 #include <sys/kernel.h>
57 #include <sys/malloc.h>
58 #include <sys/memrange.h>
60 #include <sys/random.h>
61 #include <sys/signalvar.h>
63 #include <sys/vnode.h>
65 #include <machine/frame.h>
66 #include <machine/psl.h>
67 #include <machine/specialreg.h>
68 #include <i386/isa/intr_machdep.h>
72 #include <vm/vm_extern.h>
75 static d_open_t mmopen
;
76 static d_close_t mmclose
;
78 static d_ioctl_t mmioctl
;
79 static d_mmap_t memmmap
;
80 static d_poll_t mmpoll
;
83 static struct cdevsw mem_cdevsw
= {
97 /* strategy */ nostrategy
,
102 static int rand_bolt
;
105 MALLOC_DEFINE(M_MEMDESC
, "memdesc", "memory range descriptors");
106 static int mem_ioctl (dev_t
, u_long
, caddr_t
, int, struct thread
*);
107 static int random_ioctl (dev_t
, u_long
, caddr_t
, int, struct thread
*);
109 struct mem_range_softc mem_range_softc
;
113 mmclose(dev_t dev
, int flags
, int fmt
, struct thread
*td
)
115 struct proc
*p
= td
->td_proc
;
117 switch (minor(dev
)) {
119 p
->p_md
.md_regs
->tf_eflags
&= ~PSL_IOPL
;
128 mmopen(dev_t dev
, int flags
, int fmt
, struct thread
*td
)
131 struct proc
*p
= td
->td_proc
;
133 switch (minor(dev
)) {
136 if ((flags
& FWRITE
) && securelevel
> 0)
145 p
->p_md
.md_regs
->tf_eflags
|= PSL_IOPL
;
154 mmrw(dev
, uio
, flags
)
166 while (uio
->uio_resid
> 0 && error
== 0) {
168 if (iov
->iov_len
== 0) {
171 if (uio
->uio_iovcnt
< 0)
175 switch (minor(dev
)) {
177 /* minor device 0 is physical memory */
181 pmap_kenter((vm_offset_t
)ptvmmap
, v
);
182 o
= (int)uio
->uio_offset
& PAGE_MASK
;
183 c
= (u_int
)(PAGE_SIZE
- ((int)iov
->iov_base
& PAGE_MASK
));
184 c
= min(c
, (u_int
)(PAGE_SIZE
- o
));
185 c
= min(c
, (u_int
)iov
->iov_len
);
186 error
= uiomove((caddr_t
)&ptvmmap
[o
], (int)c
, uio
);
187 pmap_kremove((vm_offset_t
)ptvmmap
);
190 /* minor device 1 is kernel memory */
192 vm_offset_t addr
, eaddr
;
196 * Make sure that all of the pages are currently resident so
197 * that we don't create any zero-fill pages.
199 addr
= trunc_page(uio
->uio_offset
);
200 eaddr
= round_page(uio
->uio_offset
+ c
);
202 if (addr
< (vm_offset_t
)VADDR(PTDPTDI
, 0))
204 if (eaddr
>= (vm_offset_t
)VADDR(APTDPTDI
, 0))
206 for (; addr
< eaddr
; addr
+= PAGE_SIZE
)
207 if (pmap_extract(kernel_pmap
, addr
) == 0)
210 if (!kernacc((caddr_t
)(int)uio
->uio_offset
, c
,
211 uio
->uio_rw
== UIO_READ
?
212 VM_PROT_READ
: VM_PROT_WRITE
))
214 error
= uiomove((caddr_t
)(int)uio
->uio_offset
, (int)c
, uio
);
218 /* minor device 2 is EOF/RATHOLE */
220 if (uio
->uio_rw
== UIO_READ
)
225 /* minor device 3 (/dev/random) is source of filth on read, rathole on write */
227 if (uio
->uio_rw
== UIO_WRITE
) {
233 malloc(PAGE_SIZE
, M_TEMP
, M_WAITOK
);
234 c
= min(iov
->iov_len
, PAGE_SIZE
);
235 poolsize
= read_random(buf
, c
);
239 if ((flags
& IO_NDELAY
) != 0)
240 return (EWOULDBLOCK
);
243 c
= min(c
, poolsize
);
244 error
= uiomove(buf
, (int)c
, uio
);
247 /* minor device 4 (/dev/urandom) is source of muck on read, rathole on write */
249 if (uio
->uio_rw
== UIO_WRITE
) {
253 if (CURSIG(curproc
) != 0) {
255 * Use tsleep() to get the error code right.
256 * It should return immediately.
258 error
= tsleep(&rand_bolt
, PCATCH
, "urand", 1);
259 if (error
!= 0 && error
!= EWOULDBLOCK
)
264 malloc(PAGE_SIZE
, M_TEMP
, M_WAITOK
);
265 c
= min(iov
->iov_len
, PAGE_SIZE
);
266 poolsize
= read_random_unlimited(buf
, c
);
267 c
= min(c
, poolsize
);
268 error
= uiomove(buf
, (int)c
, uio
);
271 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */
273 if (uio
->uio_rw
== UIO_WRITE
) {
279 malloc(PAGE_SIZE
, M_TEMP
, M_WAITOK
);
280 bzero(zbuf
, PAGE_SIZE
);
282 c
= min(iov
->iov_len
, PAGE_SIZE
);
283 error
= uiomove(zbuf
, (int)c
, uio
);
293 uio
->uio_offset
+= c
;
304 /*******************************************************\
305 * allow user processes to MMAP some memory sections *
306 * instead of going through read/write *
307 \*******************************************************/
309 memmmap(dev_t dev
, vm_offset_t offset
, int nprot
)
314 /* minor device 0 is physical memory */
316 return i386_btop(offset
);
318 /* minor device 1 is kernel memory */
320 return i386_btop(vtophys(offset
));
328 mmioctl(dev_t dev
, u_long cmd
, caddr_t data
, int flags
, struct thread
*td
)
331 switch (minor(dev
)) {
333 return mem_ioctl(dev
, cmd
, data
, flags
, td
);
336 return random_ioctl(dev
, cmd
, data
, flags
, td
);
342 * Operations for changing memory attributes.
344 * This is basically just an ioctl shim for mem_range_attr_get
345 * and mem_range_attr_set.
348 mem_ioctl(dev_t dev
, u_long cmd
, caddr_t data
, int flags
, struct thread
*td
)
351 struct mem_range_op
*mo
= (struct mem_range_op
*)data
;
352 struct mem_range_desc
*md
;
354 /* is this for us? */
355 if ((cmd
!= MEMRANGE_GET
) &&
356 (cmd
!= MEMRANGE_SET
))
359 /* any chance we can handle this? */
360 if (mem_range_softc
.mr_op
== NULL
)
363 /* do we have any descriptors? */
364 if (mem_range_softc
.mr_ndesc
== 0)
369 nd
= imin(mo
->mo_arg
[0], mem_range_softc
.mr_ndesc
);
371 md
= (struct mem_range_desc
*)
372 malloc(nd
* sizeof(struct mem_range_desc
),
373 M_MEMDESC
, M_WAITOK
);
374 error
= mem_range_attr_get(md
, &nd
);
376 error
= copyout(md
, mo
->mo_desc
,
377 nd
* sizeof(struct mem_range_desc
));
380 nd
= mem_range_softc
.mr_ndesc
;
386 md
= (struct mem_range_desc
*)malloc(sizeof(struct mem_range_desc
),
387 M_MEMDESC
, M_WAITOK
);
388 error
= copyin(mo
->mo_desc
, md
, sizeof(struct mem_range_desc
));
389 /* clamp description string */
390 md
->mr_owner
[sizeof(md
->mr_owner
) - 1] = 0;
392 error
= mem_range_attr_set(md
, &mo
->mo_arg
[0]);
400 * Implementation-neutral, kernel-callable functions for manipulating
401 * memory range attributes.
404 mem_range_attr_get(mrd
, arg
)
405 struct mem_range_desc
*mrd
;
408 /* can we handle this? */
409 if (mem_range_softc
.mr_op
== NULL
)
413 *arg
= mem_range_softc
.mr_ndesc
;
415 bcopy(mem_range_softc
.mr_desc
, mrd
, (*arg
) * sizeof(struct mem_range_desc
));
421 mem_range_attr_set(mrd
, arg
)
422 struct mem_range_desc
*mrd
;
425 /* can we handle this? */
426 if (mem_range_softc
.mr_op
== NULL
)
429 return (mem_range_softc
.mr_op
->set(&mem_range_softc
, mrd
, arg
));
434 mem_range_AP_init(void)
436 if (mem_range_softc
.mr_op
&& mem_range_softc
.mr_op
->initAP
)
437 return (mem_range_softc
.mr_op
->initAP(&mem_range_softc
));
442 random_ioctl(dev_t dev
, u_long cmd
, caddr_t data
, int flags
, struct thread
*td
)
444 static intrmask_t interrupt_allowed
;
445 intrmask_t interrupt_mask
;
449 * We're the random or urandom device. The only ioctls are for
450 * selecting and inspecting which interrupts are used in the muck
451 * gathering business and the fcntl() stuff.
453 if (cmd
!= MEM_SETIRQ
&& cmd
!= MEM_CLEARIRQ
&& cmd
!= MEM_RETURNIRQ
454 && cmd
!= FIONBIO
&& cmd
!= FIOASYNC
)
458 * XXX the data is 16-bit due to a historical botch, so we use
459 * magic 16's instead of ICU_LEN and can't support 24 interrupts
461 * Even inspecting the state is privileged, since it gives a hint
462 * about how easily the randomness might be guessed.
464 intr
= *(int16_t *)data
;
465 interrupt_mask
= 1 << intr
;
467 /* Really handled in upper layer */
475 if (intr
< 0 || intr
>= 16)
477 if (interrupt_allowed
& interrupt_mask
)
479 interrupt_allowed
|= interrupt_mask
;
480 register_randintr(intr
);
486 if (intr
< 0 || intr
>= 16)
488 if (!(interrupt_allowed
& interrupt_mask
))
490 interrupt_allowed
&= ~interrupt_mask
;
491 unregister_randintr(intr
);
497 *(u_int16_t
*)data
= interrupt_allowed
;
504 mmpoll(dev_t dev
, int events
, struct thread
*td
)
506 switch (minor(dev
)) {
507 case 3: /* /dev/random */
508 return random_poll(dev
, events
, td
);
509 case 4: /* /dev/urandom */
511 return seltrue(dev
, events
, td
);
519 return ((major(dev
) == mem_cdevsw
.d_maj
)
520 && minor(dev
) == 12);
524 mem_drvinit(void *unused
)
527 /* Initialise memory range handling */
528 if (mem_range_softc
.mr_op
!= NULL
)
529 mem_range_softc
.mr_op
->init(&mem_range_softc
);
531 cdevsw_add(&mem_cdevsw
, 0xf0, 0);
532 make_dev(&mem_cdevsw
, 0, UID_ROOT
, GID_KMEM
, 0640, "mem");
533 make_dev(&mem_cdevsw
, 1, UID_ROOT
, GID_KMEM
, 0640, "kmem");
534 make_dev(&mem_cdevsw
, 2, UID_ROOT
, GID_WHEEL
, 0666, "null");
535 make_dev(&mem_cdevsw
, 3, UID_ROOT
, GID_WHEEL
, 0644, "random");
536 make_dev(&mem_cdevsw
, 4, UID_ROOT
, GID_WHEEL
, 0644, "urandom");
537 make_dev(&mem_cdevsw
, 12, UID_ROOT
, GID_WHEEL
, 0666, "zero");
538 make_dev(&mem_cdevsw
, 14, UID_ROOT
, GID_WHEEL
, 0600, "io");
541 SYSINIT(memdev
,SI_SUB_DRIVERS
,SI_ORDER_MIDDLE
+CDEV_MAJOR
,mem_drvinit
,NULL
)