Skip to content

Commit 3bbd245

Browse files
Ard BiesheuvelAKASHI Takahiro
authored andcommitted
arm64: mm: add param to force create_pgd_mapping() to use page mappings
Add a bool parameter 'allow_block_mappings' to create_pgd_mapping() and the various helper functions that it descends into, to give the caller control over whether block entries may be used to create the mapping. The UEFI runtime mapping routines will use this to avoid creating block entries that would need to split up into page entries when applying the permissions listed in the Memory Attributes firmware table. This also replaces the block_mappings_allowed() helper function that was added for DEBUG_PAGEALLOC functionality, but the resulting code is functionally equivalent (given that debug_page_alloc does not operate on EFI page table entries anyway) Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Conflicts: arch/arm64/kernel/efi.c The file has been heavily refactored.
1 parent 520bf99 commit 3bbd245

3 files changed

Lines changed: 29 additions & 41 deletions

File tree

arch/arm64/include/asm/mmu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);
3333
extern void init_mem_pgprot(void);
3434
extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
3535
unsigned long virt, phys_addr_t size,
36-
pgprot_t prot);
36+
pgprot_t prot, bool allow_block_mappings);
3737
extern void *fixmap_remap_fdt(phys_addr_t dt_phys);
3838

3939
#endif

arch/arm64/kernel/efi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ static bool __init efi_virtmap_init(void)
264264

265265
create_pgd_mapping(&efi_mm, md->phys_addr, md->virt_addr,
266266
md->num_pages << EFI_PAGE_SHIFT,
267-
__pgprot(pgprot_val(prot) | PTE_NG));
267+
__pgprot(pgprot_val(prot) | PTE_NG), true);
268268
}
269269
return true;
270270
}

arch/arm64/mm/mmu.c

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -156,29 +156,10 @@ static void split_pud(pud_t *old_pud, pmd_t *pmd)
156156
} while (pmd++, i++, i < PTRS_PER_PMD);
157157
}
158158

159-
#ifdef CONFIG_DEBUG_PAGEALLOC
160-
static bool block_mappings_allowed(phys_addr_t (*pgtable_alloc)(void))
161-
{
162-
163-
/*
164-
* If debug_page_alloc is enabled we must map the linear map
165-
* using pages. However, other mappings created by
166-
* create_mapping_noalloc must use sections in some cases. Allow
167-
* sections to be used in those cases, where no pgtable_alloc
168-
* function is provided.
169-
*/
170-
return !pgtable_alloc || !debug_pagealloc_enabled();
171-
}
172-
#else
173-
static bool block_mappings_allowed(phys_addr_t (*pgtable_alloc)(void))
174-
{
175-
return true;
176-
}
177-
#endif
178-
179159
static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
180160
phys_addr_t phys, pgprot_t prot,
181-
phys_addr_t (*pgtable_alloc)(void))
161+
phys_addr_t (*pgtable_alloc)(void),
162+
bool allow_block_mappings)
182163
{
183164
pmd_t *pmd;
184165
unsigned long next;
@@ -209,7 +190,7 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
209190
next = pmd_addr_end(addr, end);
210191
/* try section mapping first */
211192
if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
212-
block_mappings_allowed(pgtable_alloc)) {
193+
(!pgtable_alloc || allow_block_mappings)) {
213194
pmd_t old_pmd =*pmd;
214195
pmd_set_huge(pmd, phys, prot);
215196
/*
@@ -248,7 +229,8 @@ static inline bool use_1G_block(unsigned long addr, unsigned long next,
248229

249230
static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
250231
phys_addr_t phys, pgprot_t prot,
251-
phys_addr_t (*pgtable_alloc)(void))
232+
phys_addr_t (*pgtable_alloc)(void),
233+
bool allow_block_mappings)
252234
{
253235
pud_t *pud;
254236
unsigned long next;
@@ -269,7 +251,7 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
269251
* For 4K granule only, attempt to put down a 1GB block
270252
*/
271253
if (use_1G_block(addr, next, phys) &&
272-
block_mappings_allowed(pgtable_alloc)) {
254+
(!pgtable_alloc || allow_block_mappings)) {
273255
pud_t old_pud = *pud;
274256
pud_set_huge(pud, phys, prot);
275257

@@ -290,7 +272,7 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
290272
}
291273
} else {
292274
alloc_init_pmd(pud, addr, next, phys, prot,
293-
pgtable_alloc);
275+
pgtable_alloc, allow_block_mappings);
294276
}
295277
phys += next - addr;
296278
} while (pud++, addr = next, addr != end);
@@ -304,7 +286,8 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
304286
*/
305287
static void init_pgd(pgd_t *pgd, phys_addr_t phys, unsigned long virt,
306288
phys_addr_t size, pgprot_t prot,
307-
phys_addr_t (*pgtable_alloc)(void))
289+
phys_addr_t (*pgtable_alloc)(void),
290+
bool allow_block_mappings)
308291
{
309292
unsigned long addr, length, end, next;
310293

@@ -322,7 +305,8 @@ static void init_pgd(pgd_t *pgd, phys_addr_t phys, unsigned long virt,
322305
end = addr + length;
323306
do {
324307
next = pgd_addr_end(addr, end);
325-
alloc_init_pud(pgd, addr, next, phys, prot, pgtable_alloc);
308+
alloc_init_pud(pgd, addr, next, phys, prot, pgtable_alloc,
309+
(!pgtable_alloc || allow_block_mappings));
326310
phys += next - addr;
327311
} while (pgd++, addr = next, addr != end);
328312
}
@@ -340,9 +324,11 @@ static phys_addr_t late_pgtable_alloc(void)
340324
static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
341325
unsigned long virt, phys_addr_t size,
342326
pgprot_t prot,
343-
phys_addr_t (*alloc)(void))
327+
phys_addr_t (*alloc)(void),
328+
bool allow_block_mappings)
344329
{
345-
init_pgd(pgd_offset_raw(pgdir, virt), phys, virt, size, prot, alloc);
330+
init_pgd(pgd_offset_raw(pgdir, virt), phys, virt, size, prot, alloc,
331+
allow_block_mappings);
346332
}
347333

