Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+442 -3
+44
arch/arm/kernel/head.S
··· 2 2 * linux/arch/arm/kernel/head.S 3 3 * 4 4 * Copyright (C) 1994-2002 Russell King 5 + * Copyright (c) 2003 ARM Limited 6 + * All Rights Reserved 5 7 * 6 8 * This program is free software; you can redistribute it and/or modify 7 9 * it under the terms of the GNU General Public License version 2 as ··· 166 164 bic r4, r0, #CR_A @ Clear 'A' bit 167 165 stmia r6, {r0, r4} @ Save control register values 168 166 b start_kernel 167 + 168 + #if defined(CONFIG_SMP) 169 + .type secondary_startup, #function 170 + ENTRY(secondary_startup) 171 + /* 172 + * Common entry point for secondary CPUs. 173 + * 174 + * Ensure that we're in SVC mode, and IRQs are disabled. Lookup 175 + * the processor type - there is no need to check the machine type 176 + * as it has already been validated by the primary processor. 177 + */ 178 + msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC 179 + bl __lookup_processor_type 180 + movs r10, r5 @ invalid processor? 181 + moveq r0, #'p' @ yes, error 'p' 182 + beq __error 183 + 184 + /* 185 + * Use the page tables supplied from __cpu_up. 186 + */ 187 + adr r4, __secondary_data 188 + ldmia r4, {r5, r6, r13} @ address to jump to after 189 + sub r4, r4, r5 @ mmu has been enabled 190 + ldr r4, [r6, r4] @ get secondary_data.pgdir 191 + adr lr, __enable_mmu @ return address 192 + add pc, r10, #12 @ initialise processor 193 + @ (return control reg) 194 + 195 + /* 196 + * r6 = &secondary_data 197 + */ 198 + ENTRY(__secondary_switched) 199 + ldr sp, [r6, #4] @ get secondary_data.stack 200 + mov fp, #0 201 + b secondary_start_kernel 202 + 203 + .type __secondary_data, %object 204 + __secondary_data: 205 + .long . 206 + .long secondary_data 207 + .long __secondary_switched 208 + #endif /* defined(CONFIG_SMP) */ 169 209 170 210 171 211
+1 -1
arch/arm/kernel/setup.c
··· 328 328 * cpu_init dumps the cache information, initialises SMP specific 329 329 * information, and sets up the per-CPU stacks. 330 330 */ 331 - void __init cpu_init(void) 331 + void cpu_init(void) 332 332 { 333 333 unsigned int cpu = smp_processor_id(); 334 334 struct stack *stk = &stacks[cpu];
+107
arch/arm/kernel/smp.c
··· 24 24 #include <asm/atomic.h> 25 25 #include <asm/cacheflush.h> 26 26 #include <asm/cpu.h> 27 + #include <asm/mmu_context.h> 28 + #include <asm/pgtable.h> 29 + #include <asm/pgalloc.h> 27 30 #include <asm/processor.h> 28 31 #include <asm/tlbflush.h> 29 32 #include <asm/ptrace.h> ··· 38 35 */ 39 36 cpumask_t cpu_present_mask; 40 37 cpumask_t cpu_online_map; 38 + 39 + /* 40 + * as from 2.5, kernels no longer have an init_tasks structure 41 + * so we need some other way of telling a new secondary core 42 + * where to place its SVC stack 43 + */ 44 + struct secondary_data secondary_data; 41 45 42 46 /* 43 47 * structures for inter-processor calls ··· 81 71 int __init __cpu_up(unsigned int cpu) 82 72 { 83 73 struct task_struct *idle; 74 + pgd_t *pgd; 75 + pmd_t *pmd; 84 76 int ret; 85 77 86 78 /* ··· 96 84 } 97 85 98 86 /* 87 + * Allocate initial page tables to allow the new CPU to 88 + * enable the MMU safely. This essentially means a set 89 + * of our "standard" page tables, with the addition of 90 + * a 1:1 mapping for the physical address of the kernel. 91 + */ 92 + pgd = pgd_alloc(&init_mm); 93 + pmd = pmd_offset(pgd, PHYS_OFFSET); 94 + *pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) | 95 + PMD_TYPE_SECT | PMD_SECT_AP_WRITE); 96 + 97 + /* 98 + * We need to tell the secondary core where to find 99 + * its stack and the page tables. 100 + */ 101 + secondary_data.stack = (void *)idle->thread_info + THREAD_SIZE - 8; 102 + secondary_data.pgdir = virt_to_phys(pgd); 103 + wmb(); 104 + 105 + /* 99 106 * Now bring the CPU into our world. 100 107 */ 101 108 ret = boot_secondary(cpu, idle); 109 + if (ret == 0) { 110 + unsigned long timeout; 111 + 112 + /* 113 + * CPU was successfully started, wait for it 114 + * to come online or time out. 115 + */ 116 + timeout = jiffies + HZ; 117 + while (time_before(jiffies, timeout)) { 118 + if (cpu_online(cpu)) 119 + break; 120 + 121 + udelay(10); 122 + barrier(); 123 + } 124 + 125 + if (!cpu_online(cpu)) 126 + ret = -EIO; 127 + } 128 + 129 + secondary_data.stack = 0; 130 + secondary_data.pgdir = 0; 131 + 132 + *pmd_offset(pgd, PHYS_OFFSET) = __pmd(0); 133 + pgd_free(pgd); 134 + 102 135 if (ret) { 103 136 printk(KERN_CRIT "cpu_up: processor %d failed to boot\n", cpu); 104 137 /* ··· 152 95 } 153 96 154 97 return ret; 98 + } 99 + 100 + /* 101 + * This is the secondary CPU boot entry. We're using this CPUs 102 + * idle thread stack, but a set of temporary page tables. 103 + */ 104 + asmlinkage void __init secondary_start_kernel(void) 105 + { 106 + struct mm_struct *mm = &init_mm; 107 + unsigned int cpu = smp_processor_id(); 108 + 109 + printk("CPU%u: Booted secondary processor\n", cpu); 110 + 111 + /* 112 + * All kernel threads share the same mm context; grab a 113 + * reference and switch to it. 114 + */ 115 + atomic_inc(&mm->mm_users); 116 + atomic_inc(&mm->mm_count); 117 + current->active_mm = mm; 118 + cpu_set(cpu, mm->cpu_vm_mask); 119 + cpu_switch_mm(mm->pgd, mm); 120 + enter_lazy_tlb(mm, current); 121 + 122 + cpu_init(); 123 + 124 + /* 125 + * Give the platform a chance to do its own initialisation. 126 + */ 127 + platform_secondary_init(cpu); 128 + 129 + /* 130 + * Enable local interrupts. 131 + */ 132 + local_irq_enable(); 133 + local_fiq_enable(); 134 + 135 + calibrate_delay(); 136 + 137 + smp_store_cpu_info(cpu); 138 + 139 + /* 140 + * OK, now it's safe to let the boot CPU continue 141 + */ 142 + cpu_set(cpu, cpu_online_map); 143 + 144 + /* 145 + * OK, it's off to the idle thread for us 146 + */ 147 + cpu_idle(); 155 148 } 156 149 157 150 /*
+1
arch/arm/mach-integrator/Makefile
··· 12 12 obj-$(CONFIG_PCI) += pci_v3.o pci.o 13 13 obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o 14 14 obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o 15 + obj-$(CONFIG_SMP) += platsmp.o headsmp.o
+19 -1
arch/arm/mach-integrator/core.c
··· 14 14 #include <linux/spinlock.h> 15 15 #include <linux/interrupt.h> 16 16 #include <linux/sched.h> 17 + #include <linux/smp.h> 17 18 18 19 #include <asm/hardware.h> 19 20 #include <asm/irq.h> ··· 222 221 */ 223 222 timer1->TimerClear = 1; 224 223 225 - timer_tick(regs); 224 + /* 225 + * the clock tick routines are only processed on the 226 + * primary CPU 227 + */ 228 + if (hard_smp_processor_id() == 0) { 229 + nmi_tick(); 230 + timer_tick(regs); 231 + #ifdef CONFIG_SMP 232 + smp_send_timer(); 233 + #endif 234 + } 235 + 236 + #ifdef CONFIG_SMP 237 + /* 238 + * this is the ARM equivalent of the APIC timer interrupt 239 + */ 240 + update_process_times(user_mode(regs)); 241 + #endif /* CONFIG_SMP */ 226 242 227 243 write_sequnlock(&xtime_lock); 228 244
+37
arch/arm/mach-integrator/headsmp.S
··· 1 + /* 2 + * linux/arch/arm/mach-integrator/headsmp.S 3 + * 4 + * Copyright (c) 2003 ARM Limited 5 + * All Rights Reserved 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + #include <linux/linkage.h> 12 + #include <linux/init.h> 13 + 14 + __INIT 15 + 16 + /* 17 + * Integrator specific entry point for secondary CPUs. This provides 18 + * a "holding pen" into which all secondary cores are held until we're 19 + * ready for them to initialise. 20 + */ 21 + ENTRY(integrator_secondary_startup) 22 + adr r4, 1f 23 + ldmia r4, {r5, r6} 24 + sub r4, r4, r5 25 + ldr r6, [r6, r4] 26 + pen: ldr r7, [r6] 27 + cmp r7, r0 28 + bne pen 29 + 30 + /* 31 + * we've been released from the holding pen: secondary_stack 32 + * should now contain the SVC stack for this core 33 + */ 34 + b secondary_startup 35 + 36 + 1: .long . 37 + .long phys_pen_release
+3 -1
arch/arm/mach-integrator/leds.c
··· 22 22 */ 23 23 #include <linux/kernel.h> 24 24 #include <linux/init.h> 25 + #include <linux/smp.h> 26 + #include <linux/spinlock.h> 25 27 26 28 #include <asm/hardware.h> 27 29 #include <asm/io.h> ··· 87 85 return 0; 88 86 } 89 87 90 - __initcall(leds_init); 88 + core_initcall(leds_init);
+192
arch/arm/mach-integrator/platsmp.c
··· 1 + /* 2 + * linux/arch/arm/mach-cintegrator/platsmp.c 3 + * 4 + * Copyright (C) 2002 ARM Ltd. 5 + * All Rights Reserved 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + #include <linux/init.h> 12 + #include <linux/kernel.h> 13 + #include <linux/sched.h> 14 + #include <linux/errno.h> 15 + #include <linux/mm.h> 16 + 17 + #include <asm/atomic.h> 18 + #include <asm/delay.h> 19 + #include <asm/mmu_context.h> 20 + #include <asm/procinfo.h> 21 + #include <asm/ptrace.h> 22 + #include <asm/smp.h> 23 + 24 + extern void integrator_secondary_startup(void); 25 + 26 + /* 27 + * control for which core is the next to come out of the secondary 28 + * boot "holding pen" 29 + */ 30 + volatile int __initdata pen_release = -1; 31 + unsigned long __initdata phys_pen_release = 0; 32 + 33 + static DEFINE_SPINLOCK(boot_lock); 34 + 35 + void __init platform_secondary_init(unsigned int cpu) 36 + { 37 + /* 38 + * the primary core may have used a "cross call" soft interrupt 39 + * to get this processor out of WFI in the BootMonitor - make 40 + * sure that we are no longer being sent this soft interrupt 41 + */ 42 + smp_cross_call_done(cpumask_of_cpu(cpu)); 43 + 44 + /* 45 + * if any interrupts are already enabled for the primary 46 + * core (e.g. timer irq), then they will not have been enabled 47 + * for us: do so 48 + */ 49 + secondary_scan_irqs(); 50 + 51 + /* 52 + * let the primary processor know we're out of the 53 + * pen, then head off into the C entry point 54 + */ 55 + pen_release = -1; 56 + 57 + /* 58 + * Synchronise with the boot thread. 59 + */ 60 + spin_lock(&boot_lock); 61 + spin_unlock(&boot_lock); 62 + } 63 + 64 + int __init boot_secondary(unsigned int cpu, struct task_struct *idle) 65 + { 66 + unsigned long timeout; 67 + 68 + /* 69 + * set synchronisation state between this boot processor 70 + * and the secondary one 71 + */ 72 + spin_lock(&boot_lock); 73 + 74 + /* 75 + * The secondary processor is waiting to be released from 76 + * the holding pen - release it, then wait for it to flag 77 + * that it has been released by resetting pen_release. 78 + * 79 + * Note that "pen_release" is the hardware CPU ID, whereas 80 + * "cpu" is Linux's internal ID. 81 + */ 82 + pen_release = cpu; 83 + 84 + /* 85 + * XXX 86 + * 87 + * This is a later addition to the booting protocol: the 88 + * bootMonitor now puts secondary cores into WFI, so 89 + * poke_milo() no longer gets the cores moving; we need 90 + * to send a soft interrupt to wake the secondary core. 91 + * Use smp_cross_call() for this, since there's little 92 + * point duplicating the code here 93 + */ 94 + smp_cross_call(cpumask_of_cpu(cpu)); 95 + 96 + timeout = jiffies + (1 * HZ); 97 + while (time_before(jiffies, timeout)) { 98 + if (pen_release == -1) 99 + break; 100 + 101 + udelay(10); 102 + } 103 + 104 + /* 105 + * now the secondary core is starting up let it run its 106 + * calibrations, then wait for it to finish 107 + */ 108 + spin_unlock(&boot_lock); 109 + 110 + return pen_release != -1 ? -ENOSYS : 0; 111 + } 112 + 113 + static void __init poke_milo(void) 114 + { 115 + extern void secondary_startup(void); 116 + 117 + /* nobody is to be released from the pen yet */ 118 + pen_release = -1; 119 + 120 + phys_pen_release = virt_to_phys(&pen_release); 121 + 122 + /* 123 + * write the address of secondary startup into the system-wide 124 + * flags register, then clear the bottom two bits, which is what 125 + * BootMonitor is waiting for 126 + */ 127 + #if 1 128 + #define CINTEGRATOR_HDR_FLAGSS_OFFSET 0x30 129 + __raw_writel(virt_to_phys(integrator_secondary_startup), 130 + (IO_ADDRESS(INTEGRATOR_HDR_BASE) + 131 + CINTEGRATOR_HDR_FLAGSS_OFFSET)); 132 + #define CINTEGRATOR_HDR_FLAGSC_OFFSET 0x34 133 + __raw_writel(3, 134 + (IO_ADDRESS(INTEGRATOR_HDR_BASE) + 135 + CINTEGRATOR_HDR_FLAGSC_OFFSET)); 136 + #endif 137 + 138 + mb(); 139 + } 140 + 141 + void __init smp_prepare_cpus(unsigned int max_cpus) 142 + { 143 + unsigned int ncores = get_core_count(); 144 + unsigned int cpu = smp_processor_id(); 145 + int i; 146 + 147 + /* sanity check */ 148 + if (ncores == 0) { 149 + printk(KERN_ERR 150 + "Integrator/CP: strange CM count of 0? Default to 1\n"); 151 + 152 + ncores = 1; 153 + } 154 + 155 + if (ncores > NR_CPUS) { 156 + printk(KERN_WARNING 157 + "Integrator/CP: no. of cores (%d) greater than configured " 158 + "maximum of %d - clipping\n", 159 + ncores, NR_CPUS); 160 + ncores = NR_CPUS; 161 + } 162 + 163 + /* 164 + * start with some more config for the Boot CPU, now that 165 + * the world is a bit more alive (which was not the case 166 + * when smp_prepare_boot_cpu() was called) 167 + */ 168 + smp_store_cpu_info(cpu); 169 + 170 + /* 171 + * are we trying to boot more cores than exist? 172 + */ 173 + if (max_cpus > ncores) 174 + max_cpus = ncores; 175 + 176 + /* 177 + * Initialise the present mask - this tells us which CPUs should 178 + * be present. 179 + */ 180 + for (i = 0; i < max_cpus; i++) { 181 + cpu_set(i, cpu_present_mask); 182 + } 183 + 184 + /* 185 + * Do we need any more CPUs? If so, then let them know where 186 + * to start. Note that, on modern versions of MILO, the "poke" 187 + * doesn't actually do anything until each individual core is 188 + * sent a soft interrupt to get it out of WFI 189 + */ 190 + if (max_cpus > 1) 191 + poke_milo(); 192 + }
+2
arch/arm/mach-pxa/pm.c
··· 133 133 /* *** go zzz *** */ 134 134 pxa_cpu_pm_enter(state); 135 135 136 + cpu_init(); 137 + 136 138 /* after sleeping, validate the checksum */ 137 139 checksum = 0; 138 140 for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
+2
arch/arm/mach-sa1100/pm.c
··· 88 88 /* go zzz */ 89 89 sa1100_cpu_suspend(); 90 90 91 + cpu_init(); 92 + 91 93 /* 92 94 * Ensure not to come back here if it wasn't intended 93 95 */
+19
include/asm-arm/arch-integrator/smp.h
··· 1 + #ifndef ASMARM_ARCH_SMP_H 2 + #define ASMARM_ARCH_SMP_H 3 + 4 + #include <linux/config.h> 5 + 6 + #include <asm/arch/hardware.h> 7 + #include <asm/io.h> 8 + 9 + #define hard_smp_processor_id() \ 10 + ({ \ 11 + unsigned int cpunum; \ 12 + __asm__("mrc p15, 0, %0, c0, c0, 5" \ 13 + : "=r" (cpunum)); \ 14 + cpunum &= 0x0F; \ 15 + }) 16 + 17 + extern void secondary_scan_irqs(void); 18 + 19 + #endif
+14
include/asm-arm/smp.h
··· 55 55 */ 56 56 extern int boot_secondary(unsigned int cpu, struct task_struct *); 57 57 58 + /* 59 + * Perform platform specific initialisation of the specified CPU. 60 + */ 61 + extern void platform_secondary_init(unsigned int cpu); 62 + 63 + /* 64 + * Initial data for bringing up a secondary CPU. 65 + */ 66 + struct secondary_data { 67 + unsigned long pgdir; 68 + void *stack; 69 + }; 70 + extern struct secondary_data secondary_data; 71 + 58 72 #endif /* ifndef __ASM_ARM_SMP_H */
+1
include/asm-arm/system.h
··· 104 104 extern void __show_regs(struct pt_regs *); 105 105 106 106 extern int cpu_architecture(void); 107 + extern void cpu_init(void); 107 108 108 109 #define set_cr(x) \ 109 110 __asm__ __volatile__( \