X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fsparc%2Fkernel%2Fsun4d_smp.c;h=3ff4edd32815ca842c5ccd03d4e6909d094f938c;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=e5e1349035707706cfb99db48a9888fb42f0976b;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index e5e134903..3ff4edd32 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -42,20 +42,15 @@ extern ctxd_t *srmmu_ctx_table_phys; extern void calibrate_delay(void); -extern volatile int smp_processors_ready; -extern unsigned long cpu_present_map; -extern int smp_num_cpus; +static volatile int smp_processors_ready = 0; static int smp_highest_cpu; -extern int smp_threads_ready; extern volatile unsigned long cpu_callin_map[NR_CPUS]; -extern struct cpuinfo_sparc cpu_data[NR_CPUS]; +extern cpuinfo_sparc cpu_data[NR_CPUS]; extern unsigned char boot_cpu_id; -extern int smp_activated; -extern volatile int __cpu_number_map[NR_CPUS]; -extern volatile int __cpu_logical_map[NR_CPUS]; -extern volatile unsigned long ipi_count; extern volatile int smp_process_available; -extern volatile int smp_commenced; + +extern cpumask_t smp_commenced_mask; + extern int __smp4d_processor_id(void); /* #define SMP_DEBUG */ @@ -100,8 +95,6 @@ void __init smp4d_callin(void) * the SMP initialization the master will be just allowed * to call the scheduler code. */ - init_idle(); - /* Get our local ticker going. */ smp_setup_percpu_timer(); @@ -125,8 +118,7 @@ void __init smp4d_callin(void) /* Fix idle thread fields. */ __asm__ __volatile__("ld [%0], %%g6\n\t" - "sta %%g6, [%%g0] %1\n\t" - : : "r" (¤t_set[cpuid]), "i" (ASI_M_VIKING_TMP2) + : : "r" (¤t_set[cpuid]) : "memory" /* paranoid */); cpu_leds[cpuid] = 0x9; @@ -141,18 +133,18 @@ void __init smp4d_callin(void) local_irq_enable(); /* We don't allow PIL 14 yet */ - while(!smp_commenced) + while (!cpu_isset(cpuid, smp_commenced_mask)) barrier(); spin_lock_irqsave(&sun4d_imsk_lock, flags); cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */ spin_unlock_irqrestore(&sun4d_imsk_lock, flags); + cpu_set(cpuid, cpu_online_map); + } -extern int cpu_idle(void *unused); extern void init_IRQ(void); extern void cpu_panic(void); -extern int start_secondary(void *unused); /* * Cycle through the processors asking the PROM to start each one. @@ -165,60 +157,24 @@ extern unsigned long trapbase_cpu3[]; void __init smp4d_boot_cpus(void) { - int cpucount = 0; - int i, mid; - - printk("Entering SMP Mode...\n"); - if (boot_cpu_id) current_set[0] = NULL; - - local_irq_enable(); - cpu_present_map = 0; - - /* XXX This whole thing has to go. See sparc64. */ - for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) - cpu_present_map |= (1<cpu = boot_cpu_id; - smp_store_cpu_info(boot_cpu_id); smp_setup_percpu_timer(); local_flush_cache_all(); - if (cpu_find_by_instance(1, NULL, NULL)) - return; /* Not an MP box. */ - SMP_PRINTK(("Iterating over CPUs\n")); - for(i = 0; i < NR_CPUS; i++) { - if(i == boot_cpu_id) - continue; - - if(cpu_present_map & (1 << i)) { +} + +int smp4d_boot_one_cpu(int i) +{ extern unsigned long sun4d_cpu_startup; unsigned long *entry = &sun4d_cpu_startup; struct task_struct *p; int timeout; - int no; + int cpu_node; + cpu_find_by_instance(i, &cpu_node,NULL); /* Cook up an idler for this guy. */ - kernel_thread(start_secondary, NULL, CLONE_IDLETASK); - - cpucount++; - - p = prev_task(&init_task); - - init_idle(p, i); - - current_set[i] = p->thread_info; - - unhash_process(p); - - for (no = 0; !cpu_find_by_instance(no, NULL, &mid) - && mid != i; no++) ; + p = fork_idle(i); + current_set[i] = task_thread_info(p); /* * Initialize the contexts table @@ -230,9 +186,9 @@ void __init smp4d_boot_cpus(void) smp_penguin_ctable.reg_size = 0; /* whirrr, whirrr, whirrrrrrrrr... */ - SMP_PRINTK(("Starting CPU %d at %p task %d node %08x\n", i, entry, cpucount, cpu_data(no).prom_node)); + SMP_PRINTK(("Starting CPU %d at %p \n", i, entry)); local_flush_cache_all(); - prom_startcpu(cpu_data(no).prom_node, + prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry); SMP_PRINTK(("prom_startcpu returned :)\n")); @@ -244,57 +200,46 @@ void __init smp4d_boot_cpus(void) udelay(200); } - if(cpu_callin_map[i]) { - /* Another "Red Snapper". */ - __cpu_number_map[i] = cpucount; - __cpu_logical_map[cpucount] = i; - } else { - cpucount--; - printk("Processor %d is stuck.\n", i); - } - } - if(!(cpu_callin_map[i])) { - cpu_present_map &= ~(1 << i); - __cpu_number_map[i] = -1; - } + if (!(cpu_callin_map[i])) { + printk("Processor %d is stuck.\n", i); + return -ENODEV; + } local_flush_cache_all(); - if(cpucount == 0) { - printk("Error: only one Processor found.\n"); - cpu_present_map = (1 << hard_smp4d_processor_id()); - } else { - unsigned long bogosum = 0; - - for(i = 0; i < NR_CPUS; i++) { - if(cpu_present_map & (1 << i)) { - bogosum += cpu_data(i).udelay_val; - smp_highest_cpu = i; - } + return 0; +} + +void __init smp4d_smp_done(void) +{ + int i, first; + int *prev; + + /* setup cpu list for irq rotation */ + first = 0; + prev = &first; + for (i = 0; i < NR_CPUS; i++) + if (cpu_online(i)) { + *prev = i; + prev = &cpu_data(i).next; } - SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100)); - printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", - cpucount + 1, - bogosum/(500000/HZ), - (bogosum/(5000/HZ))%100); - smp_activated = 1; - smp_num_cpus = cpucount + 1; - } + *prev = first; + local_flush_cache_all(); /* Free unneeded trap tables */ ClearPageReserved(virt_to_page(trapbase_cpu1)); - set_page_count(virt_to_page(trapbase_cpu1), 1); + init_page_count(virt_to_page(trapbase_cpu1)); free_page((unsigned long)trapbase_cpu1); totalram_pages++; num_physpages++; ClearPageReserved(virt_to_page(trapbase_cpu2)); - set_page_count(virt_to_page(trapbase_cpu2), 1); + init_page_count(virt_to_page(trapbase_cpu2)); free_page((unsigned long)trapbase_cpu2); totalram_pages++; num_physpages++; ClearPageReserved(virt_to_page(trapbase_cpu3)); - set_page_count(virt_to_page(trapbase_cpu3), 1); + init_page_count(virt_to_page(trapbase_cpu3)); free_page((unsigned long)trapbase_cpu3); totalram_pages++; num_physpages++; @@ -315,7 +260,7 @@ static struct smp_funcall { unsigned char processors_out[NR_CPUS]; /* Set when ipi exited. */ } ccall_info __attribute__((aligned(8))); -static spinlock_t cross_call_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(cross_call_lock); /* Cross calls must be serialized, at least currently. */ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, @@ -346,12 +291,13 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, /* Init receive/complete mapping, plus fire the IPI's off. */ { - register unsigned long mask; + cpumask_t mask; register int i; - mask = (cpu_present_map & ~(1 << hard_smp4d_processor_id())); + mask = cpumask_of_cpu(hard_smp4d_processor_id()); + cpus_andnot(mask, cpu_online_map, mask); for(i = 0; i <= high; i++) { - if(mask & (1 << i)) { + if (cpu_isset(i, mask)) { ccall_info.processors_in[i] = 0; ccall_info.processors_out[i] = 0; sun4d_send_ipi(i, IRQ_CROSS_CALL); @@ -411,7 +357,7 @@ void smp4d_message_pass(int target, int msg, unsigned long data, int wait) SMP_PRINTK(("smp4d_message_pass %d %d %08lx %d\n", target, msg, data, wait)); if (msg == MSG_STOP_CPU && target == MSG_ALL_BUT_SELF) { unsigned long flags; - static spinlock_t stop_cpu_lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(stop_cpu_lock); spin_lock_irqsave(&stop_cpu_lock, flags); smp4d_stop_cpu_sender = me; smp4d_cross_call((smpfunc_t)smp4d_stop_cpu, 0, 0, 0, 0, 0); @@ -421,8 +367,6 @@ void smp4d_message_pass(int target, int msg, unsigned long data, int wait) panic("Bogon SMP message pass."); } -extern void sparc_do_profile(unsigned long pc, unsigned long o7); - void smp4d_percpu_timer_interrupt(struct pt_regs *regs) { int cpu = hard_smp4d_processor_id(); @@ -440,8 +384,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) show_leds(cpu); } - if(!user_mode(regs)) - sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]); + profile_tick(CPU_PROFILING, regs); if(!--prof_counter(cpu)) { int user = user_mode(regs); @@ -475,34 +418,27 @@ void __init smp4d_blackbox_id(unsigned *addr) void __init smp4d_blackbox_current(unsigned *addr) { - /* We have a nice Linux current register :) */ - int rd = addr[1] & 0x3e000000; + int rd = *addr & 0x3e000000; - addr[0] = 0x10800006; /* b .+24 */ - addr[1] = 0xc0800820 | rd; /* lda [%g0] ASI_M_VIKING_TMP2, reg */ + addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */ + addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */ + addr[4] = 0x01000000; /* nop */ } void __init sun4d_init_smp(void) { int i; - extern unsigned int patchme_store_new_current[]; extern unsigned int t_nmi[], linux_trap_ipi15_sun4d[], linux_trap_ipi15_sun4m[]; - /* Store current into Linux current register :) */ - __asm__ __volatile__("sta %%g6, [%%g0] %0" : : "i"(ASI_M_VIKING_TMP2)); - - /* Patch switch_to */ - patchme_store_new_current[0] = (patchme_store_new_current[0] & 0x3e000000) | 0xc0a00820; - /* Patch ipi15 trap table */ t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); /* And set btfixup... */ - BTFIXUPSET_BLACKBOX(smp_processor_id, smp4d_blackbox_id); + BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id); BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(smp_message_pass, smp4d_message_pass, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); for (i = 0; i < NR_CPUS; i++) { ccall_info.processors_in[i] = 1;