Subject: Should /dev/kmem support above 0x80000000 area?

From: Jun Sun <[email-masked]>
Date: Thu, 07 Dec 2000 19:13:05 -0800

Currently one cannot read memory area above 0x80000000 throught /dev/kmem.  In
fact, an earlier bug would put the process into an infinite loop if you try to
do that.  That seems to be fixed now.

It seems to be very useful if we do allow that access.  What do you think?

Ralf, if we do want to enable it - which is pretty simple to do -, should I
give you the patch or shuld I submit it to somebody else who is maintaining
/dev/kmem?

Jun

---

From: Ralf Baechle <[email-masked]>
Date: Sat, 9 Dec 2000 00:32:23 +0100

> It seems to be very useful if we do allow that access.  What do you think?

Actually there is almost nothing left that uses /dev/{mem,kmem} these days.
Nevertheless it's a supported interface, so we have to get it right.

> give you the patch or shuld I submit it to somebody else who is maintaining

Send me the patch and I'll comment.

  Ralf

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Mon, 11 Dec 2000 12:28:19 +0100 (MET)

> Actually there is almost nothing left that uses /dev/{mem,kmem} these days.

 Last time I checked /dev/mem worked as expected.  For Alpha /dev/mem is
used to emulate PCI/ISA I/O space accesses (ioperm(), inb/outb() and
friends) by glibc.  At least XFree86 and SVGATextMode make use of these
features.  I suppose it's the same for MIPS (I haven't checked, though). 

 In general /dev/mem is useful for poking at hardware from user space.  On
the other hand, /dev/kmem is not very useful anymore, indeed. 

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email-masked], PGP key available        +

---

From: Guido Guenther <[email-masked]>
Date: Mon, 11 Dec 2000 13:41:33 +0100

> features.  I suppose it's the same for MIPS (I haven't checked, though). 
Yes. xf86MapVidMem & friends use /dev/mem to mmap videomemory & iospace
independent of architecure.
 -- Guido

---

From: Jun Sun <[email-masked]>
Date: Mon, 11 Dec 2000 18:26:51 -0800

> independent of architecure.

I am surprised.  I thought /dev/mem is for accessing SYSTEM RAM.  (do a 'man'
on /dev/mem)  It is also confirmed by the code in drivers/char/mem.c.  If you
want to access anything beyond 'high_memory", nothing is read.  

Note that drivers/char/mem.c is cross-platform code.  I am not sure how X
would access video memory through /dev/mem on either MIPS or other platforms.

That reason I want to fix /dev/kmem is that in some cases before a driver is
written people want to play with the hardware directly from the userland
(especially for demo purpose. :-0)  Very useful for embedded systems.

Potentially fixing /dev/mem can do the same job.  However /dev/mem cannot
differentiate cached or uncached accesses.  With /dev/kmem, we just specify
0x8.. or 0xa....

Jun

---

From: Guido Guenther <[email-masked]>
Date: Mon, 11 Dec 2000 19:56:30 +0100

