Last active
July 5, 2018 18:38
-
-
Save paulburton/88d0fa2f7525a0e9f1d8dd80d985ab72 to your computer and use it in GitHub Desktop.
Rough MIPS __ioremap RAM check fix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c | |
index 1986e09fb457..19ffd8370db4 100644 | |
--- a/arch/mips/mm/ioremap.c | |
+++ b/arch/mips/mm/ioremap.c | |
@@ -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)) { | |
+ WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n", | |
+ &phys_addr, &last_addr); | |
+ return NULL; | |
} | |
/* |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment