summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-01-09 18:52:00 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-01-09 18:52:00 +0000
commit293ee78424e1ac4a69060303df215db34a329a25 (patch)
tree4c106736709410ca3d55224fc704986b30d8a3c8 /sys/arch
parent2b0b9e6678db5218af464e10855bfc5c25430ece (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.c45
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;
+}