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

📄 s390mach.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
字号:
/* *  arch/s390/kernel/s390mach.c *   S/390 machine check handler, *            currently only channel-reports are supported * *  S390 version *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation *    Author(s): Ingo Adlung (adlung@de.ibm.com) */#include <linux/config.h>#include <linux/spinlock.h>#include <linux/init.h>#include <linux/slab.h>#ifdef CONFIG_SMP#include <linux/smp.h>#endif#include <asm/irq.h>#include <asm/lowcore.h>#include <asm/semaphore.h>#include <asm/s390io.h>#include <asm/s390dyn.h>#include <asm/s390mach.h>#define S390_MACHCHK_DEBUGstatic int         s390_machine_check_handler( void * parm );static void        s390_enqueue_mchchk( mache_t *mchchk );static mache_t    *s390_dequeue_mchchk( void );static void        s390_enqueue_free_mchchk( mache_t *mchchk );static mache_t    *s390_dequeue_free_mchchk( void );static int         s390_collect_crw_info( void );static mache_t    *mchchk_queue_head = NULL;static mache_t    *mchchk_queue_tail = NULL;static mache_t    *mchchk_queue_free = NULL;static crwe_t     *crw_buffer_anchor = NULL;static spinlock_t  mchchk_queue_lock = SPIN_LOCK_UNLOCKED;static spinlock_t  crw_queue_lock    = SPIN_LOCK_UNLOCKED;static struct semaphore s_sem;/* * s390_init_machine_check * * initialize machine check handling */void s390_init_machine_check( void ){	crwe_t  *pcrwe;	 /* CRW buffer element pointer */	mache_t *pmache;   /* machine check element pointer */	init_MUTEX_LOCKED( &s_sem );	pcrwe = kmalloc( MAX_CRW_PENDING * sizeof( crwe_t), GFP_KERNEL);	if ( pcrwe )	{		int i;		crw_buffer_anchor = pcrwe;		for ( i=0; i < MAX_CRW_PENDING-1; i++)		{			pcrwe->crwe_next = (crwe_t *)((unsigned long)pcrwe + sizeof(crwe_t));   		pcrwe            = pcrwe->crwe_next;		} /* endfor */			pcrwe->crwe_next = NULL;	}	else	{		panic( "s390_init_machine_check : unable to obtain memory\n");			} /* endif */	pmache = kmalloc( MAX_MACH_PENDING * sizeof( mache_t), GFP_KERNEL);	if ( pmache )	{		int i;		for ( i=0; i < MAX_MACH_PENDING; i++)		{			s390_enqueue_free_mchchk( pmache );		   pmache = (mache_t *)((unsigned long)pmache + sizeof(mache_t));		} /* endfor */		}	else	{		panic( "s390_init_machine_check : unable to obtain memory\n");			} /* endif */#ifdef S390_MACHCHK_DEBUG	printk( "init_mach : starting machine check handler\n");#endif		kernel_thread( s390_machine_check_handler, &s_sem, CLONE_FS | CLONE_FILES);	ctl_clear_bit( 14, 25 );  // disable damage MCH 	#if 1  	ctl_set_bit( 14, 28 );		// enable channel report MCH#endif#ifdef S390_MACHCHK_DEBUG	printk( "init_mach : machine check buffer : head = %08X\n",            (unsigned)&mchchk_queue_head);	printk( "init_mach : machine check buffer : tail = %08X\n",            (unsigned)&mchchk_queue_tail);	printk( "init_mach : machine check buffer : free = %08X\n",            (unsigned)&mchchk_queue_free);	printk( "init_mach : CRW entry buffer anchor = %08X\n",            (unsigned)&crw_buffer_anchor);	printk( "init_mach : machine check handler ready\n");#endif		return;}/* * s390_do_machine_check * * mchine check pre-processor, collecting the machine check info, *  queueing it and posting the machine check handler for processing. */void s390_do_machine_check( void ){	int      crw_count;	mcic_t   mcic;#ifdef S390_MACHCHK_DEBUG	printk( "s390_do_machine_check : starting ...\n");#endif	memcpy( &mcic,	        &S390_lowcore.mcck_interruption_code,	        sizeof(__u64)); 			if ( mcic.mcc.mcd.cp )	// CRW pending ?	{		crw_count = s390_collect_crw_info();		if ( crw_count )		{			up( &s_sem );		} /* endif */	} /* endif */#ifdef S390_MACHCHK_DEBUG	printk( "s390_do_machine_check : done \n");#endif	return;}/* * s390_machine_check_handler * * machine check handler, dequeueing machine check entries *  and processing them */static int s390_machine_check_handler( void *parm){	struct semaphore *sem = parm;	unsigned long     flags;	mache_t          *pmache;	int               found = 0;        /* set name to something sensible */        strcpy (current->comm, "kmcheck");        /* block all signals */        sigfillset(&current->blocked);#ifdef S390_MACHCHK_DEBUG	printk( "mach_handler : ready\n");#endif		do {#ifdef S390_MACHCHK_DEBUG		printk( "mach_handler : waiting for wakeup\n");#endif			down_interruptible( sem );#ifdef S390_MACHCHK_DEBUG		printk( "\nmach_handler : wakeup ... \n");#endif			found = 0; /* init ... */		__save_flags( flags );		__cli();		do {		pmache = s390_dequeue_mchchk();		if ( pmache )		{			found = 1;					if ( pmache->mcic.mcc.mcd.cp )			{				crwe_t *pcrwe_n;				crwe_t *pcrwe_h;				s390_do_crw_pending( pmache->mc.crwe );				pcrwe_h = pmache->mc.crwe;				pcrwe_n = pmache->mc.crwe->crwe_next;				pmache->mcic.mcc.mcd.cp = 0;				pmache->mc.crwe         = NULL;				spin_lock( &crw_queue_lock);				while ( pcrwe_h )				{					pcrwe_h->crwe_next = crw_buffer_anchor;					crw_buffer_anchor  = pcrwe_h;					pcrwe_h            = pcrwe_n;					if ( pcrwe_h != NULL )						pcrwe_n = pcrwe_h->crwe_next;				} /* endwhile */				spin_unlock( &crw_queue_lock);			} /* endif */			s390_enqueue_free_mchchk( pmache );		}		else		{			// unconditional surrender ...#ifdef S390_MACHCHK_DEBUG			printk( "mach_handler : nothing to do, sleeping\n");#endif			} /* endif */			} while ( pmache );		__restore_flags( flags );	} while ( 1 );	return( 0);}/* * s390_dequeue_mchchk * * Dequeue an entry from the machine check queue * * Note : The queue elements provide for a double linked list. *  We dequeue entries from the tail, and enqueue entries to *  the head. * */static mache_t *s390_dequeue_mchchk( void ){	mache_t *qe;	spin_lock( &mchchk_queue_lock );	qe = mchchk_queue_tail;   if ( qe != NULL )   {      mchchk_queue_tail = qe->prev;      if ( mchchk_queue_tail != NULL )      {			mchchk_queue_tail->next = NULL;		}		else      {			mchchk_queue_head = NULL;      } /* endif */	} /* endif */	spin_unlock( &mchchk_queue_lock );	return qe;}/* * s390_enqueue_mchchk * * Enqueue an entry to the machine check queue. * * Note : The queue elements provide for a double linked list. *  We enqueue entries to the head, and dequeue entries from *  the tail. * */static void s390_enqueue_mchchk( mache_t *pmache ){	spin_lock( &mchchk_queue_lock );	if ( pmache != NULL )	{		if ( mchchk_queue_head == NULL )  /* first element */		{  			pmache->next      = NULL;  			pmache->prev      = NULL;			mchchk_queue_head = pmache;			mchchk_queue_tail = pmache;		}		else /* new head */		{  			pmache->prev            = NULL;			pmache->next            = mchchk_queue_head;			mchchk_queue_head->prev = pmache;			mchchk_queue_head       = pmache;		} /* endif */	} /* endif */	spin_unlock( &mchchk_queue_lock );	return;}/* * s390_enqueue_free_mchchk * * Enqueue a free entry to the free queue. * * Note : While the queue elements provide for a double linked list, *  the free queue entries are only concatenated by means of a *  single linked list (forward concatenation). * */static void s390_enqueue_free_mchchk( mache_t *pmache ){	if ( pmache != NULL)	{		memset( pmache, '\0', sizeof( mache_t ));		spin_lock( &mchchk_queue_lock );				pmache->next = mchchk_queue_free;		mchchk_queue_free = pmache;		spin_unlock( &mchchk_queue_lock );	} /* endif */	return;}/* * s390_dequeue_free_mchchk * * Dequeue an entry from the free queue. * * Note : While the queue elements provide for a double linked list, *  the free queue entries are only concatenated by means of a *  single linked list (forward concatenation). * */static mache_t *s390_dequeue_free_mchchk( void ){	mache_t *qe;	spin_lock( &mchchk_queue_lock );	qe = mchchk_queue_free;	if ( qe != NULL )	{		mchchk_queue_free = qe->next;	} /* endif */	spin_unlock( &mchchk_queue_lock );	return qe;}/* * s390_collect_crw_info * * Retrieve CRWs. If a CRW was found a machine check element *  is dequeued from the free chain, filled and enqueued to *  be processed. * * The function returns the number of CRWs found. * * Note : We must always be called disabled ... */static int s390_collect_crw_info( void ){	crw_t    tcrw;     /* temporarily holds a CRW */	int      ccode;    /* condition code from stcrw() */	crwe_t  *pcrwe;    /* pointer to CRW buffer entry */	mache_t *pmache = NULL; /* ptr to mchchk entry */	int      chain  = 0;    /* indicate chaining */	crwe_t  *pccrw  = NULL; /* ptr to current CRW buffer entry */	int      count  = 0;    /* CRW count */#ifdef S390_MACHCHK_DEBUG	printk( "crw_info : looking for CRWs ...\n");#endif	do	{		ccode = stcrw( (__u32 *)&tcrw);		if ( ccode == 0 )		{			count++;			#ifdef S390_MACHCHK_DEBUG			printk( "crw_info : CRW reports "			        "slct=%d, oflw=%d, chn=%d, "			        "rsc=%X, anc=%d, erc=%X, "			        "rsid=%X\n",			        tcrw.slct,			        tcrw.oflw,			        tcrw.chn,			        tcrw.rsc,			        tcrw.anc,			        tcrw.erc,			        tcrw.rsid );#endif			/*			 * Dequeue a CRW entry from the free chain			 *  and process it ...			 */			spin_lock( &crw_queue_lock );			pcrwe = crw_buffer_anchor;			if ( pcrwe == NULL )			{				spin_unlock( &crw_queue_lock );				printk( KERN_CRIT"crw_info : "				        "no CRW buffer entries available\n");				break;			} /* endif */						crw_buffer_anchor = pcrwe->crwe_next;			pcrwe->crwe_next  = NULL;			spin_unlock( &crw_queue_lock );			memcpy( &(pcrwe->crw), &tcrw, sizeof(crw_t));			/*			 * If it is the first CRW, chain it to the mchchk			 *  buffer entry, otherwise to the last CRW entry.			 */			if ( chain == 0 )			{				pmache = s390_dequeue_free_mchchk();				if ( pmache != NULL )				{					memset( pmache, '\0', sizeof(mache_t));					pmache->mcic.mcc.mcd.cp = 1;					pmache->mc.crwe         = pcrwe;					pccrw                   = pcrwe;				}				else				{					panic( "crw_info : "					       "unable to dequeue "					       "free mchchk buffer");								} /* endif */			}			else			{				pccrw->crwe_next = pcrwe;				pccrw            = pcrwe;			} /* endif */				if ( pccrw->crw.chn )			{#ifdef S390_MACHCHK_DEBUG				printk( "crw_info : "				        "chained CRWs pending ...\n\n");#endif				chain = 1;			}			else			{				chain = 0;				/*				 * We can enqueue the mchchk buffer if				 *  there aren't more CRWs chained.				 */				s390_enqueue_mchchk( pmache);			} /* endif */		} /* endif */	} while ( ccode == 0 );	return( count );}

⌨️ 快捷键说明

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