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

Commit 8b22c249 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge master.kernel.org:/home/rmk/linux-2.6-arm

parents 7df55125 ea4423c3
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@
 *  linux/arch/arm/kernel/head.S
 *
 *  Copyright (C) 1994-2002 Russell King
 *  Copyright (c) 2003 ARM Limited
 *  All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
@@ -165,6 +167,48 @@ __mmap_switched:
	stmia	r6, {r0, r4}			@ Save control register values
	b	start_kernel

#if defined(CONFIG_SMP)
	.type   secondary_startup, #function
ENTRY(secondary_startup)
	/*
	 * Common entry point for secondary CPUs.
	 *
	 * Ensure that we're in SVC mode, and IRQs are disabled.  Lookup
	 * the processor type - there is no need to check the machine type
	 * as it has already been validated by the primary processor.
	 */
	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
	bl	__lookup_processor_type
	movs	r10, r5				@ invalid processor?
	moveq	r0, #'p'			@ yes, error 'p'
	beq	__error

	/*
	 * Use the page tables supplied from  __cpu_up.
	 */
	adr	r4, __secondary_data
	ldmia	r4, {r5, r6, r13}		@ address to jump to after
	sub	r4, r4, r5			@ mmu has been enabled
	ldr	r4, [r6, r4]			@ get secondary_data.pgdir
	adr	lr, __enable_mmu		@ return address
	add	pc, r10, #12			@ initialise processor
						@ (return control reg)

	/*
	 * r6  = &secondary_data
	 */
ENTRY(__secondary_switched)
	ldr	sp, [r6, #4]			@ get secondary_data.stack
	mov	fp, #0
	b	secondary_start_kernel

	.type	__secondary_data, %object
__secondary_data:
	.long	.
	.long	secondary_data
	.long	__secondary_switched
#endif /* defined(CONFIG_SMP) */



/*
+1 −1
Original line number Diff line number Diff line
@@ -328,7 +328,7 @@ static void __init setup_processor(void)
 * cpu_init dumps the cache information, initialises SMP specific
 * information, and sets up the per-CPU stacks.
 */
void __init cpu_init(void)
void cpu_init(void)
{
	unsigned int cpu = smp_processor_id();
	struct stack *stk = &stacks[cpu];
+107 −0
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@
#include <asm/atomic.h>
#include <asm/cacheflush.h>
#include <asm/cpu.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
@@ -36,6 +39,13 @@
cpumask_t cpu_present_mask;
cpumask_t cpu_online_map;

/*
 * as from 2.5, kernels no longer have an init_tasks structure
 * so we need some other way of telling a new secondary core
 * where to place its SVC stack
 */
struct secondary_data secondary_data;

/*
 * structures for inter-processor calls
 * - A collection of single bit ipi messages.
@@ -71,6 +81,8 @@ static DEFINE_SPINLOCK(smp_call_function_lock);
int __init __cpu_up(unsigned int cpu)
{
	struct task_struct *idle;
	pgd_t *pgd;
	pmd_t *pmd;
	int ret;

	/*
@@ -83,10 +95,55 @@ int __init __cpu_up(unsigned int cpu)
		return PTR_ERR(idle);
	}

	/*
	 * Allocate initial page tables to allow the new CPU to
	 * enable the MMU safely.  This essentially means a set
	 * of our "standard" page tables, with the addition of
	 * a 1:1 mapping for the physical address of the kernel.
	 */
	pgd = pgd_alloc(&init_mm);
	pmd = pmd_offset(pgd, PHYS_OFFSET);
	*pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
		     PMD_TYPE_SECT | PMD_SECT_AP_WRITE);

	/*
	 * We need to tell the secondary core where to find
	 * its stack and the page tables.
	 */
	secondary_data.stack = (void *)idle->thread_info + THREAD_SIZE - 8;
	secondary_data.pgdir = virt_to_phys(pgd);
	wmb();

	/*
	 * Now bring the CPU into our world.
	 */
	ret = boot_secondary(cpu, idle);
	if (ret == 0) {
		unsigned long timeout;

		/*
		 * CPU was successfully started, wait for it
		 * to come online or time out.
		 */
		timeout = jiffies + HZ;
		while (time_before(jiffies, timeout)) {
			if (cpu_online(cpu))
				break;

			udelay(10);
			barrier();
		}

		if (!cpu_online(cpu))
			ret = -EIO;
	}

	secondary_data.stack = 0;
	secondary_data.pgdir = 0;

	*pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
	pgd_free(pgd);

	if (ret) {
		printk(KERN_CRIT "cpu_up: processor %d failed to boot\n", cpu);
		/*
@@ -97,6 +154,56 @@ int __init __cpu_up(unsigned int cpu)
	return ret;
}

/*
 * This is the secondary CPU boot entry.  We're using this CPUs
 * idle thread stack, but a set of temporary page tables.
 */
asmlinkage void __init secondary_start_kernel(void)
{
	struct mm_struct *mm = &init_mm;
	unsigned int cpu = smp_processor_id();

	printk("CPU%u: Booted secondary processor\n", cpu);

	/*
	 * All kernel threads share the same mm context; grab a
	 * reference and switch to it.
	 */
	atomic_inc(&mm->mm_users);
	atomic_inc(&mm->mm_count);
	current->active_mm = mm;
	cpu_set(cpu, mm->cpu_vm_mask);
	cpu_switch_mm(mm->pgd, mm);
	enter_lazy_tlb(mm, current);

	cpu_init();

	/*
	 * Give the platform a chance to do its own initialisation.
	 */
	platform_secondary_init(cpu);

	/*
	 * Enable local interrupts.
	 */
	local_irq_enable();
	local_fiq_enable();

	calibrate_delay();

	smp_store_cpu_info(cpu);

	/*
	 * OK, now it's safe to let the boot CPU continue
	 */
	cpu_set(cpu, cpu_online_map);

	/*
	 * OK, it's off to the idle thread for us
	 */
	cpu_idle();
}

/*
 * Called by both boot and secondaries to move global data into
 * per-processor storage.
+1 −0
Original line number Diff line number Diff line
@@ -12,3 +12,4 @@ obj-$(CONFIG_LEDS) += leds.o
obj-$(CONFIG_PCI)			+= pci_v3.o pci.o
obj-$(CONFIG_CPU_FREQ_INTEGRATOR)	+= cpu.o
obj-$(CONFIG_INTEGRATOR_IMPD1)		+= impd1.o
obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
+19 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/smp.h>

#include <asm/hardware.h>
#include <asm/irq.h>
@@ -221,7 +222,24 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
	 */
	timer1->TimerClear = 1;

	/*
	 * the clock tick routines are only processed on the
	 * primary CPU
	 */
	if (hard_smp_processor_id() == 0) {
		nmi_tick();
		timer_tick(regs);
#ifdef CONFIG_SMP
		smp_send_timer();
#endif
	}

#ifdef CONFIG_SMP
	/*
	 * this is the ARM equivalent of the APIC timer interrupt
	 */
	update_process_times(user_mode(regs));
#endif /* CONFIG_SMP */

	write_sequnlock(&xtime_lock);

Loading