Skip to content

Commit

Permalink
ARM: hotplug cpu: setup 1:1 map for entire kernel image for secondary…
Browse files Browse the repository at this point in the history
… 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>
  • Loading branch information
Russell King committed Oct 8, 2010
1 parent f131a08 commit 37b05b6
Showing 1 changed file with 55 additions and 8 deletions.
63 changes: 55 additions & 8 deletions arch/arm/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/processor.h>
#include <asm/sections.h>
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
#include <asm/localtimer.h>
Expand Down Expand Up @@ -67,12 +68,47 @@ enum ipi_msg_type {
IPI_CPU_STOP,
};

static inline void identity_mapping_add(pgd_t *pgd, unsigned long start,
unsigned long end)
{
unsigned long addr, prot;
pmd_t *pmd;

prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
prot |= PMD_BIT4;

for (addr = start & PGDIR_MASK; addr < end;) {
pmd = pmd_offset(pgd + pgd_index(addr), addr);
pmd[0] = __pmd(addr | prot);
addr += SECTION_SIZE;
pmd[1] = __pmd(addr | prot);
addr += SECTION_SIZE;
flush_pmd_entry(pmd);
outer_clean_range(__pa(pmd), __pa(pmd + 1));
}
}

static inline void identity_mapping_del(pgd_t *pgd, unsigned long start,
unsigned long end)
{
unsigned long addr;
pmd_t *pmd;

for (addr = start & PGDIR_MASK; addr < end; addr += PGDIR_SIZE) {
pmd = pmd_offset(pgd + pgd_index(addr), addr);
pmd[0] = __pmd(0);
pmd[1] = __pmd(0);
clean_pmd_entry(pmd);
outer_clean_range(__pa(pmd), __pa(pmd + 1));
}
}

int __cpuinit __cpu_up(unsigned int cpu)
{
struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
struct task_struct *idle = ci->idle;
pgd_t *pgd;
pmd_t *pmd;
int ret;

/*
Expand Down Expand Up @@ -101,11 +137,16 @@ int __cpuinit __cpu_up(unsigned int cpu)
* a 1:1 mapping for the physical address of the kernel.
*/
pgd = pgd_alloc(&init_mm);
pmd = pmd_offset(pgd + pgd_index(PHYS_OFFSET), PHYS_OFFSET);
*pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
flush_pmd_entry(pmd);
outer_clean_range(__pa(pmd), __pa(pmd + 1));
if (!pgd)
return -ENOMEM;

if (PHYS_OFFSET != PAGE_OFFSET) {
#ifndef CONFIG_HOTPLUG_CPU
identity_mapping_add(pgd, __pa(__init_begin), __pa(__init_end));
#endif
identity_mapping_add(pgd, __pa(_stext), __pa(_etext));
identity_mapping_add(pgd, __pa(_sdata), __pa(_edata));
}

/*
* We need to tell the secondary core where to find
Expand Down Expand Up @@ -143,8 +184,14 @@ int __cpuinit __cpu_up(unsigned int cpu)
secondary_data.stack = NULL;
secondary_data.pgdir = 0;

*pmd = __pmd(0);
clean_pmd_entry(pmd);
if (PHYS_OFFSET != PAGE_OFFSET) {
#ifndef CONFIG_HOTPLUG_CPU
identity_mapping_del(pgd, __pa(__init_begin), __pa(__init_end));
#endif
identity_mapping_del(pgd, __pa(_stext), __pa(_etext));
identity_mapping_del(pgd, __pa(_sdata), __pa(_edata));
}

pgd_free(&init_mm, pgd);

if (ret) {
Expand Down

0 comments on commit 37b05b6

Please sign in to comment.