aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/smp.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-10-01 10:38:24 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-10-08 05:07:32 -0400
commit37b05b63754e995b8cb76f4fbe7ed7219b3ca896 (patch)
treedc72186db922ebfb7d3d842dccb9dc6006d163e3 /arch/arm/kernel/smp.c
parentf131a0800e286a13839784e554383c0ddfa78bce (diff)
ARM: hotplug cpu: setup 1:1 map for entire kernel image for secondary CPUs
Make the entire kernel image available for secondary CPUs rather than just the first MB of memory. This allows the startup code to appear in the cpuinit sections. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel/smp.c')
-rw-r--r--arch/arm/kernel/smp.c63
1 files changed, 55 insertions, 8 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 40dc74f2b27f..14070549e051 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -33,6 +33,7 @@
33#include <asm/pgtable.h> 33#include <asm/pgtable.h>
34#include <asm/pgalloc.h> 34#include <asm/pgalloc.h>
35#include <asm/processor.h> 35#include <asm/processor.h>
36#include <asm/sections.h>
36#include <asm/tlbflush.h> 37#include <asm/tlbflush.h>
37#include <asm/ptrace.h> 38#include <asm/ptrace.h>
38#include <asm/localtimer.h> 39#include <asm/localtimer.h>
@@ -67,12 +68,47 @@ enum ipi_msg_type {
67 IPI_CPU_STOP, 68 IPI_CPU_STOP,
68}; 69};
69 70
71static inline void identity_mapping_add(pgd_t *pgd, unsigned long start,
72 unsigned long end)
73{
74 unsigned long addr, prot;
75 pmd_t *pmd;
76
77 prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
78 if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
79 prot |= PMD_BIT4;
80
81 for (addr = start & PGDIR_MASK; addr < end;) {
82 pmd = pmd_offset(pgd + pgd_index(addr), addr);
83 pmd[0] = __pmd(addr | prot);
84 addr += SECTION_SIZE;
85 pmd[1] = __pmd(addr | prot);
86 addr += SECTION_SIZE;
87 flush_pmd_entry(pmd);
88 outer_clean_range(__pa(pmd), __pa(pmd + 1));
89 }
90}
91
92static inline void identity_mapping_del(pgd_t *pgd, unsigned long start,
93 unsigned long end)
94{
95 unsigned long addr;
96 pmd_t *pmd;
97
98 for (addr = start & PGDIR_MASK; addr < end; addr += PGDIR_SIZE) {
99 pmd = pmd_offset(pgd + pgd_index(addr), addr);
100 pmd[0] = __pmd(0);
101 pmd[1] = __pmd(0);
102 clean_pmd_entry(pmd);
103 outer_clean_range(__pa(pmd), __pa(pmd + 1));
104 }
105}
106
70int __cpuinit __cpu_up(unsigned int cpu) 107int __cpuinit __cpu_up(unsigned int cpu)
71{ 108{
72 struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); 109 struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
73 struct task_struct *idle = ci->idle; 110 struct task_struct *idle = ci->idle;
74 pgd_t *pgd; 111 pgd_t *pgd;
75 pmd_t *pmd;
76 int ret; 112 int ret;
77 113
78 /* 114 /*
@@ -101,11 +137,16 @@ int __cpuinit __cpu_up(unsigned int cpu)
101 * a 1:1 mapping for the physical address of the kernel. 137 * a 1:1 mapping for the physical address of the kernel.
102 */ 138 */
103 pgd = pgd_alloc(&init_mm); 139 pgd = pgd_alloc(&init_mm);
104 pmd = pmd_offset(pgd + pgd_index(PHYS_OFFSET), PHYS_OFFSET); 140 if (!pgd)
105 *pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) | 141 return -ENOMEM;
106 PMD_TYPE_SECT | PMD_SECT_AP_WRITE); 142
107 flush_pmd_entry(pmd); 143 if (PHYS_OFFSET != PAGE_OFFSET) {
108 outer_clean_range(__pa(pmd), __pa(pmd + 1)); 144#ifndef CONFIG_HOTPLUG_CPU
145 identity_mapping_add(pgd, __pa(__init_begin), __pa(__init_end));
146#endif
147 identity_mapping_add(pgd, __pa(_stext), __pa(_etext));
148 identity_mapping_add(pgd, __pa(_sdata), __pa(_edata));
149 }
109 150
110 /* 151 /*
111 * We need to tell the secondary core where to find 152 * We need to tell the secondary core where to find
@@ -143,8 +184,14 @@ int __cpuinit __cpu_up(unsigned int cpu)
143 secondary_data.stack = NULL; 184 secondary_data.stack = NULL;
144 secondary_data.pgdir = 0; 185 secondary_data.pgdir = 0;
145 186
146 *pmd = __pmd(0); 187 if (PHYS_OFFSET != PAGE_OFFSET) {
147 clean_pmd_entry(pmd); 188#ifndef CONFIG_HOTPLUG_CPU
189 identity_mapping_del(pgd, __pa(__init_begin), __pa(__init_end));
190#endif
191 identity_mapping_del(pgd, __pa(_stext), __pa(_etext));
192 identity_mapping_del(pgd, __pa(_sdata), __pa(_edata));
193 }
194
148 pgd_free(&init_mm, pgd); 195 pgd_free(&init_mm, pgd);
149 196
150 if (ret) { 197 if (ret) {