diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-01-18 23:34:38 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-01-18 23:34:38 -0500 |
commit | d57d64080ddc0ff13fcffc898b6251074a482ba1 (patch) | |
tree | c38fd506a30d56de84a39285412ffc1b45cc8d33 /arch/sh | |
parent | af1415314a4190b8ea06e53808d392fcf91555af (diff) |
sh: Prevent 64-bit pgprot clobbering across ioremap implementations.
Presently 'flags' gets passed around a lot between the various ioremap
helpers and implementations, which is only 32-bits. In the X2TLB case
we use 64-bit pgprots which presently results in the upper 32bits being
chopped off (which handily include our read/write/exec permissions).
As such, we convert everything internally to using pgprot_t directly and
simply convert over with pgprot_val() where needed. With this in place,
transparent fixmap utilization for early ioremap works as expected.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/boards/board-sh7785lcr.c | 6 | ||||
-rw-r--r-- | arch/sh/boards/mach-landisk/setup.c | 2 | ||||
-rw-r--r-- | arch/sh/boards/mach-lboxre2/setup.c | 2 | ||||
-rw-r--r-- | arch/sh/boards/mach-sh03/setup.c | 2 | ||||
-rw-r--r-- | arch/sh/include/asm/io.h | 53 | ||||
-rw-r--r-- | arch/sh/mm/ioremap.c | 9 |
6 files changed, 41 insertions, 33 deletions
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c index 511de38d2046..fe7e686c94ac 100644 --- a/arch/sh/boards/board-sh7785lcr.c +++ b/arch/sh/boards/board-sh7785lcr.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/i2c-algo-pca.h> | 21 | #include <linux/i2c-algo-pca.h> |
22 | #include <linux/usb/r8a66597.h> | 22 | #include <linux/usb/r8a66597.h> |
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/io.h> | ||
24 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
25 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
26 | #include <mach/sh7785lcr.h> | 27 | #include <mach/sh7785lcr.h> |
@@ -332,15 +333,14 @@ static void __init sh7785lcr_setup(char **cmdline_p) | |||
332 | pm_power_off = sh7785lcr_power_off; | 333 | pm_power_off = sh7785lcr_power_off; |
333 | 334 | ||
334 | /* sm501 DRAM configuration */ | 335 | /* sm501 DRAM configuration */ |
335 | sm501_reg = ioremap_fixed(SM107_REG_ADDR, SM501_DRAM_CONTROL, | 336 | sm501_reg = ioremap_nocache(SM107_REG_ADDR, SM501_DRAM_CONTROL); |
336 | PAGE_KERNEL); | ||
337 | if (!sm501_reg) { | 337 | if (!sm501_reg) { |
338 | printk(KERN_ERR "%s: ioremap error.\n", __func__); | 338 | printk(KERN_ERR "%s: ioremap error.\n", __func__); |
339 | return; | 339 | return; |
340 | } | 340 | } |
341 | 341 | ||
342 | writel(0x000307c2, sm501_reg + SM501_DRAM_CONTROL); | 342 | writel(0x000307c2, sm501_reg + SM501_DRAM_CONTROL); |
343 | iounmap_fixed(sm501_reg); | 343 | iounmap(sm501_reg); |
344 | } | 344 | } |
345 | 345 | ||
346 | /* Return the board specific boot mode pin configuration */ | 346 | /* Return the board specific boot mode pin configuration */ |
diff --git a/arch/sh/boards/mach-landisk/setup.c b/arch/sh/boards/mach-landisk/setup.c index db22ea2e6d49..59816355d199 100644 --- a/arch/sh/boards/mach-landisk/setup.c +++ b/arch/sh/boards/mach-landisk/setup.c | |||
@@ -63,7 +63,7 @@ static int __init landisk_devices_setup(void) | |||
63 | /* open I/O area window */ | 63 | /* open I/O area window */ |
64 | paddrbase = virt_to_phys((void *)PA_AREA5_IO); | 64 | paddrbase = virt_to_phys((void *)PA_AREA5_IO); |
65 | prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); | 65 | prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); |
66 | cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot); | 66 | cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot); |
67 | if (!cf_ide_base) { | 67 | if (!cf_ide_base) { |
68 | printk("allocate_cf_area : can't open CF I/O window!\n"); | 68 | printk("allocate_cf_area : can't open CF I/O window!\n"); |
69 | return -ENOMEM; | 69 | return -ENOMEM; |
diff --git a/arch/sh/boards/mach-lboxre2/setup.c b/arch/sh/boards/mach-lboxre2/setup.c index 2b0b5818e1e4..408dd5df7d45 100644 --- a/arch/sh/boards/mach-lboxre2/setup.c +++ b/arch/sh/boards/mach-lboxre2/setup.c | |||
@@ -57,7 +57,7 @@ static int __init lboxre2_devices_setup(void) | |||
57 | paddrbase = virt_to_phys((void*)PA_AREA5_IO); | 57 | paddrbase = virt_to_phys((void*)PA_AREA5_IO); |
58 | psize = PAGE_SIZE; | 58 | psize = PAGE_SIZE; |
59 | prot = PAGE_KERNEL_PCC( 1 , _PAGE_PCC_IO16); | 59 | prot = PAGE_KERNEL_PCC( 1 , _PAGE_PCC_IO16); |
60 | cf0_io_base = (u32)p3_ioremap(paddrbase, psize, prot.pgprot); | 60 | cf0_io_base = (u32)p3_ioremap(paddrbase, psize, prot); |
61 | if (!cf0_io_base) { | 61 | if (!cf0_io_base) { |
62 | printk(KERN_ERR "%s : can't open CF I/O window!\n" , __func__ ); | 62 | printk(KERN_ERR "%s : can't open CF I/O window!\n" , __func__ ); |
63 | return -ENOMEM; | 63 | return -ENOMEM; |
diff --git a/arch/sh/boards/mach-sh03/setup.c b/arch/sh/boards/mach-sh03/setup.c index 74cfb4b8b03d..f14ba0fa950b 100644 --- a/arch/sh/boards/mach-sh03/setup.c +++ b/arch/sh/boards/mach-sh03/setup.c | |||
@@ -82,7 +82,7 @@ static int __init sh03_devices_setup(void) | |||
82 | /* open I/O area window */ | 82 | /* open I/O area window */ |
83 | paddrbase = virt_to_phys((void *)PA_AREA5_IO); | 83 | paddrbase = virt_to_phys((void *)PA_AREA5_IO); |
84 | prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); | 84 | prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); |
85 | cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot); | 85 | cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot); |
86 | if (!cf_ide_base) { | 86 | if (!cf_ide_base) { |
87 | printk("allocate_cf_area : can't open CF I/O window!\n"); | 87 | printk("allocate_cf_area : can't open CF I/O window!\n"); |
88 | return -ENOMEM; | 88 | return -ENOMEM; |
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 6a0dd8c1e0a9..13696dfccc16 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h | |||
@@ -235,7 +235,7 @@ unsigned long long poke_real_address_q(unsigned long long addr, | |||
235 | */ | 235 | */ |
236 | #ifdef CONFIG_MMU | 236 | #ifdef CONFIG_MMU |
237 | void __iomem *__ioremap_caller(unsigned long offset, unsigned long size, | 237 | void __iomem *__ioremap_caller(unsigned long offset, unsigned long size, |
238 | unsigned long flags, void *caller); | 238 | pgprot_t prot, void *caller); |
239 | void __iounmap(void __iomem *addr); | 239 | void __iounmap(void __iomem *addr); |
240 | 240 | ||
241 | #ifdef CONFIG_IOREMAP_FIXED | 241 | #ifdef CONFIG_IOREMAP_FIXED |
@@ -254,13 +254,13 @@ static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; } | |||
254 | #endif | 254 | #endif |
255 | 255 | ||
256 | static inline void __iomem * | 256 | static inline void __iomem * |
257 | __ioremap(unsigned long offset, unsigned long size, unsigned long flags) | 257 | __ioremap(unsigned long offset, unsigned long size, pgprot_t prot) |
258 | { | 258 | { |
259 | return __ioremap_caller(offset, size, flags, __builtin_return_address(0)); | 259 | return __ioremap_caller(offset, size, prot, __builtin_return_address(0)); |
260 | } | 260 | } |
261 | 261 | ||
262 | static inline void __iomem * | 262 | static inline void __iomem * |
263 | __ioremap_29bit(unsigned long offset, unsigned long size, unsigned long flags) | 263 | __ioremap_29bit(unsigned long offset, unsigned long size, pgprot_t prot) |
264 | { | 264 | { |
265 | #ifdef CONFIG_29BIT | 265 | #ifdef CONFIG_29BIT |
266 | unsigned long last_addr = offset + size - 1; | 266 | unsigned long last_addr = offset + size - 1; |
@@ -272,7 +272,7 @@ __ioremap_29bit(unsigned long offset, unsigned long size, unsigned long flags) | |||
272 | * mapping must be done by the PMB or by using page tables. | 272 | * mapping must be done by the PMB or by using page tables. |
273 | */ | 273 | */ |
274 | if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) { | 274 | if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) { |
275 | if (unlikely(flags & _PAGE_CACHABLE)) | 275 | if (unlikely(pgprot_val(prot) & _PAGE_CACHABLE)) |
276 | return (void __iomem *)P1SEGADDR(offset); | 276 | return (void __iomem *)P1SEGADDR(offset); |
277 | 277 | ||
278 | return (void __iomem *)P2SEGADDR(offset); | 278 | return (void __iomem *)P2SEGADDR(offset); |
@@ -287,7 +287,7 @@ __ioremap_29bit(unsigned long offset, unsigned long size, unsigned long flags) | |||
287 | } | 287 | } |
288 | 288 | ||
289 | static inline void __iomem * | 289 | static inline void __iomem * |
290 | __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) | 290 | __ioremap_mode(unsigned long offset, unsigned long size, pgprot_t prot) |
291 | { | 291 | { |
292 | void __iomem *ret; | 292 | void __iomem *ret; |
293 | 293 | ||
@@ -295,30 +295,39 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) | |||
295 | if (ret) | 295 | if (ret) |
296 | return ret; | 296 | return ret; |
297 | 297 | ||
298 | ret = __ioremap_29bit(offset, size, flags); | 298 | ret = __ioremap_29bit(offset, size, prot); |
299 | if (ret) | 299 | if (ret) |
300 | return ret; | 300 | return ret; |
301 | 301 | ||
302 | return __ioremap(offset, size, flags); | 302 | return __ioremap(offset, size, prot); |
303 | } | 303 | } |
304 | #else | 304 | #else |
305 | #define __ioremap(offset, size, flags) ((void __iomem *)(offset)) | 305 | #define __ioremap(offset, size, prot) ((void __iomem *)(offset)) |
306 | #define __ioremap_mode(offset, size, flags) ((void __iomem *)(offset)) | 306 | #define __ioremap_mode(offset, size, prot) ((void __iomem *)(offset)) |
307 | #define __iounmap(addr) do { } while (0) | 307 | #define __iounmap(addr) do { } while (0) |
308 | #endif /* CONFIG_MMU */ | 308 | #endif /* CONFIG_MMU */ |
309 | 309 | ||
310 | #define ioremap(offset, size) \ | 310 | static inline void __iomem * |
311 | __ioremap_mode((offset), (size), 0) | 311 | ioremap(unsigned long offset, unsigned long size) |
312 | #define ioremap_nocache(offset, size) \ | 312 | { |
313 | __ioremap_mode((offset), (size), 0) | 313 | return __ioremap_mode(offset, size, PAGE_KERNEL_NOCACHE); |
314 | #define ioremap_cache(offset, size) \ | 314 | } |
315 | __ioremap_mode((offset), (size), _PAGE_CACHABLE) | 315 | |
316 | #define p3_ioremap(offset, size, flags) \ | 316 | static inline void __iomem * |
317 | __ioremap((offset), (size), (flags)) | 317 | ioremap_cache(unsigned long offset, unsigned long size) |
318 | #define ioremap_prot(offset, size, flags) \ | 318 | { |
319 | __ioremap_mode((offset), (size), (flags)) | 319 | return __ioremap_mode(offset, size, PAGE_KERNEL); |
320 | #define iounmap(addr) \ | 320 | } |
321 | __iounmap((addr)) | 321 | |
322 | static inline void __iomem * | ||
323 | ioremap_prot(resource_size_t offset, unsigned long size, unsigned long flags) | ||
324 | { | ||
325 | return __ioremap_mode(offset, size, __pgprot(flags)); | ||
326 | } | ||
327 | |||
328 | #define ioremap_nocache ioremap | ||
329 | #define p3_ioremap __ioremap | ||
330 | #define iounmap __iounmap | ||
322 | 331 | ||
323 | #define maybebadio(port) \ | 332 | #define maybebadio(port) \ |
324 | printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \ | 333 | printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \ |
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index a130b2278e92..85b420d00622 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c | |||
@@ -35,11 +35,10 @@ | |||
35 | */ | 35 | */ |
36 | void __iomem * __init_refok | 36 | void __iomem * __init_refok |
37 | __ioremap_caller(unsigned long phys_addr, unsigned long size, | 37 | __ioremap_caller(unsigned long phys_addr, unsigned long size, |
38 | unsigned long flags, void *caller) | 38 | pgprot_t pgprot, void *caller) |
39 | { | 39 | { |
40 | struct vm_struct *area; | 40 | struct vm_struct *area; |
41 | unsigned long offset, last_addr, addr, orig_addr; | 41 | unsigned long offset, last_addr, addr, orig_addr; |
42 | pgprot_t pgprot; | ||
43 | 42 | ||
44 | /* Don't allow wraparound or zero size */ | 43 | /* Don't allow wraparound or zero size */ |
45 | last_addr = phys_addr + size - 1; | 44 | last_addr = phys_addr + size - 1; |
@@ -69,7 +68,7 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size, | |||
69 | * If we can't yet use the regular approach, go the fixmap route. | 68 | * If we can't yet use the regular approach, go the fixmap route. |
70 | */ | 69 | */ |
71 | if (!mem_init_done) | 70 | if (!mem_init_done) |
72 | return ioremap_fixed(phys_addr, size, __pgprot(flags)); | 71 | return ioremap_fixed(phys_addr, size, pgprot); |
73 | 72 | ||
74 | /* | 73 | /* |
75 | * Ok, go for it.. | 74 | * Ok, go for it.. |
@@ -91,8 +90,9 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size, | |||
91 | * PMB entries are all pre-faulted. | 90 | * PMB entries are all pre-faulted. |
92 | */ | 91 | */ |
93 | if (unlikely(phys_addr >= P1SEG)) { | 92 | if (unlikely(phys_addr >= P1SEG)) { |
94 | unsigned long mapped = pmb_remap(addr, phys_addr, size, flags); | 93 | unsigned long mapped; |
95 | 94 | ||
95 | mapped = pmb_remap(addr, phys_addr, size, pgprot_val(pgprot)); | ||
96 | if (likely(mapped)) { | 96 | if (likely(mapped)) { |
97 | addr += mapped; | 97 | addr += mapped; |
98 | phys_addr += mapped; | 98 | phys_addr += mapped; |
@@ -101,7 +101,6 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size, | |||
101 | } | 101 | } |
102 | #endif | 102 | #endif |
103 | 103 | ||
104 | pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); | ||
105 | if (likely(size)) | 104 | if (likely(size)) |
106 | if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { | 105 | if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { |
107 | vunmap((void *)orig_addr); | 106 | vunmap((void *)orig_addr); |