⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smp.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	(*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, &regs, 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 + -