mmu.c (068a17a5805dfbca4bbf03e664ca6b19709cc7a8) mmu.c (132233a759580f5ce9b1bfaac9073e47d03c460d)
1/*
2 * Based on arch/arm/mm/mmu.c
3 *
4 * Copyright (C) 1995-2005 Russell King
5 * Copyright (C) 2012 ARM Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as

--- 102 unchanged lines hidden (view full) ---

111static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
112 unsigned long end, unsigned long pfn,
113 pgprot_t prot,
114 phys_addr_t (*pgtable_alloc)(void))
115{
116 pte_t *pte;
117
118 if (pmd_none(*pmd) || pmd_sect(*pmd)) {
1/*
2 * Based on arch/arm/mm/mmu.c
3 *
4 * Copyright (C) 1995-2005 Russell King
5 * Copyright (C) 2012 ARM Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as

--- 102 unchanged lines hidden (view full) ---

111static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
112 unsigned long end, unsigned long pfn,
113 pgprot_t prot,
114 phys_addr_t (*pgtable_alloc)(void))
115{
116 pte_t *pte;
117
118 if (pmd_none(*pmd) || pmd_sect(*pmd)) {
119 phys_addr_t pte_phys = pgtable_alloc();
119 phys_addr_t pte_phys;
120 BUG_ON(!pgtable_alloc);
121 pte_phys = pgtable_alloc();
120 pte = pte_set_fixmap(pte_phys);
121 if (pmd_sect(*pmd))
122 split_pmd(pmd, pte);
123 __pmd_populate(pmd, pte_phys, PMD_TYPE_TABLE);
124 flush_tlb_all();
125 pte_clear_fixmap();
126 }
127 BUG_ON(pmd_bad(*pmd));

--- 25 unchanged lines hidden (view full) ---

153{
154 pmd_t *pmd;
155 unsigned long next;
156
157 /*
158 * Check for initial section mappings in the pgd/pud and remove them.
159 */
160 if (pud_none(*pud) || pud_sect(*pud)) {
122 pte = pte_set_fixmap(pte_phys);
123 if (pmd_sect(*pmd))
124 split_pmd(pmd, pte);
125 __pmd_populate(pmd, pte_phys, PMD_TYPE_TABLE);
126 flush_tlb_all();
127 pte_clear_fixmap();
128 }
129 BUG_ON(pmd_bad(*pmd));

--- 25 unchanged lines hidden (view full) ---

