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

📄 smp.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  * * SMP support for ppc. * * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great * deal of code from the sparc and intel versions. * * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu> * * PowerPC-64 Support added by Dave Engebretsen, Peter Bergner, and * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com * *      This program is free software; you can redistribute it and/or *      modify it under the terms of the GNU General Public License *      as published by the Free Software Foundation; either version *      2 of the License, or (at your option) any later version. */#include <linux/config.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/interrupt.h>#include <linux/kernel_stat.h>#include <linux/delay.h>#define __KERNEL_SYSCALLS__#include <linux/unistd.h>#include <linux/init.h>/* #include <linux/openpic.h> */#include <linux/spinlock.h>#include <linux/cache.h>#include <asm/ptrace.h>#include <asm/atomic.h>#include <asm/irq.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/hardirq.h>#include <asm/softirq.h>#include <asm/init.h>#include <asm/io.h>#include <asm/prom.h>#include <asm/smp.h>#include <asm/naca.h>#include <asm/paca.h>#include <asm/iSeries/LparData.h>#include <asm/iSeries/HvCall.h>#include <asm/iSeries/HvCallCfg.h>#include <asm/time.h>#include <asm/ppcdebug.h>#include "open_pic.h"#include <asm/machdep.h>int smp_threads_ready = 0;volatile int smp_commenced = 0;int smp_num_cpus = 1;int smp_tb_synchronized = 0;extern atomic_t ipi_recv;extern atomic_t ipi_sent;spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED;cycles_t cacheflush_time;static int max_cpus __initdata = NR_CPUS;unsigned long cpu_online_map;volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};#define TB_SYNC_PASSES 4volatile unsigned long __initdata tb_sync_flag = 0;volatile unsigned long __initdata tb_offset = 0;extern unsigned char stab_array[];int start_secondary(void *);extern int cpu_idle(void *unused);void smp_call_function_interrupt(void);void smp_message_pass(int target, int msg, unsigned long data, int wait);static unsigned long iSeries_smp_message[NR_CPUS];void xics_setup_cpu(void);void xics_cause_IPI(int cpu);/* * XICS only has a single IPI, so encode the messages per CPU */volatile unsigned long xics_ipi_message[NR_CPUS] = {0};#define smp_message_pass(t,m,d,w) \    do {     atomic_inc(&ipi_sent); \	     ppc_md.smp_message_pass((t),(m),(d),(w)); \       } while(0)#ifdef CONFIG_KDBvoid smp_kdb_stop(void){}#endifstatic inline void set_tb(unsigned int upper, unsigned int lower){	mtspr(SPRN_TBWL, 0);	mtspr(SPRN_TBWU, upper);	mtspr(SPRN_TBWL, lower);}void iSeries_smp_message_recv( struct pt_regs * regs ){	int cpu = smp_processor_id();	int msg;	if ( smp_num_cpus < 2 )		return;	for ( msg = 0; msg < 4; ++msg )		if ( test_and_clear_bit( msg, &iSeries_smp_message[cpu] ) )			smp_message_recv( msg, regs );}static void smp_iSeries_message_pass(int target, int msg, unsigned long data, int wait){	int i;	for (i = 0; i < smp_num_cpus; ++i) {		if ( (target == MSG_ALL) ||                     (target == i) ||                     ((target == MSG_ALL_BUT_SELF) && (i != smp_processor_id())) ) {			set_bit( msg, &iSeries_smp_message[i] );			HvCall_sendIPI(&(paca[i]));		}	}}static int smp_iSeries_numProcs(void){	unsigned np, i;	struct ItLpPaca * lpPaca;	np = 0;        for (i=0; i < MAX_PACAS; ++i) {                lpPaca = paca[i].xLpPacaPtr;                if ( lpPaca->xDynProcStatus < 2 ) {                        ++np;                }        }	return np;}static int smp_iSeries_probe(void){	unsigned i;	unsigned np;	struct ItLpPaca * lpPaca;	np = 0;	for (i=0; i < MAX_PACAS; ++i) {		lpPaca = paca[i].xLpPacaPtr;		if ( lpPaca->xDynProcStatus < 2 ) {			++np;			paca[i].next_jiffy_update_tb = paca[0].next_jiffy_update_tb;		}	}		smp_tb_synchronized = 1;	return np;}static void smp_iSeries_kick_cpu(int nr){	struct ItLpPaca * lpPaca;	/* Verify we have a Paca for processor nr */	if ( ( nr <= 0 ) ||	     ( nr >= MAX_PACAS ) )		return;	/* Verify that our partition has a processor nr */	lpPaca = paca[nr].xLpPacaPtr;	if ( lpPaca->xDynProcStatus >= 2 )		return;	/* The information for processor bringup must	 * be written out to main store before we release	 * the processor.	 */	mb();	/* The processor is currently spinning, waiting	 * for the xProcStart field to become non-zero	 * After we set xProcStart, the processor will	 * continue on to secondary_start in iSeries_head.S	 */	paca[nr].xProcStart = 1;}static void smp_iSeries_setup_cpu(int nr){}/* This is called very early. */void smp_init_iSeries(void){	ppc_md.smp_message_pass = smp_iSeries_message_pass;	ppc_md.smp_probe        = smp_iSeries_probe;	ppc_md.smp_kick_cpu     = smp_iSeries_kick_cpu;	ppc_md.smp_setup_cpu    = smp_iSeries_setup_cpu;	naca->processorCount	= smp_iSeries_numProcs();}static voidsmp_openpic_message_pass(int target, int msg, unsigned long data, int wait){	/* make sure we're sending something that translates to an IPI */	if ( msg > 0x3 ){		printk("SMP %d: smp_message_pass: unknown msg %d\n",		       smp_processor_id(), msg);		return;	}	switch ( target )	{	case MSG_ALL:		openpic_cause_IPI(msg, 0xffffffff);		break;	case MSG_ALL_BUT_SELF:		openpic_cause_IPI(msg,				  0xffffffff & ~(1 << smp_processor_id()));		break;	default:		openpic_cause_IPI(msg, 1<<target);		break;	}}static intsmp_chrp_probe(void){	if (naca->processorCount > 1)		openpic_request_IPIs();	return naca->processorCount;}static voidsmp_kick_cpu(int nr){	/* Verify we have a Paca for processor nr */	if ( ( nr <= 0 ) ||	     ( nr >= MAX_PACAS ) )		return;	/* The information for processor bringup must	 * be written out to main store before we release	 * the processor.	 */	mb();	/* The processor is currently spinning, waiting	 * for the xProcStart field to become non-zero	 * After we set xProcStart, the processor will	 * continue on to secondary_start in iSeries_head.S	 */	paca[nr].xProcStart = 1;}extern struct gettimeofday_struct do_gtod;static void smp_space_timers( unsigned nr ){	unsigned long offset, i;		offset = tb_ticks_per_jiffy / nr;	for ( i=1; i<nr; ++i ) {		paca[i].next_jiffy_update_tb = paca[i-1].next_jiffy_update_tb + offset;	}}static voidsmp_chrp_setup_cpu(int cpu_nr){	static atomic_t ready = ATOMIC_INIT(1);	static volatile int frozen = 0;	if (naca->platform == PLATFORM_PSERIES_LPAR) {		/* timebases already synced under the hypervisor. */		paca[cpu_nr].next_jiffy_update_tb = tb_last_stamp = get_tb();		if (cpu_nr == 0) {			do_gtod.tb_orig_stamp = tb_last_stamp;			/* Should update do_gtod.stamp_xsec.			 * For now we leave it which means the time can be some			 * number of msecs off until someone does a settimeofday()			 */		}		smp_tb_synchronized = 1;	} else {		if (cpu_nr == 0) {			/* wait for all the others */			while (atomic_read(&ready) < smp_num_cpus)				barrier();			atomic_set(&ready, 1);			/* freeze the timebase */			rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);			mb();			frozen = 1;			set_tb(0, 0);			paca[0].next_jiffy_update_tb = 0;			smp_space_timers(smp_num_cpus);			while (atomic_read(&ready) < smp_num_cpus)				barrier();			/* thaw the timebase again */			rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);			mb();			frozen = 0;			tb_last_stamp = get_tb();			do_gtod.tb_orig_stamp = tb_last_stamp;			smp_tb_synchronized = 1;		} else {			atomic_inc(&ready);			while (!frozen)				barrier();			set_tb(0, 0);			mb();			atomic_inc(&ready);			while (frozen)				barrier();		}	}	if (OpenPIC_Addr) {		do_openpic_setup_cpu();	} else {	  if (cpu_nr > 0)	    xics_setup_cpu();	}}static voidsmp_xics_message_pass(int target, int msg, unsigned long data, int wait){	int i;	for (i = 0; i < smp_num_cpus; ++i) {		if (target == MSG_ALL || target == i		    || (target == MSG_ALL_BUT_SELF			&& i != smp_processor_id())) {			set_bit(msg, &xics_ipi_message[i]);			mb();			xics_cause_IPI(i);			}	}}static intsmp_xics_probe(void){	return naca->processorCount;}/* This is called very early */void smp_init_pSeries(void){	if(naca->interrupt_controller == IC_OPEN_PIC) {		ppc_md.smp_message_pass = smp_openpic_message_pass;		ppc_md.smp_probe        = smp_chrp_probe;		ppc_md.smp_kick_cpu     = smp_kick_cpu;		ppc_md.smp_setup_cpu    = smp_chrp_setup_cpu;	} else {		ppc_md.smp_message_pass = smp_xics_message_pass;		ppc_md.smp_probe        = smp_xics_probe;		ppc_md.smp_kick_cpu     = smp_kick_cpu;		ppc_md.smp_setup_cpu    = smp_chrp_setup_cpu;	}}void smp_local_timer_interrupt(struct pt_regs * regs){	if (!--(get_paca()->prof_counter)) {		update_process_times(user_mode(regs));		(get_paca()->prof_counter)=get_paca()->prof_multiplier;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -