arm: Fix memory attribute inconsistencies when using fixmap
PATCH v3 1/1 arm: Fix memory attribute inconsistencies when using fixmap
From: Jon Medhurst <[email protected]>
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 a5f4c561b3b1) 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().
---
v3: - Unfortunately, I failed to spot an issue with earlycon when testing
Tixy's v2. Earlycon depends on fixmap, but only for device mappings, which are not affected by this change. So instead, preserve the calls to early_fixmap_init() and early_ioremap_init() in their original locations, and only move build_mem_type_table() to the earliest possible moment in boot, which is right after early param parsing (which may set cachepolicy/nocache/nowb variables)
arch/arm/include/asm/fixmap.h | 2 +- arch/arm/include/asm/mmu.h | 6 ++++++ arch/arm/kernel/setup.c | 5 ++--- arch/arm/mm/mmu.c | 12 +++++++++++- 4 files changed, 20 insertions(+), 5 deletions(-)
arch/arm/include/asm/fixmap.h +1 -1
@@ -41,7 +41,7 @@ static const enum fixed_addresses __end_of_fixed_addresses =#define FIXMAP_PAGE_COMMON (L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN | L_PTE_DIRTY) -#define FIXMAP_PAGE_NORMAL (FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK) +#define FIXMAP_PAGE_NORMAL (pgprot_kernel | L_PTE_XN)#define FIXMAP_PAGE_RO (FIXMAP_PAGE_NORMAL | L_PTE_RDONLY)/* Used by set_fixmap_(io|nocache), both meant for mapping a device */
arch/arm/include/asm/mmu.h +6 -0
@@ -1,6 +1,8 @@ #ifndef __ARM_MMU_H #define __ARM_MMU_H +struct machine_desc; + #ifdef CONFIG_MMU typedef struct {
@@ -24,6 +26,8 @@ typedef struct {#define ASID (mm) (0)#endif +void early_mm_init (const struct machine_desc *mdesc); +#else /*
@@ -35,6 +39,8 @@ typedef struct {unsigned long end_brk; } mm_context_t; +static inline void early_mm_init (const struct machine_desc *mdesc) { } +#endif #endif
arch/arm/kernel/setup.c +2 -3
@@ -1087,9 +1087,8 @@ void __init setup_arch(char **cmdline_p)parse_early_param (); -#ifdef CONFIG_MMU -early_paging_init (mdesc); -#endif +early_mm_init (mdesc); +setup_dma_zone (mdesc);xen_early_init ();efi_init ();
arch/arm/mm/mmu.c +11 -1
@@ -414,6 +414,11 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) FIXADDR_END);BUG_ON (idx >= __end_of_fixed_addresses); +/* we only support device mappings until pgprot_kernel has been set */ +if (WARN_ON (pgprot_val (prot) !=pgprot_val (FIXMAP_PAGE_IO ) && +pgprot_val (pgprot_kernel) ==0 )) +return ; +if (pgprot_val (prot))set_pte_at (NULL , vaddr, pte,pfn_pte (phys >>PAGE_SHIFT , prot));
@@ -1616,7 +1621,6 @@ void __init paging_init(const struct machine_desc *mdesc) {void *zero_page; -build_mem_type_table ();prepare_page_table ();map_lowmem ();memblock_set_current_limit (arm_lowmem_limit);
@@ -1636,3 +1640,9 @@ void __init paging_init(const struct machine_desc *mdesc) empty_zero_page =virt_to_page (zero_page);__flush_dcache_page (NULL , empty_zero_page); } + +void __init early_mm_init (const struct machine_desc *mdesc) +{ +build_mem_type_table (); +early_paging_init (mdesc); +}
Signature · 1 line
2.7.4
PATCH v3 1/1 arm: Fix memory attribute inconsistencies when using fixmap
Quoted 32 lines · Ard Biesheuvel
From: Jon Medhurst <[email protected]>
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
a5f4c561b3b1) the attributes used for mappings were hard coded becausepgprot_kernelis 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 sobuild_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 afterparse_early_params().Fixes a5f4c561b3b1 ("ARM: 8415/1: early fixmap support for earlycon")Cc <[email protected]> # v4.3+Signed-off-by Jon Medhurst <[email protected]>[ardb: keep early_fixmap_init() before param parsing, for earlycon]Signed-off-by Ard Biesheuvel <[email protected]>---
[...]
arch/arm/mm/mmu.c void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) · line 421
Quoted 13 lines
arch/arm/mm/mmu.c +5
-0@@ -414,6 +414,11 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) FIXADDR_END);BUG_ON (idx >= __end_of_fixed_addresses); +/* we only support device mappings until pgprot_kernel has been set */ +if (WARN_ON (pgprot_val (prot) !=pgprot_val (FIXMAP_PAGE_IO ) && +pgprot_val (pgprot_kernel) ==0 )) +return ; +
Hmm, on return from this function, isn't the caller then going to try and access the memory at the fixmap address we didn't map, and so get a page fault? If so, would a BUG_ON here be better?
Quoted 12 lines
arch/arm/mm/mmu.c +0
-1if (pgprot_val (prot))set_pte_at (NULL , vaddr, pte,pfn_pte (phys >>PAGE_SHIFT , prot));@@ -1616,7 +1621,6 @@ void __init paging_init(const struct machine_desc *mdesc) {void *zero_page; -build_mem_type_table ();prepare_page_table ();map_lowmem ();memblock_set_current_limit (arm_lowmem_limit);
arch/arm/mm/mmu.c void __init paging_init(const struct machine_desc *mdesc) · line 1648
Quoted 9 lines
arch/arm/mm/mmu.c +6
-0@@ -1636,3 +1640,9 @@ void __init paging_init(const struct machine_desc *mdesc) empty_zero_page =virt_to_page (zero_page);__flush_dcache_page (NULL , empty_zero_page); } + +void __init early_mm_init (const struct machine_desc *mdesc) +{ +build_mem_type_table (); +early_paging_init (mdesc); +}
I tested this change with kprobes tests on TC2 (the setup that showed the original bug) and compile tested for a nommu device (I will boot test that in a bit as that's not quick to setup).
Also, with this patch we can now make?early_paging_init() static now, and remove the extern...
arch/arm/kernel/setup.c +0 -1
@@ -80,7 +80,6 @@ __setup("fpe=", fpe_setup);extern void init_default_cache_policy (unsigned long );extern void paging_init (const struct machine_desc *desc); -extern void early_paging_init (const struct machine_desc *);extern void adjust_lowmem_bounds (void );extern enum reboot_mode reboot_mode;extern void setup_dma_zone (const struct machine_desc *desc);
arch/arm/mm/mmu.c +2 -2
@@ -1497,7 +1497,7 @@ pgtables_remap lpae_pgtables_remap_asm;* early_paging_init() recreates boot time page table setup, allowing machines * to switch over to a high (>4G) address space on LPAE systems */ -void __init early_paging_init (const struct machine_desc *mdesc) +static void __init early_paging_init (const struct machine_desc *mdesc) {pgtables_remap *lpae_pgtables_remap;unsigned long pa_pgd;
@@ -1565,7 +1565,7 @@ void __init early_paging_init(const struct machine_desc *mdesc)#else -void __init early_paging_init (const struct machine_desc *mdesc) +static void __init early_paging_init (const struct machine_desc *mdesc) {long long offset;
PATCH v3 1/1 arm: Fix memory attribute inconsistencies when using fixmap
Quoted 42 lines · Jon Medhurst (Tixy)
Quoted 32 lines · Ard Biesheuvel
From: Jon Medhurst <[email protected]>
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
a5f4c561b3b1) the attributes used for mappings were hard coded becausepgprot_kernelis 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 sobuild_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 afterparse_early_params().Fixes a5f4c561b3b1 ("ARM: 8415/1: early fixmap support for earlycon")Cc <[email protected]> # v4.3+Signed-off-by Jon Medhurst <[email protected]>[ardb: keep early_fixmap_init() before param parsing, for earlycon]Signed-off-by Ard Biesheuvel <[email protected]>---
[...]
Quoted 8 lines
arch/arm/mm/mmu.c +0
-0@@ -414,6 +414,11 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) FIXADDR_END);BUG_ON (idx >= __end_of_fixed_addresses);
Quoted 10 lines
arch/arm/mm/mmu.c void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) · line 421
Quoted 5 lines
arch/arm/mm/mmu.c +5
-0+/* we only support device mappings until pgprot_kernel has been set */ +if (WARN_ON (pgprot_val (prot) !=pgprot_val (FIXMAP_PAGE_IO ) && +pgprot_val (pgprot_kernel) ==0 )) +return ; +Hmm, on return from this function, isn't the caller then going to try and access the memory at the fixmap address we didn't map, and so get a page fault? If so, would a
BUG_ONhere be better?
Yes, and no. BUG_ON guarantees a crash, while without it, it's only highly likely. Since this will occur very early during boot, it is better to limp on if we can than crash unconditionally.
Quoted 55 lines
Quoted 12 lines
arch/arm/mm/mmu.c +0
-1if (pgprot_val (prot))set_pte_at (NULL , vaddr, pte,pfn_pte (phys >>PAGE_SHIFT , prot));@@ -1616,7 +1621,6 @@ void __init paging_init(const struct machine_desc *mdesc) {void *zero_page; -build_mem_type_table ();prepare_page_table ();map_lowmem ();memblock_set_current_limit (arm_lowmem_limit);arch/arm/mm/mmu.c void __init paging_init(const struct machine_desc *mdesc) · line 1648
Quoted 9 lines
arch/arm/mm/mmu.c +6
-0@@ -1636,3 +1640,9 @@ void __init paging_init(const struct machine_desc *mdesc) empty_zero_page =virt_to_page (zero_page);__flush_dcache_page (NULL , empty_zero_page); } + +void __init early_mm_init (const struct machine_desc *mdesc) +{ +build_mem_type_table (); +early_paging_init (mdesc); +}I tested this change with kprobes tests on TC2 (the setup that showed the original bug) and compile tested for a nommu device (I will boot test that in a bit as that's not quick to setup).
Also, with this patch we can now make
early_paging_init()static now, and remove the extern...arch/arm/kernel/setup.c +0
-1@@ -80,7 +80,6 @@ __setup("fpe=", fpe_setup);extern void init_default_cache_policy (unsigned long );extern void paging_init (const struct machine_desc *desc); -extern void early_paging_init (const struct machine_desc *);extern void adjust_lowmem_bounds (void );extern enum reboot_mode reboot_mode;extern void setup_dma_zone (const struct machine_desc *desc);arch/arm/mm/mmu.c +1
-1@@ -1497,7 +1497,7 @@ pgtables_remap lpae_pgtables_remap_asm;* early_paging_init() recreates boot time page table setup, allowing machines * to switch over to a high (>4G) address space on LPAE systems */ -void __init early_paging_init (const struct machine_desc *mdesc) +static void __init early_paging_init (const struct machine_desc *mdesc) {pgtables_remap *lpae_pgtables_remap;unsigned long pa_pgd;
arch/arm/mm/mmu.c void __init early_paging_init(const struct machine_desc *mdesc) · line 1571
Quoted 8 lines
arch/arm/mm/mmu.c +1
-1@@ -1565,7 +1565,7 @@ void __init early_paging_init(const struct machine_desc *mdesc)#else -void __init early_paging_init (const struct machine_desc *mdesc) +static void __init early_paging_init (const struct machine_desc *mdesc) {long long offset;
Good point. If everything checks out, we should fold that in when submitting it to the patch tracker.
PATCH v3 1/1 arm: Fix memory attribute inconsistencies when using fixmap
Quoted 1 line · Ard Biesheuvel
On 4 April 2017 at 09:48, Jon Medhurst (Tixy) <[email protected]> wrote:
[...]
Quoted 3 lines
Quoted 3 lines
I tested this change with kprobes tests on TC2 (the setup that showed the original bug) and compile tested for a nommu device (I will boot test that in a bit as that's not quick to setup).
The nommu device (ARM MPS2) boots OK
Quoted 3 lines
Quoted 3 lines
Also, with this patch we can now make
early_paging_init()static now, and remove the extern...
[...]
Quoted 2 lines
Good point. If everything checks out, we should fold that in when submitting it to the patch tracker.
I delayed a little in case Russell had comments about the changes, but I've now submitted the patch...
http://www.armlinux.org.uk/developer/patches/viewpatch.php?id=8667/2
Signature · 1 line
Tixy
Russell King - ARM Linux
maintainerPATCH v3 1/1 arm: Fix memory attribute inconsistencies when using fixmap
In reply to Ard BiesheuvelQuoted 23 lines · Ard Biesheuvel
arch/arm/include/asm/mmu.h +4
-0@@ -1,6 +1,8 @@ #ifndef __ARM_MMU_H #define __ARM_MMU_H +struct machine_desc; + #ifdef CONFIG_MMU typedef struct {@@ -24,6 +26,8 @@ typedef struct {#define ASID (mm) (0)#endif +void early_mm_init (const struct machine_desc *mdesc); +#else /*
arch/arm/include/asm/mmu.h typedef struct { · line 43
Quoted 5 lines
arch/arm/include/asm/mmu.h +2
-0@@ -35,6 +39,8 @@ typedef struct {unsigned long end_brk; } mm_context_t; +static inline void early_mm_init (const struct machine_desc *mdesc) { } +
Why are we stuffing this into mmu.h? mmu.h is not the header file for arch/arm/mm/mmu.c - although they have the same base filename, they are not really related.
asm/mmu.h is supposed to be a kernel-wide include file for the mm_context_t thing, and should not be filled with arch-private stuff.
Please find a better location for this.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up according to speedtest.net.
PATCH v3 1/1 arm: Fix memory attribute inconsistencies when using fixmap
Quoted 34 lines · Russell King - ARM Linux
Quoted 23 lines · Ard Biesheuvel
arch/arm/include/asm/mmu.h +4
-0@@ -1,6 +1,8 @@ #ifndef __ARM_MMU_H #define __ARM_MMU_H +struct machine_desc; + #ifdef CONFIG_MMU typedef struct {@@ -24,6 +26,8 @@ typedef struct {#define ASID (mm) (0)#endif +void early_mm_init (const struct machine_desc *mdesc); +#else /* arch/arm/include/asm/mmu.h typedef struct { · line 43
Quoted 5 lines
arch/arm/include/asm/mmu.h +2
-0@@ -35,6 +39,8 @@ typedef struct {unsigned long end_brk; } mm_context_t; +static inline void early_mm_init (const struct machine_desc *mdesc) { } +Why are we stuffing this into
mmu.h?mmu.his not the header file forarch/arm/mm/mmu.c- although they have the same base filename, they are not really related.
Quoted 4 lines
asm/mmu.his supposed to be a kernel-wide include file for themm_context_tthing, and should not be filled with arch-private stuff.Please find a better location for this.
In arch/arm/mm/mm.h ?
Or as early_mm_init() is replacing early_paging_init()?in setup.c, and that is currently handled by a local extern statement, keeping doing the same? That keeps the diff neater which is a plus for a patch that should be backported to stable kernels.
Signature · 1 line
Tixy
PATCH v3 1/1 arm: Fix memory attribute inconsistencies when using fixmap
Quoted 38 lines · Jon Medhurst (Tixy)
Quoted 37 lines · Russell King - ARM Linux
Quoted 23 lines · Ard Biesheuvel
arch/arm/include/asm/mmu.h +4
-0@@ -1,6 +1,8 @@ #ifndef __ARM_MMU_H #define __ARM_MMU_H +struct machine_desc; + #ifdef CONFIG_MMU typedef struct {@@ -24,6 +26,8 @@ typedef struct {#define ASID (mm) (0)#endif +void early_mm_init (const struct machine_desc *mdesc); +#else /* arch/arm/include/asm/mmu.h typedef struct { · line 43
Quoted 5 lines
arch/arm/include/asm/mmu.h +2
-0@@ -35,6 +39,8 @@ typedef struct {unsigned long end_brk; } mm_context_t; +static inline void early_mm_init (const struct machine_desc *mdesc) { } +Why are we stuffing this into
mmu.h?mmu.his not the header file forarch/arm/mm/mmu.c- although they have the same base filename, they are not really related.
asm/mmu.his supposed to be a kernel-wide include file for themm_context_tthing, and should not be filled with arch-private stuff.
Quoted 9 lines
Quoted 1 line
Please find a better location for this.
In
arch/arm/mm/mm.h?Or as
early_mm_init()is replacingearly_paging_init()insetup.c, and that is currently handled by a local extern statement, keeping doing the same? That keeps the diff neater which is a plus for a patch that should be backported to stable kernels.
Yes, the latter sounds like the least intrusive approach.
PATCH v4 1/1 arm: 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 a5f4c561b3b1) 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().
---
v4: - Drop declaration of early_mm_init() from arch/arm/include/asm/mmu.h
and make early_paging_init() static.
Ard's v3:
- Unfortunately, I failed to spot an issue with earlycon when testing Tixy's v2. Earlycon depends on fixmap, but only for device mappings, which are not affected by this change. So instead, preserve the calls to early_fixmap_init() and early_ioremap_init() in their original locations, and only move build_mem_type_table() to the earliest possible moment in boot, which is right after early param parsing (which may set cachepolicy/nocache/nowb variables)
arch/arm/include/asm/fixmap.h | 2 +- arch/arm/kernel/setup.c | 4 ++-- arch/arm/mm/mmu.c | 16 +++++++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-)
arch/arm/include/asm/fixmap.h +1 -1
@@ -41,7 +41,7 @@ static const enum fixed_addresses __end_of_fixed_addresses =#define FIXMAP_PAGE_COMMON (L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN | L_PTE_DIRTY) -#define FIXMAP_PAGE_NORMAL (FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK) +#define FIXMAP_PAGE_NORMAL (pgprot_kernel | L_PTE_XN)#define FIXMAP_PAGE_RO (FIXMAP_PAGE_NORMAL | L_PTE_RDONLY)/* Used by set_fixmap_(io|nocache), both meant for mapping a device */
arch/arm/kernel/setup.c +2 -2
@@ -80,7 +80,7 @@ __setup("fpe=", fpe_setup);extern void init_default_cache_policy (unsigned long );extern void paging_init (const struct machine_desc *desc); -extern void early_paging_init (const struct machine_desc *); +extern void early_mm_init (const struct machine_desc *);extern void adjust_lowmem_bounds (void );extern enum reboot_mode reboot_mode;extern void setup_dma_zone (const struct machine_desc *desc);
@@ -1088,7 +1088,7 @@ void __init setup_arch(char **cmdline_p)parse_early_param ();#ifdef CONFIG_MMU -early_paging_init (mdesc); +early_mm_init (mdesc);#endif setup_dma_zone (mdesc);xen_early_init ();
arch/arm/mm/mmu.c +13 -3
@@ -414,6 +414,11 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) FIXADDR_END);BUG_ON (idx >= __end_of_fixed_addresses); +/* we only support device mappings until pgprot_kernel has been set */ +if (WARN_ON (pgprot_val (prot) !=pgprot_val (FIXMAP_PAGE_IO ) && +pgprot_val (pgprot_kernel) ==0 )) +return ; +if (pgprot_val (prot))set_pte_at (NULL , vaddr, pte,pfn_pte (phys >>PAGE_SHIFT , prot));
@@ -1492,7 +1497,7 @@ pgtables_remap lpae_pgtables_remap_asm;* early_paging_init() recreates boot time page table setup, allowing machines * to switch over to a high (>4G) address space on LPAE systems */ -void __init early_paging_init (const struct machine_desc *mdesc) +static void __init early_paging_init (const struct machine_desc *mdesc) {pgtables_remap *lpae_pgtables_remap;unsigned long pa_pgd;
@@ -1560,7 +1565,7 @@ void __init early_paging_init(const struct machine_desc *mdesc)#else -void __init early_paging_init (const struct machine_desc *mdesc) +static void __init early_paging_init (const struct machine_desc *mdesc) {long long offset;
@@ -1616,7 +1621,6 @@ void __init paging_init(const struct machine_desc *mdesc) {void *zero_page; -build_mem_type_table ();prepare_page_table ();map_lowmem ();memblock_set_current_limit (arm_lowmem_limit);
@@ -1636,3 +1640,9 @@ void __init paging_init(const struct machine_desc *mdesc) empty_zero_page =virt_to_page (zero_page);__flush_dcache_page (NULL , empty_zero_page); } + +void __init early_mm_init (const struct machine_desc *mdesc) +{ +build_mem_type_table (); +early_paging_init (mdesc); +}
PATCH v4 1/1 arm: Fix memory attribute inconsistencies when using fixmap
Hi,
Quoted 16 lines · Jon Medhurst (Tixy)
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
a5f4c561b3b1) the attributes used for mappings were hard coded becausepgprot_kernelis 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.
Quoted 7 lines
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 sobuild_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 afterparse_early_params().
with an emphasis on no-MMU's
Regards
afzal
PATCH v4 1/1 arm: Fix memory attribute inconsistencies when using fixmap
Quoted 27 lines · afzal mohammed
Hi,
Quoted 16 lines · Jon Medhurst (Tixy)
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
a5f4c561b3b1) the attributes used for mappings were hard coded becausepgprot_kernelis 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.Quoted 7 lines
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 sobuild_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 afterparse_early_params().
Quoted 3 lines
Tested-by afzal mohammed <[email protected]>with an emphasis on no-MMU's
Thanks. I've now submitted this new version to the patch tracker...
http://www.armlinux.org.uk/developer/patches/viewpatch.php?id=8667/3