diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2010-01-09 18:52:00 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2010-01-09 18:52:00 +0000 |
commit | 293ee78424e1ac4a69060303df215db34a329a25 (patch) | |
tree | 4c106736709410ca3d55224fc704986b30d8a3c8 /sys/arch | |
parent | 2b0b9e6678db5218af464e10855bfc5c25430ece (diff) |
Correctly check /dev/kmem offsets within directly translated segments (XKPHYS
or CKSEG) against the actual physical memory segments, instead of assuming
contiguous physical memory starting from zero, as this is utterly wrong
on Octane (and a bit less wrong on other systems (-: )
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/mips64/mips64/mem.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/sys/arch/mips64/mips64/mem.c b/sys/arch/mips64/mips64/mem.c index a68d2f64cc6..4e2cedaa2a8 100644 --- a/sys/arch/mips64/mips64/mem.c +++ b/sys/arch/mips64/mips64/mem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mem.c,v 1.13 2009/11/19 20:16:27 miod Exp $ */ +/* $OpenBSD: mem.c,v 1.14 2010/01/09 18:51:59 miod Exp $ */ /* $NetBSD: mem.c,v 1.6 1995/04/10 11:55:03 mycroft Exp $ */ /* @@ -57,9 +57,12 @@ #include <machine/autoconf.h> #include <machine/cpu.h> +#include <machine/memconf.h> #include <uvm/uvm_extern.h> +boolean_t is_memory_range(paddr_t, psize_t, psize_t); + caddr_t zeropage; #define mmread mmrw @@ -125,21 +128,19 @@ mmrw(dev_t dev, struct uio *uio, int flags) c = min(iov->iov_len, MAXPHYS); /* Allow access to RAM through XKPHYS... */ - if (IS_XKPHYS(v) && IS_XKPHYS(v + (vsize_t)c) && - XKPHYS_TO_PHYS(v + (vsize_t)c) <= ptoa(physmem)) - allowed = TRUE; + if (IS_XKPHYS(v)) + allowed = is_memory_range(XKPHYS_TO_PHYS(v), + (psize_t)c, 0); /* ...or through CKSEG0... */ else if (v >= CKSEG0_BASE && - v + (vsize_t)c < CKSEG0_BASE + CKSEG_SIZE && - (physmem >= atop(CKSEG_SIZE) || - v + (vsize_t)c <= CKSEG0_BASE + ptoa(physmem))) - allowed = TRUE; + v < CKSEG0_BASE + CKSEG_SIZE) + allowed = is_memory_range(CKSEG0_TO_PHYS(v), + (psize_t)c, CKSEG_SIZE); /* ...or through CKSEG1... */ else if (v >= CKSEG1_BASE && - v + (vsize_t)c < CKSEG1_BASE + CKSEG_SIZE && - (physmem >= atop(CKSEG_SIZE) || - v + c <= CKSEG1_BASE + ptoa(physmem))) - allowed = TRUE; + v < CKSEG1_BASE + CKSEG_SIZE) + allowed = is_memory_range(CKSEG1_TO_PHYS(v), + (psize_t)c, CKSEG_SIZE); /* ...otherwise, check it's within kernel kvm limits. */ else allowed = uvm_kernacc((caddr_t)v, c, @@ -196,3 +197,23 @@ mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) { return (EOPNOTSUPP); } + +boolean_t +is_memory_range(paddr_t pa, psize_t len, psize_t limit) +{ + struct phys_mem_desc *seg; + uint64_t fp, lp; + int i; + + fp = atop(pa); + lp = atop(round_page(pa + len)); + + if (limit != 0 && lp > atop(limit)) + return FALSE; + + for (i = 0, seg = mem_layout; i < MAXMEMSEGS; i++, seg++) + if (fp >= seg->mem_first_page && lp <= seg->mem_last_page) + return TRUE; + + return FALSE; +} |