diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-05 16:15:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-05 16:15:32 -0400 |
commit | c3c55a07203947f72afa50a3218460b27307c47d (patch) | |
tree | de3a2f8adbb3bea4bba1df0f709b0d6c1f4e87b7 /arch/arm64/mm | |
parent | 046f153343e33dcad1be7f6249ea6ff1c6fd9b58 (diff) | |
parent | 74bcc2499291d38b6253f9dbd6af33a195222208 (diff) |
Merge branch 'arm64-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into next
Pull ARM64 EFI update from Peter Anvin:
"By agreement with the ARM64 EFI maintainers, we have agreed to make
-tip the upstream for all EFI patches. That is why this patchset
comes from me :)
This patchset enables EFI stub support for ARM64, like we already have
on x86"
* 'arm64-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
arm64: efi: only attempt efi map setup if booting via EFI
efi/arm64: ignore dtb= when UEFI SecureBoot is enabled
doc: arm64: add description of EFI stub support
arm64: efi: add EFI stub
doc: arm: add UEFI support documentation
arm64: add EFI runtime services
efi: Add shared FDT related functions for ARM/ARM64
arm64: Add function to create identity mappings
efi: add helper function to get UEFI params from FDT
doc: efi-stub.txt updates for ARM
lib: add fdt_empty_tree.c
Diffstat (limited to 'arch/arm64/mm')
-rw-r--r-- | arch/arm64/mm/mmu.c | 65 |
1 files changed, 47 insertions, 18 deletions
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 0a472c41a67f..4a829a210bb6 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c | |||
@@ -168,7 +168,8 @@ static void __init *early_alloc(unsigned long sz) | |||
168 | } | 168 | } |
169 | 169 | ||
170 | static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, | 170 | static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, |
171 | unsigned long end, unsigned long pfn) | 171 | unsigned long end, unsigned long pfn, |
172 | pgprot_t prot) | ||
172 | { | 173 | { |
173 | pte_t *pte; | 174 | pte_t *pte; |
174 | 175 | ||
@@ -180,16 +181,28 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, | |||
180 | 181 | ||
181 | pte = pte_offset_kernel(pmd, addr); | 182 | pte = pte_offset_kernel(pmd, addr); |
182 | do { | 183 | do { |
183 | set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); | 184 | set_pte(pte, pfn_pte(pfn, prot)); |
184 | pfn++; | 185 | pfn++; |
185 | } while (pte++, addr += PAGE_SIZE, addr != end); | 186 | } while (pte++, addr += PAGE_SIZE, addr != end); |
186 | } | 187 | } |
187 | 188 | ||
188 | static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, | 189 | static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, |
189 | unsigned long end, phys_addr_t phys) | 190 | unsigned long end, phys_addr_t phys, |
191 | int map_io) | ||
190 | { | 192 | { |
191 | pmd_t *pmd; | 193 | pmd_t *pmd; |
192 | unsigned long next; | 194 | unsigned long next; |
195 | pmdval_t prot_sect; | ||
196 | pgprot_t prot_pte; | ||
197 | |||
198 | if (map_io) { | ||
199 | prot_sect = PMD_TYPE_SECT | PMD_SECT_AF | | ||
200 | PMD_ATTRINDX(MT_DEVICE_nGnRE); | ||
201 | prot_pte = __pgprot(PROT_DEVICE_nGnRE); | ||
202 | } else { | ||
203 | prot_sect = prot_sect_kernel; | ||
204 | prot_pte = PAGE_KERNEL_EXEC; | ||
205 | } | ||
193 | 206 | ||
194 | /* | 207 | /* |
195 | * Check for initial section mappings in the pgd/pud and remove them. | 208 | * Check for initial section mappings in the pgd/pud and remove them. |
@@ -205,7 +218,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, | |||
205 | /* try section mapping first */ | 218 | /* try section mapping first */ |
206 | if (((addr | next | phys) & ~SECTION_MASK) == 0) { | 219 | if (((addr | next | phys) & ~SECTION_MASK) == 0) { |
207 | pmd_t old_pmd =*pmd; | 220 | pmd_t old_pmd =*pmd; |
208 | set_pmd(pmd, __pmd(phys | prot_sect_kernel)); | 221 | set_pmd(pmd, __pmd(phys | prot_sect)); |
209 | /* | 222 | /* |
210 | * Check for previous table entries created during | 223 | * Check for previous table entries created during |
211 | * boot (__create_page_tables) and flush them. | 224 | * boot (__create_page_tables) and flush them. |
@@ -213,21 +226,23 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, | |||
213 | if (!pmd_none(old_pmd)) | 226 | if (!pmd_none(old_pmd)) |
214 | flush_tlb_all(); | 227 | flush_tlb_all(); |
215 | } else { | 228 | } else { |
216 | alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys)); | 229 | alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), |
230 | prot_pte); | ||
217 | } | 231 | } |
218 | phys += next - addr; | 232 | phys += next - addr; |
219 | } while (pmd++, addr = next, addr != end); | 233 | } while (pmd++, addr = next, addr != end); |
220 | } | 234 | } |
221 | 235 | ||
222 | static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, | 236 | static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, |
223 | unsigned long end, unsigned long phys) | 237 | unsigned long end, unsigned long phys, |
238 | int map_io) | ||
224 | { | 239 | { |
225 | pud_t *pud = pud_offset(pgd, addr); | 240 | pud_t *pud = pud_offset(pgd, addr); |
226 | unsigned long next; | 241 | unsigned long next; |
227 | 242 | ||
228 | do { | 243 | do { |
229 | next = pud_addr_end(addr, end); | 244 | next = pud_addr_end(addr, end); |
230 | alloc_init_pmd(pud, addr, next, phys); | 245 | alloc_init_pmd(pud, addr, next, phys, map_io); |
231 | phys += next - addr; | 246 | phys += next - addr; |
232 | } while (pud++, addr = next, addr != end); | 247 | } while (pud++, addr = next, addr != end); |
233 | } | 248 | } |
@@ -236,30 +251,44 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, | |||
236 | * Create the page directory entries and any necessary page tables for the | 251 | * Create the page directory entries and any necessary page tables for the |
237 | * mapping specified by 'md'. | 252 | * mapping specified by 'md'. |
238 | */ | 253 | */ |
239 | static void __init create_mapping(phys_addr_t phys, unsigned long virt, | 254 | static void __init __create_mapping(pgd_t *pgd, phys_addr_t phys, |
240 | phys_addr_t size) | 255 | unsigned long virt, phys_addr_t size, |
256 | int map_io) | ||
241 | { | 257 | { |
242 | unsigned long addr, length, end, next; | 258 | unsigned long addr, length, end, next; |
243 | pgd_t *pgd; | ||
244 | |||
245 | if (virt < VMALLOC_START) { | ||
246 | pr_warning("BUG: not creating mapping for 0x%016llx at 0x%016lx - outside kernel range\n", | ||
247 | phys, virt); | ||
248 | return; | ||
249 | } | ||
250 | 259 | ||
251 | addr = virt & PAGE_MASK; | 260 | addr = virt & PAGE_MASK; |
252 | length = PAGE_ALIGN(size + (virt & ~PAGE_MASK)); | 261 | length = PAGE_ALIGN(size + (virt & ~PAGE_MASK)); |
253 | 262 | ||
254 | pgd = pgd_offset_k(addr); | ||
255 | end = addr + length; | 263 | end = addr + length; |
256 | do { | 264 | do { |
257 | next = pgd_addr_end(addr, end); | 265 | next = pgd_addr_end(addr, end); |
258 | alloc_init_pud(pgd, addr, next, phys); | 266 | alloc_init_pud(pgd, addr, next, phys, map_io); |
259 | phys += next - addr; | 267 | phys += next - addr; |
260 | } while (pgd++, addr = next, addr != end); | 268 | } while (pgd++, addr = next, addr != end); |
261 | } | 269 | } |
262 | 270 | ||
271 | static void __init create_mapping(phys_addr_t phys, unsigned long virt, | ||
272 | phys_addr_t size) | ||
273 | { | ||
274 | if (virt < VMALLOC_START) { | ||
275 | pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n", | ||
276 | &phys, virt); | ||
277 | return; | ||
278 | } | ||
279 | __create_mapping(pgd_offset_k(virt & PAGE_MASK), phys, virt, size, 0); | ||
280 | } | ||
281 | |||
282 | void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io) | ||
283 | { | ||
284 | if ((addr >> PGDIR_SHIFT) >= ARRAY_SIZE(idmap_pg_dir)) { | ||
285 | pr_warn("BUG: not creating id mapping for %pa\n", &addr); | ||
286 | return; | ||
287 | } | ||
288 | __create_mapping(&idmap_pg_dir[pgd_index(addr)], | ||
289 | addr, addr, size, map_io); | ||
290 | } | ||
291 | |||
263 | static void __init map_mem(void) | 292 | static void __init map_mem(void) |
264 | { | 293 | { |
265 | struct memblock_region *reg; | 294 | struct memblock_region *reg; |