lkml.org 
[lkml]   [2008]   [Jan]   [15]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateTue, 15 Jan 2008 18:39:59 -0800
From venkatesh.pallipadi@intel ...
Subject[patch 4/4] x86: PAT followup - use ioremap for devmem read of reserved regions
map and unmap reserved regions, before accessing through /dev/mem read
interface. This is for full compatibility with existing /dev/mem
usages.
For regions that are mapped in identity map, we use __va().

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>

Index: linux-2.6.git/arch/x86/mm/ioremap.c
===================================================================
--- linux-2.6.git.orig/arch/x86/mm/ioremap.c	2008-01-15 10:05:13.000000000 -0800
+++ linux-2.6.git/arch/x86/mm/ioremap.c	2008-01-15 10:39:18.000000000 -0800
@@ -32,6 +32,39 @@
 }
 EXPORT_SYMBOL(ioremap_wc);
 
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+void *xlate_dev_mem_ptr(unsigned long phys)
+{
+	void *addr;
+	unsigned long start = phys & PAGE_MASK;
+
+	/*
+	 * If any memory in PAGE_SIZE is valid, then we can use __va. Otherwise
+	 * ioremap and unmap the memory.
+	 */
+	if (is_memory_any_valid(start, start + PAGE_SIZE))
+		return __va(phys);
+
+	addr = (void *)ioremap(start, PAGE_SIZE);
+	if (addr)
+		addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
+
+	return addr;
+}
+
+void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+{
+	unsigned long start = phys & PAGE_MASK;
+	if (is_memory_any_valid(start, start + PAGE_SIZE))
+		return;
+
+	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
+	return;
+}
+
 int valid_phys_addr_range(unsigned long addr, size_t count)
 {
 	if (addr + count > __pa(high_memory))
Index: linux-2.6.git/drivers/char/mem.c
===================================================================
--- linux-2.6.git.orig/drivers/char/mem.c	2008-01-15 10:05:13.000000000 -0800
+++ linux-2.6.git/drivers/char/mem.c	2008-01-15 10:05:51.000000000 -0800
@@ -127,9 +127,14 @@
 		 * by the kernel or data corruption may occur
 		 */
 		ptr = xlate_dev_mem_ptr(p);
+		if (!ptr)
+			return -EFAULT;
 
 		if (copy_to_user(buf, ptr, sz))
 			return -EFAULT;
+
+		unxlate_dev_mem_ptr(p, ptr);
+
 		buf += sz;
 		p += sz;
 		count -= sz;
@@ -184,6 +189,11 @@
 		 * by the kernel or data corruption may occur
 		 */
 		ptr = xlate_dev_mem_ptr(p);
+		if (!ptr) {
+			if (written)
+				break;
+			return -EFAULT;
+		}
 
 		copied = copy_from_user(ptr, buf, sz);
 		if (copied) {
@@ -192,6 +202,9 @@
 				break;
 			return -EFAULT;
 		}
+
+		unxlate_dev_mem_ptr(p, ptr);
+
 		buf += sz;
 		p += sz;
 		count -= sz;
Index: linux-2.6.git/include/asm-generic/iomap.h
===================================================================
--- linux-2.6.git.orig/include/asm-generic/iomap.h	2008-01-15 10:05:13.000000000 -0800
+++ linux-2.6.git/include/asm-generic/iomap.h	2008-01-15 10:23:24.000000000 -0800
@@ -69,4 +69,8 @@
 #define ioremap_wc ioremap_nocache
 #endif
 
+#ifndef unxlate_dev_mem_ptr
+static inline void unxlate_dev_mem_ptr(unsigned long phys, void *addr) {}
+#endif
+
 #endif
Index: linux-2.6.git/include/asm-x86/io.h
===================================================================
--- linux-2.6.git.orig/include/asm-x86/io.h	2008-01-15 10:05:13.000000000 -0800
+++ linux-2.6.git/include/asm-x86/io.h	2008-01-15 10:21:42.000000000 -0800
@@ -2,6 +2,7 @@
 #define _ASM_X86_IO_H
 
 #define ioremap_wc ioremap_wc
+#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
 
 #ifdef CONFIG_X86_32
 # include "io_32.h"
@@ -10,6 +11,8 @@
 #endif
 
 extern void __iomem * ioremap_wc(unsigned long offset, unsigned long size);
+extern void *xlate_dev_mem_ptr(unsigned long phys);
+extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
 
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
 
Index: linux-2.6.git/include/asm-x86/io_32.h
===================================================================
--- linux-2.6.git.orig/include/asm-x86/io_32.h	2008-01-15 10:05:13.000000000 -0800
+++ linux-2.6.git/include/asm-x86/io_32.h	2008-01-15 10:05:51.000000000 -0800
@@ -49,12 +49,6 @@
 #include <linux/vmalloc.h>
 
 /*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)	__va(p)
-
-/*
  * Convert a virtual cached pointer to an uncached pointer
  */
 #define xlate_dev_kmem_ptr(p)	p
Index: linux-2.6.git/include/asm-x86/io_64.h
===================================================================
--- linux-2.6.git.orig/include/asm-x86/io_64.h	2008-01-15 10:05:13.000000000 -0800
+++ linux-2.6.git/include/asm-x86/io_64.h	2008-01-15 10:05:51.000000000 -0800
@@ -278,12 +278,6 @@
 #define BIO_VMERGE_BOUNDARY iommu_bio_merge
 
 /*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)	__va(p)
-
-/*
  * Convert a virtual cached pointer to an uncached pointer
  */
 #define xlate_dev_kmem_ptr(p)	p
-- 


\
 
 \ /
  Last update: 2008-01-16 02:45    [from the cache]
©2003-2008