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

📄 excmgr.c

📁 T-kernel 的extension源代码
💻 C
字号:
/* *---------------------------------------------------------------------- *    T-Kernel / Standard Extension * *    Copyright (C) 2006 by Ken Sakamura. All rights reserved. *    T-Kernel / Standard Extension is distributed  *      under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * *    Version:   1.00.00 *    Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* *	excmgr.c (memory) * *	System exception handling (ARM Virtual storage version) */#include "segmgr.h"#include <sys/sysexc.h>#include <tm/tmonitor.h>#include <sys/bdm.h>IMPORT	void	_ExitTask( PINFO *pi, ID tskid );  /* proc/prcmgr.c */#define	BMS_KILL_PROC	SWI_KILLPROC	/* Process forced termination request from monitor *//* Message to system exception handling task */typedef struct {	BDM_ExcInfo	i;		/* Exception information */	unsigned int	pgfault:1;	/* Page fault: TRUE */	unsigned int	killproc:1;	/* Process forced termination request: TRUE */} ExcMsg;Inline UW getFSR( void );Inline void setFSR( UW fsr );Inline UW getFAR( void );Inline void setFAR( UW far );Inline BOOL TaskIndependent( void );LOCAL void print_regs( ID tid );LOCAL ER sendExcMsg( ExcMsg *msg );LOCAL void recvExcMsg( ExcMsg *msg );LOCAL void SysExcTsk( void );LOCAL ER RegistPageFaultHdr( void );/* Message buffer for communicating with system exception handling task */#define	MaxExcMsg	64ULOCAL	ExcMsg	ExcMsg_buf[MaxExcMsg];LOCAL	UW	ExcMsg_top, ExcMsg_cnt;LOCAL	ID	SysExcTskID;		/* System exception handling task */EXPORT	FP	DefaultHandlerEntry;	/* Monitor default handler */#define TSD_PFH_VAL_M1		(-1)#define TSD_HDR_VAL_3		3#define TSD_IEM_STK_2048	2048/* * Read/set fault status register (FSR) */Inline UW getFSR( void ){	UW	fsr;	Asm("mrc p15, 0, %0, cr5, c0": "=r"(fsr));	return fsr;}Inline void setFSR( UW fsr ){	Asm("mcr p15, 0, %0, cr5, c0":: "r"(fsr));}/* * Read/set fault address register (FAR) */Inline UW getFAR( void ){	UW	far;	Asm("mrc p15, 0, %0, cr6, c0": "=r"(far));	return far;}Inline void setFAR( UW far ){	Asm("mcr p15, 0, %0, cr6, c0":: "r"(far));}/* * Exception occurred in the task-independent section: TRUE */Inline BOOL TaskIndependent( void ){	return ( SCInfo.taskindp > 1 )? TRUE: FALSE;}/* * Indicate task register value */LOCAL void print_regs( ID tid ){#if DEBUGFUNC_SUPPORT	T_REGS	g;	T_EIT	e;	T_CREGS	c;	ER	er;	er = tk_get_reg(tid, &g, &e, &c);	if ( er < E_OK ) {		BMS_DEBUG_PRINT(("- register can not read -\n"));		return;	}	PrintTaskRegister(bms_printf, &g, &e, &c);#endif /* DEBUGFUNC_SUPPORT */}/* * Send exception message *	Called in interrupt-disabled state */LOCAL ER sendExcMsg( ExcMsg *msg ){	UW	pos;	if ( ExcMsg_cnt >= (UW)MaxExcMsg ) {		return E_LIMIT;	}	pos = (UW)((ExcMsg_top + ExcMsg_cnt) % (UW)MaxExcMsg);	ExcMsg_buf[pos] = *msg;	if ( ExcMsg_cnt++ == 0U ) {		tk_wup_tsk(SysExcTskID);	}	return E_OK;}/* * Receive exception message */LOCAL void recvExcMsg( ExcMsg *msg ){	UINT	imask;	for ( ;; ) {		DI(imask);		if ( ExcMsg_cnt > 0U ) {			*msg = ExcMsg_buf[ExcMsg_top];			if ( ++ExcMsg_top >= (UW)MaxExcMsg ) {				ExcMsg_top = 0U;			}			ExcMsg_cnt--;			break;		}		EI(imask);		tk_slp_tsk(TMO_FEVR);	}	EI(imask);}/* * System exception handling task */LOCAL void SysExcTsk( void ){IMPORT	WER	_snd_hdr_msg( MESSAGE *msg, W opt );	/* Message management */	ExcMsg	excmsg;	PINFO	*pinfo;	ID	oldrid;	EXCMESG	msg;	ER	er;	for ( ;; ) {	/* Not terminate on its own */		/* Receive system exception */		recvExcMsg(&excmsg);		if ( excmsg.pgfault != 0U ) {			/* Handle page fault */			UW lsid = GetLSID_tid(excmsg.i.taskid);			LockSEG();			er = PageIn((VP)excmsg.i.excaddr, lsid);			UnlockSEG();			if ( er >= E_OK ) {				/* Reopen intended task */				er = tk_frsm_tsk(excmsg.i.taskid);				if ( er >= E_OK ) {					continue;				}			}			DEBUG_PRINT(("SysExcTsk PageIn err = %d\n", er));		}		/* Obtain PINFO on exception occurrence process. */		pinfo = GetPinfo(excmsg.i.taskid);		if ( pinfo == NULL ) {			goto system_down;		}		/* If the task is in the course of termination processing,		   call task termination processing directly from process management. */		if ( pinfo->exitkind != 0 ) {			oldrid = tk_set_rid(TSK_SELF, pinfo->resid);			_ExitTask(pinfo, excmsg.i.taskid);			tk_set_rid(TSK_SELF, oldrid);			continue;		}		if ( excmsg.killproc != 0U ) {			goto kill_proc;		}		/* Send message */		msg.type = MS_SYS1;		msg.size = (W)sizeof(EXCMESG) - (W)offsetof(EXCMESG, taskid);		msg.taskid = excmsg.i.taskid;		msg.procid = pinfo->procid;		msg.vecno   = excmsg.i.vecno;		msg.excinfo = excmsg.i.excinfo;		msg.excaddr = excmsg.i.excaddr;		/* Send to exception server */		er = _snd_hdr_msg((MESSAGE*)&msg, NOWAIT);		if ( er <= 0 ) {			DEBUG_PRINT(("SysExcTsk _snd_hdr_msg err = %d\n", er));kill_proc:			/* If message could not be sent to exception server,			   forcedly terminate the process. */			tk_ras_tex(excmsg.i.taskid, 0);			if ( excmsg.i.taskid != pinfo->tsk[0].tskid ) {				/* Terminate main task as well. */				tk_ras_tex(pinfo->tsk[0].tskid, 0);			}			pinfo->exitkind = MS_ABORT;			tk_frsm_tsk(excmsg.i.taskid);		}	}system_down:	/* Use monitor to output message */	BMS_DEBUG_PRINT(("\n***** OS SYSTEM DOWN *****\n"));	BMS_DEBUG_PRINT(("INT:%d FSR:%08x FAR:%08x tid:%d\n",		excmsg.i.vecno, excmsg.i.excinfo, excmsg.i.excaddr,		excmsg.i.taskid));	print_regs(excmsg.i.taskid);	tm_monitor();	/* to monitor */}/* * System exception handler */EXPORT void SysExcHdr( W vecno, ExcStack *sp ){	ExcMsg	excmsg;	PINFO	*pinfo;	ER	er;	memset(&excmsg, 0, (size_t)sizeof(excmsg));	if ( vecno == -BMS_KILL_PROC ) {		vecno = -vecno;		excmsg.killproc = TRUE;	}	excmsg.i.vecno   = (UW)vecno;	excmsg.i.excinfo = getFSR();	excmsg.i.excaddr = getFAR();	excmsg.pgfault = FALSE;	EI(0);	/* Multiplex interrupt enabled */	/* Obtain intended task ID */	excmsg.i.taskid = tk_get_tid();	if ( excmsg.i.taskid <= 0 ) {		goto system_down;	}	/* If an exception occurs during the execution of interrupt handler (task independent	   section) or in the interrupt-disabled state, shut down the system. */	if ( ((sp->spsr & (UW)(PSR_I|PSR_F)) != 0U)	  || TaskIndependent() ) {		goto system_down;	}	/* Notify BDM of the exception. */	er = BDM_NotifyException(&excmsg.i);	if ( er == E_OK ) {		return;	}	/* If BDM does not exist, continue exception handling. */	/* If an exception occurs during the execution of a task (extension, SVC, non-process,	   etc.) within OS, shut down the system. */	if ( ((SCInfo.taskmode & (UW)TMF_PPL(TSD_HDR_VAL_3)) == (UW)TMF_PPL(0))	  || ((pinfo = GetPinfo(excmsg.i.taskid)) == NULL) ) {		goto system_down;	}	/* If the current task is a system process that is in the course of termination	   processing, shut down the system. */	if ( (pinfo->exitkind != 0)	  && ((SCInfo.taskmode & (UW)TMF_PPL(TSD_HDR_VAL_3)) < (UW)TMF_PPL(TSD_HDR_VAL_3)) ) {		goto system_down;	}	/* Suspend current task */	er = tk_sus_tsk(excmsg.i.taskid);	if ( er < E_OK ) {		goto system_down;	}	/* Notify to exception handling task */	er = sendExcMsg(&excmsg);	if ( er < E_OK ) {		goto system_down;	}	return;	/** Use monitor to indicate message **/system_down:	BMS_DEBUG_PRINT(("\n***** OS SYSTEM DOWN *****\n"));	BMS_DEBUG_PRINT(("INT:%d PC:%08x CPSR:%08x FSR:%08x FAR:%08x tid:%d\n",		vecno, sp->lr, sp->spsr,		excmsg.i.excinfo, excmsg.i.excaddr, excmsg.i.taskid));	tm_monitor();	/* To monitor */}/* * Page fault handler *	EIT_IABORT	Prefetch abort *	EIT_DABORT	Data abort */EXPORT W PageFaultHdr( UW vecno, ExcStack *sp ){IMPORT	W	DebugMonitorFlag;	/* debug.c */	UW	excinfo, excaddr;	PTH	pth;	PTE	pte;	ER	er;	DO_DEBUG( pte.w = TSD_PFH_VAL_M1; )	if ( vecno == EIT_DABORT ) {		excinfo = getFSR();		excaddr = getFAR();	} else {		excinfo = 0;		excaddr = sp->lr;	}	EI(0);	/* Multiplex interrupt enabled */	InitPTH(&pth, (VP)excaddr, 0);	er = NextPTE(&pth);	if ( er < E_OK ) {		goto exception;		/* Invalid access */	}	pte.w = GetPTE(&pth);	if ( pte.w == PTE_NONE ) {		goto exception;	/* Invalid access */	}	if ( vecno == EIT_IABORT ) {		/* Set exception information for prefetch abort */		if ( (pte.c.u == 0)		  && ((SCInfo.taskmode & (UW)TMF_PPL(TSD_HDR_VAL_3)) == (UW)TMF_PPL(TSD_HDR_VAL_3)) ) {			excinfo = FSR_Permission | FSR_Page;		} else {			excinfo = FSR_Translation | FSR_Page;		}	}	/* Except for page absent exception, handle all exceptions as invalid access. */	if ( (excinfo & (UW)FSR_TypeMask) != (UW)FSR_Translation ) {		goto exception;	}	if ( (pte.c.p == 0) && (pte.c.va != 0) && (SegLock.cnt < 0) ) {		/* Since the page is valid, make page frame settings only.		 * However, if LockSEG() cannot be handled here,		 * pass it to an exception handling task.		 */		PFE *pfe = PFAtoPFE(pte.c.pfa);		MovePageFrame(pfe, PFS_use);		(void)ChgPTE(&pth, PT_Present, ~PT_Present, TRUE);	} else {		ExcMsg	excmsg;		ID	tid;		/* Obtain intended task ID */		tid = er = tk_get_tid();		if ( er < E_OK ) {			goto exception;		}		memset(&excmsg, 0, (size_t)sizeof(excmsg));		excmsg.i.taskid  = tid;		excmsg.i.vecno   = vecno;		excmsg.i.excinfo = excinfo;		excmsg.i.excaddr = excaddr;		excmsg.pgfault = TRUE;		/* Handle it as exception if it occurred while a task independent section is executed or interrupt is disabled. */		if ( ((sp->spsr & ((UW)PSR_I|(UW)PSR_F)) != 0U)		  || TaskIndependent() ) {			goto exception;		}		/* Suspend current task */		er = tk_sus_tsk(tid);		if ( er < E_OK ) {			goto exception;		}		/* Notify to exception handling task */		er = sendExcMsg(&excmsg);		if ( er < E_OK ) {			BMS_DEBUG_PRINT(("\nPageFaultHdr sendExcMsg er = %d\n", er));			goto exception;		}	}	EndPTH(&pth, FALSE);	return 0;exception:	/* Exception not handled by segment management */	EndPTH(&pth, FALSE);	BMS_DEBUG_PRINT(("PageFaultHdr vecno=%d excinfo=0x%08x excaddr=0x%08x "				"pte=0x%08x er=%d\n",				vecno, excinfo, excaddr, pte.w, er));	disint();	setFSR(excinfo);	setFAR(excaddr);	if ( DebugMonitorFlag != 0 ) {		return 1;  /* To BMS */	}	SysExcHdr((W)vecno, sp);	return 0;}/* * Register/deregister system exception handler *	regist = TRUE	Register *	regist = FALSE	Deregister */EXPORT void RegistSysExcHdr( BOOL regist ){	T_DINT	dint;	dint.intatr = TA_HLNG;	dint.inthdr = SysExcHdr;	tk_def_int(EIT_DEFAULT, ( regist != 0 )? &dint: NULL);}/* * Register page fault handler */LOCAL ER RegistPageFaultHdr( void ){#if !RESIDENT_ONLYIMPORT	void	asmIAbortHdr( void );IMPORT	void	asmDAbortHdr( void );	T_DINT	dint;	ER	er;	/* Save monitor default handler. */	DefaultHandlerEntry = SCArea->intvec[EIT_DEFAULT];	/* Register abort handler. */	dint.intatr = TA_ASM;	dint.inthdr = asmIAbortHdr;	er = tk_def_int(EIT_IABORT, &dint);	if ( er < E_OK ) {		goto err_ret;	}	dint.inthdr = asmDAbortHdr;	er = tk_def_int(EIT_DABORT, &dint);	if ( er < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	BMS_DEBUG_PRINT(("RegistPageFaultHdr er = %d\n", er));	return er;#else	return E_OK;#endif}/* ------------------------------------------------------------------------ *//* * Initialize system exception processing *	(immediately after T-Kernel startup) */EXPORT ER InitExcMgr( BOOL StartUp ){IMPORT	void	asmKillProcHdr( void );	T_CTSK	ctsk;	T_DINT	dint;	ER	er;	if ( !StartUp ) {		/* Termination processing: deregister at least the exception handler. */		RegistSysExcHdr(FALSE);		return E_OK;	}	/* Start system exception processing task */	SetOBJNAME(ctsk.exinf, "SExc");	ctsk.tskatr  = TA_HLNG|TA_RNG0;	ctsk.task    = SysExcTsk;	ctsk.itskpri = 1;	ctsk.stksz   = TSD_IEM_STK_2048;	er = tk_cre_tsk(&ctsk);	if ( er < E_OK ) {		goto err_ret;	}	er = tk_sta_tsk(SysExcTskID = er, 0);	if ( er < E_OK ) {		goto err_ret;	}	/* Register page fault handler */	er = RegistPageFaultHdr();	if ( er < E_OK ) {		goto err_ret;	}	/* Register BMS_KILL_PROC handler */	dint.intatr = TA_ASM;	dint.inthdr = asmKillProcHdr;	er = tk_def_int(BMS_KILL_PROC, &dint);	if ( er < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	BMS_DEBUG_PRINT(("InitExcMgr: er = %d\n", er));	return er;}

⌨️ 快捷键说明

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