|
@@ -9,6 +9,7 @@
|
|
|
#include <linux/export.h>
|
|
|
#include <asm/addrspace.h>
|
|
|
#include <asm/byteorder.h>
|
|
|
+#include <linux/ioport.h>
|
|
|
#include <linux/sched.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/vmalloc.h>
|
|
@@ -98,6 +99,20 @@ static int remap_area_pages(unsigned long address, phys_addr_t phys_addr,
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
+static int __ioremap_check_ram(unsigned long start_pfn, unsigned long nr_pages,
|
|
|
+ void *arg)
|
|
|
+{
|
|
|
+ unsigned long i;
|
|
|
+
|
|
|
+ for (i = 0; i < nr_pages; i++) {
|
|
|
+ if (pfn_valid(start_pfn + i) &&
|
|
|
+ !PageReserved(pfn_to_page(start_pfn + i)))
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Generic mapping function (not visible outside):
|
|
|
*/
|
|
@@ -116,8 +131,8 @@ static int remap_area_pages(unsigned long address, phys_addr_t phys_addr,
|
|
|
|
|
|
void __iomem * __ioremap(phys_addr_t phys_addr, phys_addr_t size, unsigned long flags)
|
|
|
{
|
|
|
+ unsigned long offset, pfn, last_pfn;
|
|
|
struct vm_struct * area;
|
|
|
- unsigned long offset;
|
|
|
phys_addr_t last_addr;
|
|
|
void * addr;
|
|
|
|
|
@@ -137,18 +152,16 @@ void __iomem * __ioremap(phys_addr_t phys_addr, phys_addr_t size, unsigned long
|
|
|
return (void __iomem *) CKSEG1ADDR(phys_addr);
|
|
|
|
|
|
/*
|
|
|
- * Don't allow anybody to remap normal RAM that we're using..
|
|
|
+ * Don't allow anybody to remap RAM that may be allocated by the page
|
|
|
+ * allocator, since that could lead to races & data clobbering.
|
|
|
*/
|
|
|
- if (phys_addr < virt_to_phys(high_memory)) {
|
|
|
- char *t_addr, *t_end;
|
|
|
- struct page *page;
|
|
|
-
|
|
|
- t_addr = __va(phys_addr);
|
|
|
- t_end = t_addr + (size - 1);
|
|
|
-
|
|
|
- for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
|
|
|
- if(!PageReserved(page))
|
|
|
- return NULL;
|
|
|
+ pfn = PFN_DOWN(phys_addr);
|
|
|
+ last_pfn = PFN_DOWN(last_addr);
|
|
|
+ if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
|
|
|
+ __ioremap_check_ram) == 1) {
|
|
|
+ WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n",
|
|
|
+ &phys_addr, &last_addr);
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
/*
|