diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-10-18 17:34:47 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-10-18 17:34:47 -0400 |
| commit | a0a55682b83fd5f012afadcf415b030d7424ae68 (patch) | |
| tree | 97ad3cb7e3443f09fbe55f57d3c36994b20a8e52 /arch/arm/kernel/smp.c | |
| parent | 23beab76b490172a9ff3d52843e4d27a35b2a4c6 (diff) | |
| parent | 865a4fae7793b80e2b8bca76e279d6dfecbeac17 (diff) | |
Merge branch 'hotplug' into devel
Conflicts:
arch/arm/kernel/head-common.S
Diffstat (limited to 'arch/arm/kernel/smp.c')
| -rw-r--r-- | arch/arm/kernel/smp.c | 63 |
1 files changed, 55 insertions, 8 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 32e16da5cbce..8c1959590252 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 | ||
| 71 | static 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 | |||
| 92 | static 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 | |||
| 70 | int __cpuinit __cpu_up(unsigned int cpu) | 107 | int __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) { |