> I am surprised.  I thought /dev/mem is for accessing SYSTEM RAM.  (do a 'man'
I'd not call it system ram but rather ''visible address space'' or
something. If there's actually ''system ram'' or the fb of a graphics
card at a given address doesn't make a difference.

> would access video memory through /dev/mem on either MIPS or other platforms.
The newports REX3 for example is at (KSEG1 + 0x1f0f000) which is mmaped
by the xserver to access the REX3s registers.
 -- Guido

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Mon, 11 Dec 2000 20:05:45 +0100 (MET)

> I am surprised.  I thought /dev/mem is for accessing SYSTEM RAM.  (do a 'man'

 You access the memory space.  Whatever is found at the address you
specify, be it RAM, an MMIO area or unoccupied space.  You may receive a
bus error in the latter case (depending on a system configuration). 

> want to access anything beyond 'high_memory", nothing is read.  

 Yep, you may only use read()/write() for system RAM.  For other areas you
have to mmap() the interesting part of /dev/mem and then access it
directly (which is easier and better anyway, as you may control the width
of bus transfers -- not all MMIO devices support all widths). 

> would access video memory through /dev/mem on either MIPS or other platforms.

 It mmap()s the areas it's interested in.  Read the code!

> (especially for demo purpose. :-0)  Very useful for embedded systems.

 I'm not sure how to use /dev/kmem for this purpose -- it's kernel's
*virtual* memory...
 
> differentiate cached or uncached accesses.  With /dev/kmem, we just specify

 Yep, /dev/mem for non system RAM areas is always uncached which is what
is almost always desired (for system RAM areas you may request
uncacheability by passing O_SYNC when opening the file).

 Anyway, /dev/mem works great -- I've successfully used it to access APICs
(at 0xfec00000 and 0xfee00000) in my i386 system and various stuff (an
NVRAM at 0x1c000000, a graphics accelerator at 0x1e000000, a FDDI network
controller at 0x1f000000, onboard I/O stuff at 0x1f800000 and a system ROM
at 0x1fc00000) in my DECstation.

---

From: Jun Sun <[email-masked]>
Date: Mon, 11 Dec 2000 22:16:46 -0800

> of bus transfers -- not all MMIO devices support all widths).

I see.  It is funny that you cannot read/write memory beyond high_memory
through /dev/mem, but you can re-map it and then read/write through the
remapped region.

How do you control the width of bus transfers?  If you have direct access to
the device memory, the userland "drivers" should be able to deal with the bus
access width correctly.

>  I'm not sure how to use /dev/kmem for this purpose -- it's kernel's

kseg0 and kseg1 are part of kernel virtual memory space.  If we implement
/dev/kmem correctly, one should be able to directly read/write those area by
specifying 0x80000000 or 0xa0000000 offsets through /dev/kmem.

Jun

---

From: Jun Sun <[email-masked]>
Date: Mon, 11 Dec 2000 23:38:36 -0800

> Send me the patch and I'll comment.

Here is my patch.  I think it should be safe for mips64.  Please double check
it.

Jun

diff -Nru linux/drivers/char/mem.c.orig linux/drivers/char/mem.c
--- linux/drivers/char/mem.c.orig	Mon Dec 11 22:07:19 2000
+++ linux/drivers/char/mem.c	Mon Dec 11 22:38:11 2000
@@ -258,6 +258,14 @@
 		count -= read;
 	}
 
+#if defined(__mips__)
+        if (KSEGX(p)) {
+		if (copy_to_user(buf, (char*)p, count))
+			return -EFAULT;
+		return count+read;
+	}
+#endif
+
 	kbuf = (char *)__get_free_page(GFP_KERNEL);
 	if (!kbuf)
 		return -ENOMEM;
@@ -288,6 +296,12 @@
 			  size_t count, loff_t *ppos)
 {
 	unsigned long p = *ppos;
+
+#if defined(__mips__)
+        if (KSEGX(p)) {
+		return do_write_mem(file, (void*)p, p, buf, count, ppos);
+	}
+#endif
 
 	if (p >= (unsigned long) high_memory)
 		return 0;

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Tue, 12 Dec 2000 12:58:18 +0100 (MET)

> through /dev/mem, but you can re-map it and then read/write through the

 I see it consistent.  The system memory can be treated like a stream of
bytes.  That's much like any random-access file.  Other devices do not
necessarily exhibit this behaviour.  They may implement side effects,
values read may be different from what was written previously.  You may
even achieve different effects by performing transfers of different
widths. 

> the device memory, the userland "drivers" should be able to deal with the bus

 If you declare a location int32_t, gcc will perform a 32-bit access on
assignment (lw/sw for MIPS).  If you declare a location int16_t, gcc will
perform a 16-bit access (lh/sh for MIPS).  Ditto for int8_t (and for
int64_t for 64-bit configurations).  Names of types do not matter, of
course, sizeof -- does.  I just used the ISO C portable names for
fixed-size types.  Please note you might need to use the "volatile" 
keyword or gcc might reorder or even optimize out certain accesses. 

> specifying 0x80000000 or 0xa0000000 offsets through /dev/kmem.

 But this is highly unportable.  MIPS has trivially mapped virtual memory
areas but many (most?) architectures do not.

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Tue, 12 Dec 2000 14:23:47 +0100 (MET)

> Here is my patch.  I think it should be safe for mips64.  Please double check

 I don't think we should allow access to non page-mapped areas as well as
read()/write() for non-memory areas.  That would be inconsistent with the
idea of /dev/kmem and the implementation for other ports.

---

From: Jun Sun <[email-masked]>
Date: Tue, 12 Dec 2000 10:53:48 -0800

> keyword or gcc might reorder or even optimize out certain accesses.

I see the point now.  It is not such a good idea to map IO memory through a
file API, especially given that we have a working /dev/mem.

Ralf, I "officially" retract my previous patch.

Jun