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 * 4. 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.
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
35 * from: Utah $Hdr: mem.c 1.13 89/10/08$
36 * from: @(#)mem.c 7.2 (Berkeley) 5/9/91
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
46 #include <sys/param.h>
48 #include <sys/fcntl.h>
49 #include <sys/ioccom.h>
50 #include <sys/kernel.h>
52 #include <sys/malloc.h>
53 #include <sys/memrange.h>
54 #include <sys/module.h>
55 #include <sys/mutex.h>
58 #include <sys/signalvar.h>
59 #include <sys/systm.h>
62 #include <machine/specialreg.h>
66 #include <vm/vm_extern.h>
68 #include <machine/memdev.h>
71 * Used in /dev/mem drivers and elsewhere
73 MALLOC_DEFINE(M_MEMDESC
, "memdesc", "memory range descriptors");
75 static struct sx memsxlock
;
76 SX_SYSINIT(memsxlockinit
, &memsxlock
, "/dev/mem lock");
80 memrw(struct cdev
*dev
, struct uio
*uio
, int flags
)
89 if (dev2unit(dev
) != CDEV_MINOR_MEM
&& dev2unit(dev
) != CDEV_MINOR_KMEM
)
92 if (dev2unit(dev
) == CDEV_MINOR_KMEM
&& uio
->uio_resid
> 0) {
93 if (uio
->uio_offset
< (vm_offset_t
)VADDR(PTDPTDI
, 0))
96 if (!kernacc((caddr_t
)(int)uio
->uio_offset
, uio
->uio_resid
,
97 uio
->uio_rw
== UIO_READ
? VM_PROT_READ
: VM_PROT_WRITE
))
101 while (uio
->uio_resid
> 0 && error
== 0) {
103 if (iov
->iov_len
== 0) {
106 if (uio
->uio_iovcnt
< 0)
110 if (dev2unit(dev
) == CDEV_MINOR_MEM
) {
111 pa
= uio
->uio_offset
;
115 * Extract the physical page since the mapping may
116 * change at any time. This avoids panics on page
117 * fault in this case but will cause reading/writing
119 * Hopefully an application will notice the wrong
120 * data on read access and refrain from writing.
121 * This should be replaced by a special uiomove
122 * type function that just returns an error if there
123 * is a page fault on a kernel page.
125 addr
= trunc_page(uio
->uio_offset
);
126 pa
= pmap_extract(kernel_pmap
, addr
);
133 * XXX UPS This should just use sf_buf_alloc.
134 * Unfortunately sf_buf_alloc needs a vm_page
135 * and we may want to look at memory not covered
139 sx_xlock(&memsxlock
);
140 pmap_kenter((vm_offset_t
)ptvmmap
, pa
);
141 pmap_invalidate_page(kernel_pmap
,(vm_offset_t
)ptvmmap
);
143 o
= (int)uio
->uio_offset
& PAGE_MASK
;
145 c
= min(c
, (u_int
)iov
->iov_len
);
146 error
= uiomove((caddr_t
)&ptvmmap
[o
], (int)c
, uio
);
147 pmap_qremove((vm_offset_t
)ptvmmap
, 1);
148 sx_xunlock(&memsxlock
);
156 * allow user processes to MMAP some memory sections
157 * instead of going through read/write
161 memmmap(struct cdev
*dev
, vm_ooffset_t offset
, vm_paddr_t
*paddr
,
162 int prot __unused
, vm_memattr_t
*memattr __unused
)
164 if (dev2unit(dev
) == CDEV_MINOR_MEM
)
166 else if (dev2unit(dev
) == CDEV_MINOR_KMEM
)
167 *paddr
= vtophys(offset
);
173 * Operations for changing memory attributes.
175 * This is basically just an ioctl shim for mem_range_attr_get
176 * and mem_range_attr_set.
180 memioctl(struct cdev
*dev __unused
, u_long cmd
, caddr_t data
, int flags
,
184 struct mem_range_op
*mo
= (struct mem_range_op
*)data
;
185 struct mem_range_desc
*md
;
187 /* is this for us? */
188 if ((cmd
!= MEMRANGE_GET
) &&
189 (cmd
!= MEMRANGE_SET
))
192 /* any chance we can handle this? */
193 if (mem_range_softc
.mr_op
== NULL
)
196 /* do we have any descriptors? */
197 if (mem_range_softc
.mr_ndesc
== 0)
202 nd
= imin(mo
->mo_arg
[0], mem_range_softc
.mr_ndesc
);
204 md
= (struct mem_range_desc
*)
205 malloc(nd
* sizeof(struct mem_range_desc
),
206 M_MEMDESC
, M_WAITOK
);
207 error
= mem_range_attr_get(md
, &nd
);
209 error
= copyout(md
, mo
->mo_desc
,
210 nd
* sizeof(struct mem_range_desc
));
214 nd
= mem_range_softc
.mr_ndesc
;
219 md
= (struct mem_range_desc
*)malloc(sizeof(struct mem_range_desc
),
220 M_MEMDESC
, M_WAITOK
);
221 error
= copyin(mo
->mo_desc
, md
, sizeof(struct mem_range_desc
));
222 /* clamp description string */
223 md
->mr_owner
[sizeof(md
->mr_owner
) - 1] = 0;
225 error
= mem_range_attr_set(md
, &mo
->mo_arg
[0]);