Skip to content

Commit b089c31

Browse files
tixyRussell King
authored andcommitted
ARM: 8667/3: Fix memory attribute inconsistencies when using fixmap
To cope with the variety in ARM architectures and configurations, the pagetable attributes for kernel memory are generated at runtime to match the system the kernel finds itself on. This calculated value is stored in pgprot_kernel. However, when early fixmap support was added for ARM (commit a5f4c56) the attributes used for mappings were hard coded because pgprot_kernel is not set up early enough. Unfortunately, when fixmap is used after early boot this means the memory being mapped can have different attributes to existing mappings, potentially leading to unpredictable behaviour. A specific problem also exists due to the hard coded values not include the 'shareable' attribute which means on systems where this matters (e.g. those with multiple CPU clusters) the cache contents for a memory location can become inconsistent between CPUs. To resolve these issues we change fixmap to use the same memory attributes (from pgprot_kernel) that the rest of the kernel uses. To enable this we need to refactor the initialisation code so build_mem_type_table() is called early enough. Note, that relies on early param parsing for memory type overrides passed via the kernel command line, so we need to make sure this call is still after parse_early_params(). [ardb: keep early_fixmap_init() before param parsing, for earlycon] Fixes: a5f4c56 ("ARM: 8415/1: early fixmap support for earlycon") Cc: <[email protected]> # v4.3+ Tested-by: afzal mohammed <[email protected]> Signed-off-by: Jon Medhurst <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]> Signed-off-by: Russell King <[email protected]>
1 parent ea2d9a9 commit b089c31

File tree

3 files changed

+16
-6
lines changed

3 files changed

+16
-6
lines changed

arch/arm/include/asm/fixmap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ static const enum fixed_addresses __end_of_fixed_addresses =
4141

4242
#define FIXMAP_PAGE_COMMON (L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN | L_PTE_DIRTY)
4343

44-
#define FIXMAP_PAGE_NORMAL (FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK)
44+
#define FIXMAP_PAGE_NORMAL (pgprot_kernel | L_PTE_XN)
4545
#define FIXMAP_PAGE_RO (FIXMAP_PAGE_NORMAL | L_PTE_RDONLY)
4646

4747
/* Used by set_fixmap_(io|nocache), both meant for mapping a device */

arch/arm/kernel/setup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ __setup("fpe=", fpe_setup);
8080

8181
extern void init_default_cache_policy(unsigned long);
8282
extern void paging_init(const struct machine_desc *desc);
83-
extern void early_paging_init(const struct machine_desc *);
83+
extern void early_mm_init(const struct machine_desc *);
8484
extern void adjust_lowmem_bounds(void);
8585
extern enum reboot_mode reboot_mode;
8686
extern void setup_dma_zone(const struct machine_desc *desc);
@@ -1088,7 +1088,7 @@ void __init setup_arch(char **cmdline_p)
10881088
parse_early_param();
10891089

10901090
#ifdef CONFIG_MMU
1091-
early_paging_init(mdesc);
1091+
early_mm_init(mdesc);
10921092
#endif
10931093
setup_dma_zone(mdesc);
10941094
xen_early_init();

arch/arm/mm/mmu.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
414414
FIXADDR_END);
415415
BUG_ON(idx >= __end_of_fixed_addresses);
416416

417+
/* we only support device mappings until pgprot_kernel has been set */
418+
if (WARN_ON(pgprot_val(prot) != pgprot_val(FIXMAP_PAGE_IO) &&
419+
pgprot_val(pgprot_kernel) == 0))
420+
return;
421+
417422
if (pgprot_val(prot))
418423
set_pte_at(NULL, vaddr, pte,
419424
pfn_pte(phys >> PAGE_SHIFT, prot));
@@ -1492,7 +1497,7 @@ pgtables_remap lpae_pgtables_remap_asm;
14921497
* early_paging_init() recreates boot time page table setup, allowing machines
14931498
* to switch over to a high (>4G) address space on LPAE systems
14941499
*/
1495-
void __init early_paging_init(const struct machine_desc *mdesc)
1500+
static void __init early_paging_init(const struct machine_desc *mdesc)
14961501
{
14971502
pgtables_remap *lpae_pgtables_remap;
14981503
unsigned long pa_pgd;
@@ -1560,7 +1565,7 @@ void __init early_paging_init(const struct machine_desc *mdesc)
15601565

15611566
#else
15621567

1563-
void __init early_paging_init(const struct machine_desc *mdesc)
1568+
static void __init early_paging_init(const struct machine_desc *mdesc)
15641569
{
15651570
long long offset;
15661571

@@ -1616,7 +1621,6 @@ void __init paging_init(const struct machine_desc *mdesc)
16161621
{
16171622
void *zero_page;
16181623

1619-
build_mem_type_table();
16201624
prepare_page_table();
16211625
map_lowmem();
16221626
memblock_set_current_limit(arm_lowmem_limit);
@@ -1636,3 +1640,9 @@ void __init paging_init(const struct machine_desc *mdesc)
16361640
empty_zero_page = virt_to_page(zero_page);
16371641
__flush_dcache_page(NULL, empty_zero_page);
16381642
}
1643+
1644+
void __init early_mm_init(const struct machine_desc *mdesc)
1645+
{
1646+
build_mem_type_table();
1647+
early_paging_init(mdesc);
1648+
}

0 commit comments

Comments
 (0)