diff options
author | marcel <marcel@FreeBSD.org> | 2003-06-04 21:56:10 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2003-06-04 21:56:10 +0000 |
commit | 23fb7b1d8ae16786c3d0b8f3981f6fd027669b2e (patch) | |
tree | d0abb41f35b15c8128a7ae033c88a20a4d858a65 /sys/ia64 | |
parent | 482a35058c1ec5165650b6b75eab0e46a3cafd33 (diff) | |
download | FreeBSD-src-23fb7b1d8ae16786c3d0b8f3981f6fd027669b2e.zip FreeBSD-src-23fb7b1d8ae16786c3d0b8f3981f6fd027669b2e.tar.gz |
Fix the dreaded double counting that was present on alpha as well and
got fixed two weeks after the ia64 version was copied from the alpha
version (see rev 1.32 of sys/alpha/alpha/mem.c). As such, we were
missing the same continue as on alpha.
While here, add a default case for the device minor switch and do
some general style(9) cleanups.
WARNING: this file still has bugs. When reading from region 6 or
region 7, we don't validate the physical address. One can trivially
cause a machine check by trying to read from address 0xFFFFFFFFFFFFFFF0
or something that uses the unimplemented physical address bits.
Reported by: Alan Robinson <alan.robinson@fujitsu-siemens.com>
Diffstat (limited to 'sys/ia64')
-rw-r--r-- | sys/ia64/ia64/mem.c | 38 |
1 files changed, 21 insertions, 17 deletions
diff --git a/sys/ia64/ia64/mem.c b/sys/ia64/ia64/mem.c index 75b65ae..cd4f3b1 100644 --- a/sys/ia64/ia64/mem.c +++ b/sys/ia64/ia64/mem.c @@ -139,12 +139,11 @@ mmopen(dev_t dev, int flags, int fmt, struct thread *td) static int mmrw(dev_t dev, struct uio *uio, int flags) { - vm_offset_t o, v; - int c = 0; struct iovec *iov; - int error = 0, rw; - vm_offset_t addr, eaddr; + vm_offset_t addr, eaddr, o, v; + int c, error, rw; + error = 0; while (uio->uio_resid > 0 && !error) { iov = uio->uio_iov; if (iov->iov_len == 0) { @@ -154,6 +153,7 @@ mmrw(dev_t dev, struct uio *uio, int flags) panic("mmrw"); continue; } + switch (minor(dev)) { /* minor device 0 is physical memory */ @@ -161,7 +161,8 @@ mmrw(dev_t dev, struct uio *uio, int flags) v = uio->uio_offset; kmemphys: /* Allow reads only in RAM. */ - rw = (uio->uio_rw == UIO_READ) ? VM_PROT_READ : VM_PROT_WRITE; + rw = (uio->uio_rw == UIO_READ) + ? VM_PROT_READ : VM_PROT_WRITE; if ((ia64_pa_access(v) & rw) != rw) { error = EFAULT; c = 0; @@ -170,8 +171,7 @@ kmemphys: o = uio->uio_offset & PAGE_MASK; c = min(uio->uio_resid, (int)(PAGE_SIZE - o)); - error = - uiomove((caddr_t)IA64_PHYS_TO_RR7(v), c, uio); + error = uiomove((caddr_t)IA64_PHYS_TO_RR7(v), c, uio); continue; /* minor device 1 is kernel memory */ @@ -184,22 +184,26 @@ kmemphys: } c = min(iov->iov_len, MAXPHYS); + /* - * Make sure that all of the pages are currently resident so - * that we don't create any zero-fill pages. + * Make sure that all of the pages are currently + * resident so that we don't create any zero-fill + * pages. */ addr = trunc_page(v); eaddr = round_page(v + c); - for (; addr < eaddr; addr += PAGE_SIZE) - if (pmap_extract(kernel_pmap, addr) == 0) { - return EFAULT; - } - if (!kernacc((caddr_t)v, c, - uio->uio_rw == UIO_READ ? - VM_PROT_READ : VM_PROT_WRITE)) { - return (EFAULT); + for (; addr < eaddr; addr += PAGE_SIZE) { + if (pmap_extract(kernel_pmap, addr) == 0) + return (EFAULT); } + if (!kernacc((caddr_t)v, c, (uio->uio_rw == UIO_READ) + ? VM_PROT_READ : VM_PROT_WRITE)) + return (EFAULT); error = uiomove((caddr_t)v, c, uio); + continue; + + default: + return (ENODEV); } if (error) |