Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37b05b63 authored by Russell King's avatar Russell King
Browse files

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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent f131a080
Loading
Loading
Loading
Loading
+55 −8
Original line number Diff line number Diff line
@@ -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>
@@ -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;

	/*
@@ -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
@@ -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) {