[PATCH 2/4] ARM: Allow optional UP processor functions for SMP kernels
Tony Lindgren
tony at atomide.com
Tue Aug 17 06:53:25 EDT 2010
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 at 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
}
More information about the linux-arm-kernel
mailing list