348334
/*
@@ -358,16 +344,15 @@ static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt,
358344
&phys, virt);
359345
return;
360346
}
361-
__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot,
362-
NULL);
347+
__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, true);
363348
}
364349

365350
void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
366351
unsigned long virt, phys_addr_t size,
367-
pgprot_t prot)
352+
pgprot_t prot, bool allow_block_mappings)
368353
{
369354
__create_pgd_mapping(mm->pgd, phys, virt, size, prot,
370-
late_pgtable_alloc);
355+
late_pgtable_alloc, allow_block_mappings);
371356
}
372357

373358
static void create_mapping_late(phys_addr_t phys, unsigned long virt,
@@ -380,7 +365,7 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt,
380365
}
381366

382367
__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot,
383-
late_pgtable_alloc);
368+
late_pgtable_alloc, !debug_pagealloc_enabled());
384369
}
385370

386371
static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
@@ -397,7 +382,8 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end
397382
if (end < kernel_start || start >= kernel_end) {
398383
__create_pgd_mapping(pgd, start, __phys_to_virt(start),
399384
end - start, PAGE_KERNEL,
400-
early_pgtable_alloc);
385+
early_pgtable_alloc,
386+
!debug_pagealloc_enabled());
401387
return;
402388
}
403389

@@ -409,12 +395,14 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end
409395
__create_pgd_mapping(pgd, start,
410396
__phys_to_virt(start),
411397
kernel_start - start, PAGE_KERNEL,
412-
early_pgtable_alloc);
398+
early_pgtable_alloc,
399+
!debug_pagealloc_enabled());
413400
if (kernel_end < end)
414401
__create_pgd_mapping(pgd, kernel_end,
415402
__phys_to_virt(kernel_end),
416403
end - kernel_end, PAGE_KERNEL,
417-
early_pgtable_alloc);
404+
early_pgtable_alloc,
405+
!debug_pagealloc_enabled());
418406

419407
/*
420408
* Map the linear alias of the [_text, _etext) interval as
@@ -424,7 +412,7 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end
424412
*/
425413
__create_pgd_mapping(pgd, kernel_start, __phys_to_virt(kernel_start),
426414
kernel_end - kernel_start, PAGE_KERNEL_RO,
427-
early_pgtable_alloc);
415+
early_pgtable_alloc, !debug_pagealloc_enabled());
428416
}
429417

430418
static void __init map_mem(pgd_t *pgd)
@@ -479,7 +467,7 @@ static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end,
479467
BUG_ON(!PAGE_ALIGNED(size));
480468

481469
__create_pgd_mapping(pgd, pa_start, (unsigned long)va_start, size, prot,
482-
early_pgtable_alloc);
470+
early_pgtable_alloc, !debug_pagealloc_enabled());
483471

484472
vma->addr = va_start;
485473
vma->phys_addr = pa_start;

0 commit comments

Comments
 (0)