ARM: mvebu: disable I/O coherency on !SMP
Get series with b4
b4 am [email protected]Versions newest first
- v1 Latest0 of 3 patches 0 repliesNew
Patches in v1 No applies recorded yet
None of the 3 patches the cover letter announces are in this archive.
Reviews trailers per patch
No Reviewed-by, Acked-by or Tested-by trailers for v1 yet.
Cover letter [PATCH 0/3] ARM: mvebu: disable I/O coherency on !SMP
Quoted 7 lines · Russell King - ARM Linux
Quoted 1 line · Santosh Shilimkar
Thanks for spotting it RMK. Will have a loot at it.
I already have this for it - which includes a lot more comments on the code (some in anticipation of the reply from the architecture people.) The first hunk alone should fix the spotted problem.
Cool. The alignment fix was easy but I was more worried about the other part. Thanks for the those additional comments.
Quoted 81 lines
arch/arm/mm/mmu.c +42
-5@@ -1406,8 +1406,8 @@ void __init early_paging_init(const struct machine_desc *mdesc,return ;/* remap kernel code and data */ - map_start = init_mm.start_code; - map_end = init_mm.brk; + map_start = init_mm.start_code &PMD_MASK ; + map_end =ALIGN (init_mm.brk,PMD_SIZE );/* get a handle on things... */ pgd0 =pgd_offset_k (0 );@@ -1434,23 +1434,60 @@ void __init early_paging_init(const struct machine_desc *mdesc,dsb (ishst);isb (); -/* remap level 1 table */ +/* +* WARNING: This code is not architecturally compliant: we modify +* the mappings in-place, indeed while they are in use by this +* very same code. +* +* Even modifying the mappings in a separate page table does +* not resolve this. +* +* The architecture strongly recommends that when a mapping is +* changed, that it is changed by first going via an invalid +* mapping and back to the new mapping. This is to ensure +* that no TLB conflicts (caused by the TLB having more than +* one TLB entry match a translation) can occur. +*/ + +/* +* Remap level 1 table. This changes the physical addresses +* used to refer to the level 2 page tables to the high +* physical address alias, leaving everything else the same. +*/ for (i =0 ; i <PTRS_PER_PGD ; pud0++, i++) {set_pud (pud0,__pud (__pa (pmd0) |PMD_TYPE_TABLE |L_PGD_SWAPPER )); pmd0 +=PTRS_PER_PMD ; } -/* remap pmds for kernel mapping */ - phys =__pa (map_start) &PMD_MASK ; +/* +* Remap the level 2 table, pointing the mappings at the high +* physical address alias of these pages. +*/ + phys =__pa (map_start);do { *pmdk++ =__pmd (phys | pmdprot); phys +=PMD_SIZE ; }while (phys < map_end); +/* +* Ensure that the above updates are flushed out of the cache. +* This is not strictly correct; on a system where the caches +* are coherent with each other, but the MMU page table walks +* may not be coherent, flush_cache_all() may be a no-op, and +* this will fail. +*/ flush_cache_all (); + +/* +* Re-write the TTBR values to point them at the high physical +* alias of the page tables. We expect __va() will work on +* cpu_get_pgd(), which returns the value of TTBR0. +*/ cpu_switch_mm (pgd0, &init_mm);cpu_set_ttbr (1 ,__pa (pgd0) +TTBR1_OFFSET ); + +/* Finally flush any stale TLB values. */ local_flush_bp_all ();local_flush_tlb_all (); }