Messages in this thread Patch in this message | | | Date | Mon, 16 Dec 1996 13:58:20 +0100 (MET) | From | Marcin Dalecki <> | Subject | /dev/kmem /dev/mem PATCH for kernel 2.1.15 |
| |
Just recently I sendid a patch, which fixed the behaviour of /dev/kmem but broke /dev/mem. During this weekend I took the time to dig something deeper into the memory mapping organization. Here is the hopefully correct patch for the behaviour of the reading functions. We can't relay on /dev/mem in /dev/kmem after the kernel has been remapped to 0xC0000000. Just recently someone created an device with major number 1 and minor number 0. It was called ram but that's exactly what /dev/mem is supposed to do: read the physical ram mapping. The virtual address space should be accessed by /dev/kmem (see man 2 kmem or man 2 mem for confirmance.)
The writing function for /dev/kmem still deservs fixing... But the ability to write into the kernel space wasn't important at this point for mee.
Marcin
diff -urN linux-old/drivers/char/mem.c linux/drivers/char/mem.c --- linux-old/drivers/char/mem.c Sat Dec 14 17:35:51 1996 +++ linux/drivers/char/mem.c Sat Dec 14 19:52:42 1996 @@ -34,18 +34,10 @@ void pcwatchdog_init(void); #endif -static long read_ram(struct inode * inode, struct file * file, - char * buf, unsigned long count) -{ - return -EIO; -} - -static long write_ram(struct inode * inode, struct file * file, - const char * buf, unsigned long count) -{ - return -EIO; -} - +/* + * This funcions reads the *physical* memory. The f_pos points directly to the + * memory location. + */ static long read_mem(struct inode * inode, struct file * file, char * buf, unsigned long count) { @@ -53,8 +45,6 @@ unsigned long end_mem; int read; - if (count < 0) - return -EINVAL; end_mem = __pa(high_memory); if (p >= end_mem) return 0; @@ -83,8 +73,6 @@ unsigned long end_mem; int written; - if (count < 0) - return -EINVAL; end_mem = __pa(high_memory); if (p >= end_mem) return 0; @@ -130,19 +118,41 @@ return 0; } +/* + * This function read's the *virtual* memory as seen by the kernel. + */ static long read_kmem(struct inode *inode, struct file *file, char *buf, unsigned long count) { - int read1, read2; + unsigned long p = file->f_pos; + unsigned long read = 0; + long virtr; + + if (p < (unsigned long) high_memory) { + unsigned long tmp; + + if (count > (unsigned long) high_memory - p) + tmp = (unsigned long) high_memory - p; + else + tmp = count; + read = tmp; +#if defined(__sparc__) /* we don't have page 0 mapped on sparc.. */ + while (p < PAGE_SIZE && tmp > 0) { + put_user(0,buf); + buf++; + p++; + tmp--; + } +#endif + copy_to_user(buf, (char *) p, tmp); + buf += tmp; + } - read1 = read_mem(inode, file, buf, count); - if (read1 < 0) - return read1; - read2 = vread(buf + read1, (char *) ((unsigned long) file->f_pos), count - read1); - if (read2 < 0) - return read2; - file->f_pos += read2; - return read1 + read2; + virtr = vread(buf, (char *) (unsigned long) file->f_pos, count - read); + if (virtr < 0) + return virtr; + file->f_pos += virtr + read; + return virtr + read; } static long read_port(struct inode * inode, struct file * file, @@ -301,19 +311,6 @@ #define zero_lseek null_lseek #define write_zero write_null -static struct file_operations ram_fops = { - memory_lseek, - read_ram, - write_ram, - NULL, /* ram_readdir */ - NULL, /* ram_select */ - NULL, /* ram_ioctl */ - NULL, /* ram_mmap */ - NULL, /* no special open code */ - NULL, /* no special release code */ - NULL /* fsync */ -}; - static struct file_operations mem_fops = { memory_lseek, read_mem, @@ -393,9 +390,6 @@ static int memory_open(struct inode * inode, struct file * filp) { switch (MINOR(inode->i_rdev)) { - case 0: - filp->f_op = &ram_fops; - break; case 1: filp->f_op = &mem_fops; break;
| |