diff options
| author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2007-04-21 05:47:29 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-04-21 15:36:00 -0400 |
| commit | b29e9f5e64fb90d2e4be1c7ef8c925b56669c74a (patch) | |
| tree | 99331c544296b82abe31c55e6bca1ae37dd142c5 | |
| parent | 24e6c6996fb6e0e716c1dda1def1bb023a0fe43b (diff) | |
[ARM] mm 5: Use mem_types table in ioremap
We really want to be using the memory type table in ioremap, so we
only have to do the CPU type fixups in one place.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
| -rw-r--r-- | arch/arm/mm/ioremap.c | 65 | ||||
| -rw-r--r-- | arch/arm/mm/mm.h | 9 | ||||
| -rw-r--r-- | arch/arm/mm/mmu.c | 14 |
3 files changed, 42 insertions, 46 deletions
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 800855b2dc83..b26b36109d54 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c | |||
| @@ -32,6 +32,9 @@ | |||
| 32 | #include <asm/tlbflush.h> | 32 | #include <asm/tlbflush.h> |
| 33 | #include <asm/sizes.h> | 33 | #include <asm/sizes.h> |
| 34 | 34 | ||
| 35 | #include <asm/mach/map.h> | ||
| 36 | #include "mm.h" | ||
| 37 | |||
| 35 | /* | 38 | /* |
| 36 | * Used by ioremap() and iounmap() code to mark (super)section-mapped | 39 | * Used by ioremap() and iounmap() code to mark (super)section-mapped |
| 37 | * I/O regions in vm_struct->flags field. | 40 | * I/O regions in vm_struct->flags field. |
| @@ -39,8 +42,9 @@ | |||
| 39 | #define VM_ARM_SECTION_MAPPING 0x80000000 | 42 | #define VM_ARM_SECTION_MAPPING 0x80000000 |
| 40 | 43 | ||
| 41 | static int remap_area_pte(pmd_t *pmd, unsigned long addr, unsigned long end, | 44 | static int remap_area_pte(pmd_t *pmd, unsigned long addr, unsigned long end, |
| 42 | unsigned long phys_addr, pgprot_t prot) | 45 | unsigned long phys_addr, const struct mem_type *type) |
| 43 | { | 46 | { |
| 47 | pgprot_t prot = __pgprot(type->prot_pte); | ||
| 44 | pte_t *pte; | 48 | pte_t *pte; |
| 45 | 49 | ||
| 46 | pte = pte_alloc_kernel(pmd, addr); | 50 | pte = pte_alloc_kernel(pmd, addr); |
| @@ -63,7 +67,7 @@ static int remap_area_pte(pmd_t *pmd, unsigned long addr, unsigned long end, | |||
| 63 | 67 | ||
| 64 | static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr, | 68 | static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr, |
| 65 | unsigned long end, unsigned long phys_addr, | 69 | unsigned long end, unsigned long phys_addr, |
| 66 | pgprot_t prot) | 70 | const struct mem_type *type) |
| 67 | { | 71 | { |
| 68 | unsigned long next; | 72 | unsigned long next; |
| 69 | pmd_t *pmd; | 73 | pmd_t *pmd; |
| @@ -75,7 +79,7 @@ static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr, | |||
| 75 | 79 | ||
| 76 | do { | 80 | do { |
| 77 | next = pmd_addr_end(addr, end); | 81 | next = pmd_addr_end(addr, end); |
| 78 | ret = remap_area_pte(pmd, addr, next, phys_addr, prot); | 82 | ret = remap_area_pte(pmd, addr, next, phys_addr, type); |
| 79 | if (ret) | 83 | if (ret) |
| 80 | return ret; | 84 | return ret; |
| 81 | phys_addr += next - addr; | 85 | phys_addr += next - addr; |
| @@ -84,13 +88,11 @@ static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr, | |||
| 84 | } | 88 | } |
| 85 | 89 | ||
| 86 | static int remap_area_pages(unsigned long start, unsigned long pfn, | 90 | static int remap_area_pages(unsigned long start, unsigned long pfn, |
| 87 | unsigned long size, unsigned long flags) | 91 | size_t size, const struct mem_type *type) |
| 88 | { | 92 | { |
| 89 | unsigned long addr = start; | 93 | unsigned long addr = start; |
| 90 | unsigned long next, end = start + size; | 94 | unsigned long next, end = start + size; |
| 91 | unsigned long phys_addr = __pfn_to_phys(pfn); | 95 | unsigned long phys_addr = __pfn_to_phys(pfn); |
| 92 | pgprot_t prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | | ||
| 93 | L_PTE_DIRTY | L_PTE_WRITE | flags); | ||
| 94 | pgd_t *pgd; | 96 | pgd_t *pgd; |
| 95 | int err = 0; | 97 | int err = 0; |
| 96 | 98 | ||
| @@ -98,7 +100,7 @@ static int remap_area_pages(unsigned long start, unsigned long pfn, | |||
| 98 | pgd = pgd_offset_k(addr); | 100 | pgd = pgd_offset_k(addr); |
| 99 | do { | 101 | do { |
| 100 | next = pgd_addr_end(addr, end); | 102 | next = pgd_addr_end(addr, end); |
| 101 | err = remap_area_pmd(pgd, addr, next, phys_addr, prot); | 103 | err = remap_area_pmd(pgd, addr, next, phys_addr, type); |
| 102 | if (err) | 104 | if (err) |
| 103 | break; | 105 | break; |
| 104 | phys_addr += next - addr; | 106 | phys_addr += next - addr; |
| @@ -178,9 +180,9 @@ static void unmap_area_sections(unsigned long virt, unsigned long size) | |||
| 178 | 180 | ||
| 179 | static int | 181 | static int |
| 180 | remap_area_sections(unsigned long virt, unsigned long pfn, | 182 | remap_area_sections(unsigned long virt, unsigned long pfn, |
| 181 | unsigned long size, unsigned long flags) | 183 | size_t size, const struct mem_type *type) |
| 182 | { | 184 | { |
| 183 | unsigned long prot, addr = virt, end = virt + size; | 185 | unsigned long addr = virt, end = virt + size; |
| 184 | pgd_t *pgd; | 186 | pgd_t *pgd; |
| 185 | 187 | ||
| 186 | /* | 188 | /* |
| @@ -189,23 +191,13 @@ remap_area_sections(unsigned long virt, unsigned long pfn, | |||
| 189 | */ | 191 | */ |
| 190 | unmap_area_sections(virt, size); | 192 | unmap_area_sections(virt, size); |
| 191 | 193 | ||
| 192 | prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO) | | ||
| 193 | (flags & (L_PTE_CACHEABLE | L_PTE_BUFFERABLE)); | ||
| 194 | |||
| 195 | /* | ||
| 196 | * ARMv6 and above need XN set to prevent speculative prefetches | ||
| 197 | * hitting IO. | ||
| 198 | */ | ||
| 199 | if (cpu_architecture() >= CPU_ARCH_ARMv6) | ||
| 200 | prot |= PMD_SECT_XN; | ||
| 201 | |||
| 202 | pgd = pgd_offset_k(addr); | 194 | pgd = pgd_offset_k(addr); |
| 203 | do { | 195 | do { |
| 204 | pmd_t *pmd = pmd_offset(pgd, addr); | 196 | pmd_t *pmd = pmd_offset(pgd, addr); |
| 205 | 197 | ||
| 206 | pmd[0] = __pmd(__pfn_to_phys(pfn) | prot); | 198 | pmd[0] = __pmd(__pfn_to_phys(pfn) | type->prot_sect); |
| 207 | pfn += SZ_1M >> PAGE_SHIFT; | 199 | pfn += SZ_1M >> PAGE_SHIFT; |
| 208 | pmd[1] = __pmd(__pfn_to_phys(pfn) | prot); | 200 | pmd[1] = __pmd(__pfn_to_phys(pfn) | type->prot_sect); |
| 209 | pfn += SZ_1M >> PAGE_SHIFT; | 201 | pfn += SZ_1M >> PAGE_SHIFT; |
| 210 | flush_pmd_entry(pmd); | 202 | flush_pmd_entry(pmd); |
| 211 | 203 | ||
| @@ -218,9 +210,9 @@ remap_area_sections(unsigned long virt, unsigned long pfn, | |||
| 218 | 210 | ||
| 219 | static int | 211 | static int |
| 220 | remap_area_supersections(unsigned long virt, unsigned long pfn, | 212 | remap_area_supersections(unsigned long virt, unsigned long pfn, |
| 221 | unsigned long size, unsigned long flags) | 213 | size_t size, const struct mem_type *type) |
| 222 | { | 214 | { |
| 223 | unsigned long prot, addr = virt, end = virt + size; | 215 | unsigned long addr = virt, end = virt + size; |
| 224 | pgd_t *pgd; | 216 | pgd_t *pgd; |
| 225 | 217 | ||
| 226 | /* | 218 | /* |
| @@ -229,22 +221,12 @@ remap_area_supersections(unsigned long virt, unsigned long pfn, | |||
| 229 | */ | 221 | */ |
| 230 | unmap_area_sections(virt, size); | 222 | unmap_area_sections(virt, size); |
| 231 | 223 | ||
| 232 | prot = PMD_TYPE_SECT | PMD_SECT_SUPER | PMD_SECT_AP_WRITE | | ||
| 233 | PMD_DOMAIN(DOMAIN_IO) | | ||
| 234 | (flags & (L_PTE_CACHEABLE | L_PTE_BUFFERABLE)); | ||
| 235 | |||
| 236 | /* | ||
| 237 | * ARMv6 and above need XN set to prevent speculative prefetches | ||
| 238 | * hitting IO. | ||
| 239 | */ | ||
| 240 | if (cpu_architecture() >= CPU_ARCH_ARMv6) | ||
| 241 | prot |= PMD_SECT_XN; | ||
| 242 | |||
| 243 | pgd = pgd_offset_k(virt); | 224 | pgd = pgd_offset_k(virt); |
| 244 | do { | 225 | do { |
| 245 | unsigned long super_pmd_val, i; | 226 | unsigned long super_pmd_val, i; |
| 246 | 227 | ||
| 247 | super_pmd_val = __pfn_to_phys(pfn) | prot; | 228 | super_pmd_val = __pfn_to_phys(pfn) | type->prot_sect | |
| 229 | PMD_SECT_SUPER; | ||
| 248 | super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20; | 230 | super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20; |
| 249 | 231 | ||
| 250 | for (i = 0; i < 8; i++) { | 232 | for (i = 0; i < 8; i++) { |
| @@ -282,6 +264,8 @@ void __iomem * | |||
| 282 | __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, | 264 | __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, |
| 283 | unsigned long flags) | 265 | unsigned long flags) |
| 284 | { | 266 | { |
| 267 | const struct mem_type *type; | ||
| 268 | struct mem_type t; | ||
| 285 | int err; | 269 | int err; |
| 286 | unsigned long addr; | 270 | unsigned long addr; |
| 287 | struct vm_struct * area; | 271 | struct vm_struct * area; |
| @@ -292,6 +276,11 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, | |||
| 292 | if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK)) | 276 | if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK)) |
| 293 | return NULL; | 277 | return NULL; |
| 294 | 278 | ||
| 279 | t = *get_mem_type(MT_DEVICE); | ||
| 280 | t.prot_sect |= flags; | ||
| 281 | t.prot_pte |= flags; | ||
| 282 | type = &t; | ||
| 283 | |||
| 295 | size = PAGE_ALIGN(size); | 284 | size = PAGE_ALIGN(size); |
| 296 | 285 | ||
| 297 | area = get_vm_area(size, VM_IOREMAP); | 286 | area = get_vm_area(size, VM_IOREMAP); |
| @@ -305,13 +294,13 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, | |||
| 305 | cpu_is_xsc3()) && pfn >= 0x100000 && | 294 | cpu_is_xsc3()) && pfn >= 0x100000 && |
| 306 | !((__pfn_to_phys(pfn) | size | addr) & ~SUPERSECTION_MASK)) { | 295 | !((__pfn_to_phys(pfn) | size | addr) & ~SUPERSECTION_MASK)) { |
| 307 | area->flags |= VM_ARM_SECTION_MAPPING; | 296 | area->flags |= VM_ARM_SECTION_MAPPING; |
| 308 | err = remap_area_supersections(addr, pfn, size, flags); | 297 | err = remap_area_supersections(addr, pfn, size, type); |
| 309 | } else if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) { | 298 | } else if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) { |
| 310 | area->flags |= VM_ARM_SECTION_MAPPING; | 299 | area->flags |= VM_ARM_SECTION_MAPPING; |
| 311 | err = remap_area_sections(addr, pfn, size, flags); | 300 | err = remap_area_sections(addr, pfn, size, type); |
| 312 | } else | 301 | } else |
| 313 | #endif | 302 | #endif |
| 314 | err = remap_area_pages(addr, pfn, size, flags); | 303 | err = remap_area_pages(addr, pfn, size, type); |
| 315 | 304 | ||
| 316 | if (err) { | 305 | if (err) { |
| 317 | vunmap((void *)addr); | 306 | vunmap((void *)addr); |
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index a44e30970635..66f8612c5e5b 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
| @@ -16,6 +16,15 @@ static inline pmd_t *pmd_off_k(unsigned long virt) | |||
| 16 | return pmd_off(pgd_offset_k(virt), virt); | 16 | return pmd_off(pgd_offset_k(virt), virt); |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | struct mem_type { | ||
| 20 | unsigned int prot_pte; | ||
| 21 | unsigned int prot_l1; | ||
| 22 | unsigned int prot_sect; | ||
| 23 | unsigned int domain; | ||
| 24 | }; | ||
| 25 | |||
| 26 | const struct mem_type *get_mem_type(unsigned int type); | ||
| 27 | |||
| 19 | #endif | 28 | #endif |
| 20 | 29 | ||
| 21 | struct map_desc; | 30 | struct map_desc; |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 5821e67cf8c2..6cb80b4973d2 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
| @@ -176,14 +176,7 @@ void adjust_cr(unsigned long mask, unsigned long set) | |||
| 176 | } | 176 | } |
| 177 | #endif | 177 | #endif |
| 178 | 178 | ||
| 179 | struct mem_type { | 179 | static struct mem_type mem_types[] = { |
| 180 | unsigned int prot_pte; | ||
| 181 | unsigned int prot_l1; | ||
| 182 | unsigned int prot_sect; | ||
| 183 | unsigned int domain; | ||
| 184 | }; | ||
| 185 | |||
| 186 | static struct mem_type mem_types[] __initdata = { | ||
| 187 | [MT_DEVICE] = { | 180 | [MT_DEVICE] = { |
| 188 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | 181 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | |
| 189 | L_PTE_WRITE, | 182 | L_PTE_WRITE, |
| @@ -237,6 +230,11 @@ static struct mem_type mem_types[] __initdata = { | |||
| 237 | } | 230 | } |
| 238 | }; | 231 | }; |
| 239 | 232 | ||
| 233 | const struct mem_type *get_mem_type(unsigned int type) | ||
| 234 | { | ||
| 235 | return type < ARRAY_SIZE(mem_types) ? &mem_types[type] : NULL; | ||
| 236 | } | ||
| 237 | |||
| 240 | /* | 238 | /* |
| 241 | * Adjust the PMD section entries according to the CPU in use. | 239 | * Adjust the PMD section entries according to the CPU in use. |
| 242 | */ | 240 | */ |
