[PATCH 2/4] ARM: Allow optional UP processor functions for SMP kernels
From: tony@atomide.com (Tony Lindgren)
Date: 2010-08-17 10:53:25
Also in:
linux-omap
Subsystem:
arm port, the rest · Maintainers:
Russell King, Linus Torvalds
Attempt to detect if the hardware is UP hardware, and use the optional UP specific processors functions in struct proc_info_list if available. Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/include/asm/procinfo.h | 6 +++++ arch/arm/include/asm/smp_plat.h | 9 ++++++++ arch/arm/kernel/setup.c | 45 +++++++++++++++++++++++++++++++++++++++ arch/arm/mm/mmu.c | 20 ++++++++++------- 4 files changed, 71 insertions(+), 9 deletions(-)
diff --git a/arch/arm/include/asm/procinfo.h b/arch/arm/include/asm/procinfo.h
index ca52e58..962d01e 100644
--- a/arch/arm/include/asm/procinfo.h
+++ b/arch/arm/include/asm/procinfo.h@@ -40,6 +40,12 @@ struct proc_info_list { struct cpu_tlb_fns *tlb; struct cpu_user_fns *user; struct cpu_cache_fns *cache; + +#ifdef CONFIG_SMP_ON_UP + struct processor *proc_up; + struct cpu_tlb_fns *tlb_up; + struct cpu_cache_fns *cache_up; +#endif }; #else /* __KERNEL__ */
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h
index e621530..1c2f587 100644
--- a/arch/arm/include/asm/smp_plat.h
+++ b/arch/arm/include/asm/smp_plat.h@@ -18,4 +18,13 @@ static inline int cache_ops_need_broadcast(void) return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1; } +#ifdef CONFIG_SMP_ON_UP +extern int smp_on_up(void); +#else +static inline int smp_on_up(void) +{ + return 0; +} +#endif + #endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index d5231ae..5f3606c 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c@@ -289,6 +289,50 @@ static void __init feat_v6_fixup(void) elf_hwcap &= ~HWCAP_TLS; } +#ifdef CONFIG_SMP_ON_UP + +static int _smp_on_up; + +int smp_on_up(void) +{ + return _smp_on_up; +} + +static void __init smp_on_up_fixup(struct proc_info_list *list) +{ + int id; + + id = read_cpuid_id() & 0xff0f0000; + if ((id == 0x41070000) || (id == 0x410f0000)) { + int mpidr; + + asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (mpidr)); + mpidr >>= 30; + + /* SMP hardware? */ + if (!((mpidr == 0) || (mpidr == 3))) + return; + } + + _smp_on_up = 1; + + pr_info("CPU: SMP kernel on UP hardware\n"); + + if (list->proc_up) + processor = *list->proc_up; + + if (list->tlb_up) + cpu_tlb = *list->tlb_up; + + if (list->cache_up) + cpu_cache = *list->cache_up; +} +#else +static inline void smp_on_up_fixup(struct proc_info_list *list) +{ +} +#endif + static void __init setup_processor(void) { struct proc_info_list *list;
@@ -331,6 +375,7 @@ static void __init setup_processor(void) elf_hwcap &= ~HWCAP_THUMB; #endif + smp_on_up_fixup(list); feat_v6_fixup(); cacheid_init();
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 6e1c4f6..f320901 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c@@ -430,15 +430,17 @@ static void __init build_mem_type_table(void) /* * Mark memory with the "shared" attribute for SMP systems */ - user_pgprot |= L_PTE_SHARED; - kern_pgprot |= L_PTE_SHARED; - vecs_pgprot |= L_PTE_SHARED; - mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S; - mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; - mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; - mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; - mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; - mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; + if (!smp_on_up()) { + user_pgprot |= L_PTE_SHARED; + kern_pgprot |= L_PTE_SHARED; + vecs_pgprot |= L_PTE_SHARED; + mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S; + mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; + mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; + mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; + } #endif }