155{
156 pmd_t *pmd;
157 unsigned long next;
158
159 /*
160 * Check for initial section mappings in the pgd/pud and remove them.
161 */
162 if (pud_none(*pud) || pud_sect(*pud)) {
161 phys_addr_t pmd_phys = pgtable_alloc();
163 phys_addr_t pmd_phys;
164 BUG_ON(!pgtable_alloc);
165 pmd_phys = pgtable_alloc();
162 pmd = pmd_set_fixmap(pmd_phys);
163 if (pud_sect(*pud)) {
164 /*
165 * need to have the 1G of mappings continue to be
166 * present
167 */
168 split_pud(pud, pmd);
169 }

--- 48 unchanged lines hidden (view full) ---

218static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
219 phys_addr_t phys, pgprot_t prot,
220 phys_addr_t (*pgtable_alloc)(void))
221{
222 pud_t *pud;
223 unsigned long next;
224
225 if (pgd_none(*pgd)) {
166 pmd = pmd_set_fixmap(pmd_phys);
167 if (pud_sect(*pud)) {
168 /*
169 * need to have the 1G of mappings continue to be
170 * present
171 */
172 split_pud(pud, pmd);
173 }

--- 48 unchanged lines hidden (view full) ---

222static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
223 phys_addr_t phys, pgprot_t prot,
224 phys_addr_t (*pgtable_alloc)(void))
225{
226 pud_t *pud;
227 unsigned long next;
228
229 if (pgd_none(*pgd)) {
226 phys_addr_t pud_phys = pgtable_alloc();
230 phys_addr_t pud_phys;
231 BUG_ON(!pgtable_alloc);
232 pud_phys = pgtable_alloc();
227 __pgd_populate(pgd, pud_phys, PUD_TYPE_TABLE);
228 }
229 BUG_ON(pgd_bad(*pgd));
230
231 pud = pud_set_fixmap_offset(pgd, addr);
232 do {
233 next = pud_addr_end(addr, end);
234

--- 72 unchanged lines hidden (view full) ---

307static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
308 unsigned long virt, phys_addr_t size,
309 pgprot_t prot,
310 phys_addr_t (*alloc)(void))
311{
312 init_pgd(pgd_offset_raw(pgdir, virt), phys, virt, size, prot, alloc);
313}
314
233 __pgd_populate(pgd, pud_phys, PUD_TYPE_TABLE);
234 }
235 BUG_ON(pgd_bad(*pgd));
236
237 pud = pud_set_fixmap_offset(pgd, addr);
238 do {
239 next = pud_addr_end(addr, end);
240

--- 72 unchanged lines hidden (view full) ---

313static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
314 unsigned long virt, phys_addr_t size,
315 pgprot_t prot,
316 phys_addr_t (*alloc)(void))
317{
318 init_pgd(pgd_offset_raw(pgdir, virt), phys, virt, size, prot, alloc);
319}
320
315static void __init create_mapping(phys_addr_t phys, unsigned long virt,
321/*
322 * This function can only be used to modify existing table entries,
323 * without allocating new levels of table. Note that this permits the
324 * creation of new section or page entries.
325 */
326static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt,
316 phys_addr_t size, pgprot_t prot)
317{
318 if (virt < VMALLOC_START) {
319 pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n",
320 &phys, virt);
321 return;
322 }
323 __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot,
327 phys_addr_t size, pgprot_t prot)
328{
329 if (virt < VMALLOC_START) {
330 pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n",
331 &phys, virt);
332 return;
333 }
334 __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot,
324 early_pgtable_alloc);
335 NULL);
325}
326
327void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
328 unsigned long virt, phys_addr_t size,
329 pgprot_t prot)
330{
331 __create_pgd_mapping(mm->pgd, phys, virt, size, prot,
332 late_pgtable_alloc);

--- 342 unchanged lines hidden (view full) ---

675 */
676 BUILD_BUG_ON(MIN_FDT_ALIGN < 8);
677 if (!dt_phys || dt_phys % MIN_FDT_ALIGN)
678 return NULL;
679
680 /*
681 * Make sure that the FDT region can be mapped without the need to
682 * allocate additional translation table pages, so that it is safe
336}
337
338void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
339 unsigned long virt, phys_addr_t size,
340 pgprot_t prot)
341{
342 __create_pgd_mapping(mm->pgd, phys, virt, size, prot,
343 late_pgtable_alloc);

--- 342 unchanged lines hidden (view full) ---

686 */
687 BUILD_BUG_ON(MIN_FDT_ALIGN < 8);
688 if (!dt_phys || dt_phys % MIN_FDT_ALIGN)
689 return NULL;
690
691 /*
692 * Make sure that the FDT region can be mapped without the need to
693 * allocate additional translation table pages, so that it is safe
683 * to call create_mapping() this early.
694 * to call create_mapping_noalloc() this early.
684 *
685 * On 64k pages, the FDT will be mapped using PTEs, so we need to
686 * be in the same PMD as the rest of the fixmap.
687 * On 4k pages, we'll use section mappings for the FDT so we only
688 * have to be in the same PUD.
689 */
690 BUILD_BUG_ON(dt_virt_base % SZ_2M);
691
692 BUILD_BUG_ON(__fix_to_virt(FIX_FDT_END) >> SWAPPER_TABLE_SHIFT !=
693 __fix_to_virt(FIX_BTMAP_BEGIN) >> SWAPPER_TABLE_SHIFT);
694
695 offset = dt_phys % SWAPPER_BLOCK_SIZE;
696 dt_virt = (void *)dt_virt_base + offset;
697
698 /* map the first chunk so we can read the size from the header */
695 *
696 * On 64k pages, the FDT will be mapped using PTEs, so we need to
697 * be in the same PMD as the rest of the fixmap.
698 * On 4k pages, we'll use section mappings for the FDT so we only
699 * have to be in the same PUD.
700 */
701 BUILD_BUG_ON(dt_virt_base % SZ_2M);
702
703 BUILD_BUG_ON(__fix_to_virt(FIX_FDT_END) >> SWAPPER_TABLE_SHIFT !=
704 __fix_to_virt(FIX_BTMAP_BEGIN) >> SWAPPER_TABLE_SHIFT);
705
706 offset = dt_phys % SWAPPER_BLOCK_SIZE;
707 dt_virt = (void *)dt_virt_base + offset;
708
709 /* map the first chunk so we can read the size from the header */
699 create_mapping(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
700 SWAPPER_BLOCK_SIZE, prot);
710 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
711 dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
701
702 if (fdt_check_header(dt_virt) != 0)
703 return NULL;
704
705 size = fdt_totalsize(dt_virt);
706 if (size > MAX_FDT_SIZE)
707 return NULL;
708
709 if (offset + size > SWAPPER_BLOCK_SIZE)
712
713 if (fdt_check_header(dt_virt) != 0)
714 return NULL;
715
716 size = fdt_totalsize(dt_virt);
717 if (size > MAX_FDT_SIZE)
718 return NULL;
719
720 if (offset + size > SWAPPER_BLOCK_SIZE)
710 create_mapping(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
721 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
711 round_up(offset + size, SWAPPER_BLOCK_SIZE), prot);
712
713 memblock_reserve(dt_phys, size);
714
715 return dt_virt;
716}
722 round_up(offset + size, SWAPPER_BLOCK_SIZE), prot);
723
724 memblock_reserve(dt_phys, size);
725
726 return dt_virt;
727}