📄 smp.c
字号:
(*func)(info); if (wait) atomic_inc(&call_data->finished);}void smp_message_pass(int target, int msg, unsigned long data, int wait){ if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep|_MACH_gemini)) ) return; switch (_machine) { case _MACH_Pmac: /* * IPI's on the Pmac are a hack but without reasonable * IPI hardware SMP on Pmac is a hack. * * We assume here that the msg is not -1. If it is, * the recipient won't know the message was destined * for it. -- Cort */ if (smp_processor_id() == 0) { /* primary cpu */ if (target == 1 || target == MSG_ALL_BUT_SELF || target == MSG_ALL) { pmac_smp_message[1] = msg + 1; /* interrupt secondary processor */ out_be32(psurge_sec_intr, ~0); out_be32(psurge_sec_intr, 0); } } else { /* secondary cpu */ if (target == 0 || target == MSG_ALL_BUT_SELF || target == MSG_ALL) { pmac_smp_message[0] = msg + 1; /* interrupt primary processor */ in_be32(psurge_pri_intr); } } if (target == smp_processor_id() || target == MSG_ALL) { /* sending a message to ourself */ /* XXX maybe we shouldn't do this if ints are off */ smp_message_recv(msg, NULL); } break; case _MACH_chrp: case _MACH_prep: case _MACH_gemini:#ifndef CONFIG_POWER4 /* make sure we're sending something that translates to an IPI */ if ( msg > 0x3 ) break; switch ( target ) { case MSG_ALL: openpic_cause_IPI(smp_processor_id(), msg, 0xffffffff); break; case MSG_ALL_BUT_SELF: openpic_cause_IPI(smp_processor_id(), msg, 0xffffffff & ~(1 << smp_processor_id())); break; default: openpic_cause_IPI(smp_processor_id(), msg, 1<<target); break; }#else /* CONFIG_POWER4 */ /* for now, only do reschedule messages since we only have one IPI */ if (msg != PPC_MSG_RESCHEDULE) break; for (i = 0; i < smp_num_cpus; ++i) { if (target == MSG_ALL || target == i || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())) xics_cause_IPI(i); }#endif /* CONFIG_POWER4 */ break; }}void __init smp_boot_cpus(void){ extern struct task_struct *current_set[NR_CPUS]; extern unsigned long smp_chrp_cpu_nr; extern void __secondary_start_psurge(void); extern void __secondary_start_chrp(void); int i, cpu_nr; struct task_struct *p; unsigned long a; printk("Entering SMP Mode...\n"); smp_num_cpus = 1; smp_store_cpu_info(0); /* * assume for now that the first cpu booted is * cpu 0, the master -- Cort */ cpu_callin_map[0] = 1; active_kernel_processor = 0; current->processor = 0; init_idle(); 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; if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_gemini)) ) { printk("SMP not supported on this machine.\n"); return; } switch ( _machine ) { case _MACH_Pmac: /* assume powersurge board - 2 processors -- Cort */ cpu_nr = 2; psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); psurge_sec_intr = ioremap(PSURGE_SEC_INTR, 4); psurge_start = ioremap(PSURGE_START, 4); break; case _MACH_chrp: if (OpenPIC) for ( i = 0; i < 4 ; i++ ) openpic_enable_IPI(i); cpu_nr = smp_chrp_cpu_nr; break; case _MACH_gemini: for ( i = 0; i < 4 ; i++ ) openpic_enable_IPI(i); cpu_nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK)>>2; cpu_nr = (cpu_nr == 0) ? 4 : cpu_nr; break; } /* * only check for cpus we know exist. We keep the callin map * with cpus at the bottom -- Cort */ for ( i = 1 ; i < cpu_nr; i++ ) { int c; struct pt_regs regs; /* create a process for the processor */ /* we don't care about the values in regs since we'll never reschedule the forked task. */ 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); del_from_runqueue(p); unhash_process(p); init_tasks[i] = p; p->processor = i; p->has_cpu = 1; current_set[i] = p; /* need to flush here since secondary bats aren't setup */ for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) asm volatile("dcbf 0,%0" : : "r" (a) : "memory"); asm volatile("sync"); /* wake up cpus */ switch ( _machine ) { case _MACH_Pmac: /* setup entry point of secondary processor */ out_be32(psurge_start, __pa(__secondary_start_psurge)); /* interrupt secondary to begin executing code */ out_be32(psurge_sec_intr, ~0); udelay(1); out_be32(psurge_sec_intr, 0); break; case _MACH_chrp: *(unsigned long *)KERNELBASE = i; asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); break; case _MACH_gemini: openpic_init_processor( 1<<i ); openpic_init_processor( 0 ); break; } /* * wait to see if the cpu made a callin (is actually up). * use this value that I found through experimentation. * -- Cort */ for ( c = 1000; c && !cpu_callin_map[i] ; c-- ) udelay(100); if ( cpu_callin_map[i] ) { printk("Processor %d found.\n", i); smp_num_cpus++; } else { printk("Processor %d is stuck.\n", i); } } if (OpenPIC && (_machine & (_MACH_gemini|_MACH_chrp|_MACH_prep))) do_openpic_setup_cpu(); if ( _machine == _MACH_Pmac ) { /* reset the entry point so if we get another intr we won't * try to startup again */ out_be32(psurge_start, 0x100); if (request_irq(30, pmac_primary_intr, 0, "primary IPI", 0)) printk(KERN_ERR "Couldn't get primary IPI interrupt"); /* * The decrementers of both cpus are frozen at this point * until we give the secondary cpu another interrupt. * We set them both to decrementer_count and then send * the interrupt. This should get the decrementers * synchronized. * -- paulus. */ set_dec(tb_ticks_per_jiffy); if ((_get_PVR() >> 16) != 1) { set_tb(0, 0); /* set timebase if not 601 */ last_jiffy_stamp(0) = 0; } out_be32(psurge_sec_intr, ~0); udelay(1); out_be32(psurge_sec_intr, 0); }}void __init smp_commence(void){ /* * Lets the callin's below out of their loop. */ wmb(); smp_commenced = 1;}/* intel needs this */void __init initialize_secondary(void){}/* Activate a secondary processor. */int __init start_secondary(void *unused){ atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; smp_callin(); return cpu_idle(NULL);}void __init smp_callin(void){ smp_store_cpu_info(current->processor); set_dec(tb_ticks_per_jiffy); if (_machine == _MACH_Pmac && (_get_PVR() >> 16) != 1) { set_tb(0, 0); /* set timebase if not 601 */ last_jiffy_stamp(current->processor) = 0; } init_idle(); cpu_callin_map[current->processor] = 1;#ifndef CONFIG_POWER4 /* * Each processor has to do this and this is the best * place to stick it for now. * -- Cort */ if (OpenPIC && _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep)) do_openpic_setup_cpu();#else xics_setup_cpu();#endif /* CONFIG_POWER4 */#ifdef CONFIG_GEMINI if ( _machine == _MACH_gemini ) gemini_init_l2();#endif while(!smp_commenced) barrier(); __sti();}void __init smp_setup(char *str, int *ints){}int __init setup_profiling_timer(unsigned int multiplier){ return 0;}void __init smp_store_cpu_info(int id){ struct cpuinfo_PPC *c = &cpu_data[id]; /* assume bogomips are same for everything */ c->loops_per_sec = loops_per_sec; c->pvr = _get_PVR();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -