aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/mmu.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-09-04 05:47:48 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-10-04 15:23:36 -0400
commitf00ec48fadf5e37e7889f14cff900aa70d18b644 (patch)
tree421cbce97167a78532aa825624f380caade3c0d2 /arch/arm/mm/mmu.c
parent067173526c3bbc2eaeefcf6b7b2a9d998b9e8042 (diff)
ARM: Allow SMP kernels to boot on UP systems
UP systems do not implement all the instructions that SMP systems have, so in order to boot a SMP kernel on a UP system, we need to rewrite parts of the kernel. Do this using an 'alternatives' scheme, where the kernel code and data is modified prior to initialization to replace the SMP instructions, thereby rendering the problematical code ineffectual. We use the linker to generate a list of 32-bit word locations and their replacement values, and run through these replacements when we detect a UP system. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/mmu.c')
-rw-r--r--arch/arm/mm/mmu.c46
1 files changed, 21 insertions, 25 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 6a3a2d0cd6db..e2335811c02e 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -310,9 +310,8 @@ static void __init build_mem_type_table(void)
310 cachepolicy = CPOLICY_WRITEBACK; 310 cachepolicy = CPOLICY_WRITEBACK;
311 ecc_mask = 0; 311 ecc_mask = 0;
312 } 312 }
313#ifdef CONFIG_SMP 313 if (is_smp())
314 cachepolicy = CPOLICY_WRITEALLOC; 314 cachepolicy = CPOLICY_WRITEALLOC;
315#endif
316 315
317 /* 316 /*
318 * Strip out features not present on earlier architectures. 317 * Strip out features not present on earlier architectures.
@@ -406,13 +405,11 @@ static void __init build_mem_type_table(void)
406 cp = &cache_policies[cachepolicy]; 405 cp = &cache_policies[cachepolicy];
407 vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; 406 vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
408 407
409#ifndef CONFIG_SMP
410 /* 408 /*
411 * Only use write-through for non-SMP systems 409 * Only use write-through for non-SMP systems
412 */ 410 */
413 if (cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH) 411 if (!is_smp() && cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH)
414 vecs_pgprot = cache_policies[CPOLICY_WRITETHROUGH].pte; 412 vecs_pgprot = cache_policies[CPOLICY_WRITETHROUGH].pte;
415#endif
416 413
417 /* 414 /*
418 * Enable CPU-specific coherency if supported. 415 * Enable CPU-specific coherency if supported.
@@ -436,22 +433,23 @@ static void __init build_mem_type_table(void)
436 mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; 433 mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
437 mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; 434 mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
438 435
439#ifdef CONFIG_SMP 436 if (is_smp()) {
440 /* 437 /*
441 * Mark memory with the "shared" attribute for SMP systems 438 * Mark memory with the "shared" attribute
442 */ 439 * for SMP systems
443 user_pgprot |= L_PTE_SHARED; 440 */
444 kern_pgprot |= L_PTE_SHARED; 441 user_pgprot |= L_PTE_SHARED;
445 vecs_pgprot |= L_PTE_SHARED; 442 kern_pgprot |= L_PTE_SHARED;
446 mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S; 443 vecs_pgprot |= L_PTE_SHARED;
447 mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; 444 mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
448 mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; 445 mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
449 mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; 446 mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
450 mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; 447 mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
451 mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; 448 mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
452 mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; 449 mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
453 mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; 450 mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
454#endif 451 mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
452 }
455 } 453 }
456 454
457 /* 455 /*
@@ -829,8 +827,7 @@ static void __init sanity_check_meminfo(void)
829 * rather difficult. 827 * rather difficult.
830 */ 828 */
831 reason = "with VIPT aliasing cache"; 829 reason = "with VIPT aliasing cache";
832#ifdef CONFIG_SMP 830 } else if (is_smp() && tlb_ops_need_broadcast()) {
833 } else if (tlb_ops_need_broadcast()) {
834 /* 831 /*
835 * kmap_high needs to occasionally flush TLB entries, 832 * kmap_high needs to occasionally flush TLB entries,
836 * however, if the TLB entries need to be broadcast 833 * however, if the TLB entries need to be broadcast
@@ -840,7 +837,6 @@ static void __init sanity_check_meminfo(void)
840 * (must not be called with irqs off) 837 * (must not be called with irqs off)
841 */ 838 */
842 reason = "without hardware TLB ops broadcasting"; 839 reason = "without hardware TLB ops broadcasting";
843#endif
844 } 840 }
845 if (reason) { 841 if (reason) {
846 printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n", 842 printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n",