void __init smp_prepare_cpus(unsigned int max_cpus) { int num_cpus, i; /* Fixup boot cpu */ smp_store_cpu_info(smp_processor_id()); cpu_callin_map[smp_processor_id()] = 1; smp_ops = ppc_md.smp_ops; if (smp_ops == NULL) { printk("SMP not supported on this machine.\n"); return; } /* Probe platform for CPUs: always linear. */ num_cpus = smp_ops->probe(); for (i = 0; i < num_cpus; ++i) cpu_set(i, cpu_possible_map); /* Backup CPU 0 state */ __save_cpu_setup(); if (smp_ops->space_timers) smp_ops->space_timers(num_cpus); }
void __init smp_boot_cpus(void) { extern struct task_struct *current_set[NR_CPUS]; int i, cpu_nr; struct task_struct *p; printk("Entering SMP Mode...\n"); smp_num_cpus = 1; smp_store_cpu_info(0); cpu_online_map = 1UL; /* * assume for now that the first cpu booted is * cpu 0, the master -- Cort */ cpu_callin_map[0] = 1; current->processor = 0; for (i = 0; i < NR_CPUS; i++) { prof_counter[i] = 1; prof_multiplier[i] = 1; } /* * XXX very rough, assumes 20 bus cycles to read a cache line, * timebase increments every 4 bus cycles, 32kB L1 data cache. */ cacheflush_time = 5 * 1024; smp_ops = ppc_md.smp_ops; if (smp_ops == NULL) { printk("SMP not supported on this machine.\n"); return; } #ifndef CONFIG_750_SMP /* check for 750's, they just don't work with linux SMP. * If you actually have 750 SMP hardware and want to try to get * it to work, send me a patch to make it work and * I'll make CONFIG_750_SMP a config option. -- Troy ([email protected]) */ if ( PVR_VER(mfspr(PVR)) == 8 ){ printk("SMP not supported on 750 cpus. %s line %d\n", __FILE__, __LINE__); return; } #endif /* Probe arch for CPUs */ cpu_nr = smp_ops->probe(); /* Backup CPU 0 state */ __save_cpu_setup(); /* * only check for cpus we know exist. We keep the callin map * with cpus at the bottom -- Cort */ if (cpu_nr > max_cpus) cpu_nr = max_cpus; for (i = 1; i < cpu_nr; i++) { int c; struct pt_regs regs; /* create a process for the processor */ /* only regs.msr is actually used, and 0 is OK for it */ memset(®s, 0, sizeof(struct pt_regs)); if (do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0) < 0) panic("failed fork for CPU %d", i); p = init_task.prev_task; if (!p) panic("No idle task for CPU %d", i); init_idle(p, i); unhash_process(p); init_tasks[i] = p; p->processor = i; p->cpus_runnable = 1 << i; /* we schedule the first task manually */ current_set[i] = p; /* * There was a cache flush loop here to flush the cache * to memory for the first 8MB of RAM. The cache flush * has been pushed into the kick_cpu function for those * platforms that need it. */ /* wake up cpus */ smp_ops->kick_cpu(i); /* * wait to see if the cpu made a callin (is actually up). * use this value that I found through experimentation. * -- Cort */ for ( c = 10000; c && !cpu_callin_map[i] ; c-- ) udelay(100); if ( cpu_callin_map[i] ) { char buf[32]; sprintf(buf, "found cpu %d", i); if (ppc_md.progress) ppc_md.progress(buf, 0x350+i); printk("Processor %d found.\n", i); smp_num_cpus++; } else { char buf[32]; sprintf(buf, "didn't find cpu %d", i); if (ppc_md.progress) ppc_md.progress(buf, 0x360+i); printk("Processor %d is stuck.\n", i); } } /* Setup CPU 0 last (important) */ smp_ops->setup_cpu(0); if (smp_num_cpus < 2) smp_tb_synchronized = 1; }