📄 excmgr.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 (VR 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 CALL_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;/* 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 *//* * Structure of exception stack at exception handler entry. */typedef struct { DW ssp; /* Saved by the exception handler itself through its entry processing. */ DW t8; /* Subsequently, saved through monitor's branch processing. */ DW t9; DW epc; UW taskmode; UW psr; DW usp;} ExcStack;Inline BOOL TaskIndependent( ExcStack *isp );LOCAL void print_regs( ID tid );LOCAL ER sendExcMsg( ExcMsg *msg );LOCAL void recvExcMsg( ExcMsg *msg );LOCAL void SysExcTsk( void );LOCAL ER RegistPageFaultHdr( void );#define TSD_SEH_VAL_2 2#define TSD_HDR_VAL_3 3#define TSD_SEH_VAL_3 3#define TSD_PFH_VAL_M1 (-1)#define TSD_PFH_VAL_EM1 (-1)#define TSD_IEM_STK_4096 (4*1024)/* * Exception occurred in the task-independent section: TRUE */Inline BOOL TaskIndependent( ExcStack *isp ){IMPORT VP int_stack_top; /* Exception/interrupt stack top (T-Kernel) */ W n; n = ( (isp->taskmode & (UW)TMF_CPL(TSD_HDR_VAL_3)) > 0U )? sizeof(ExcStack): offsetof(ExcStack, usp); return ( ((B*)isp + n) < (B*)int_stack_top );}/* * 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); VP excaddr = (VP)excmsg.i.badvaddr.lo; LockSEG(); if ( excmsg.i.vecno != EXC_TLBMOD ) { er = PageIn(excaddr, lsid); } else { er = CopyOnWrite(excaddr, lsid); } if ( er >= E_OK ) { /* Register in TLB */ UW pte = GET_PTE(excaddr, lsid); UpdateTLB(excaddr, lsid, pte); } 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 != 0U ) { 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) - offsetof(EXCMESG, taskid)); msg.taskid = excmsg.i.taskid; msg.procid = pinfo->procid; msg.vecno = excmsg.i.vecno; msg.badvaddr = excmsg.i.badvaddr; /* 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 BMS to output message. */ BMS_DEBUG_PRINT(("\n***** OS SYSTEM DOWN *****\n")); BMS_DEBUG_PRINT(("INT:%d BVA:%08x %08x tid:%d\n", excmsg.i.vecno, excmsg.i.badvaddr.hi, excmsg.i.badvaddr.lo, excmsg.i.taskid)); print_regs(excmsg.i.taskid); tm_monitor(); /* To BMS */}/* ------------------------------------------------------------------------ *//* * System exception handler */EXPORT W SysExcHdr( UINT vecno, DW badvaddr ){ ExcStack *isp; ExcMsg excmsg; PINFO *pinfo; ER er; memset(&excmsg, 0, (size_t)sizeof(excmsg)); excmsg.i.vecno = vecno; excmsg.i.badvaddr = badvaddr; excmsg.pgfault = FALSE; EI(0); /* Multiplex interrupt enabled */ if ( vecno == (UW)BMS_KILL_PROC ) { /* Not considered as BMS_KILL_PROC request when called from CPL > 0. */ if ( (SCInfo.taskmode & (UW)TMF_PPL(TSD_SEH_VAL_3)) == 0U ) { /* In the case of BMS_KILL_PROC, its immediately preceding stack * indicates the actual state at the occurrence of exception. * Therefore, turn back the stack. */ isp = (ExcStack*)((B*)SCInfo.istkpos + (sizeof(ExcStack) - (sizeof(DW) * TSD_SEH_VAL_2))); isp->ssp = ((ExcStack*)SCInfo.istkpos)->ssp; SCInfo.istkpos = isp; excmsg.killproc = TRUE; } } isp = SCInfo.istkpos; /* 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 ( ((isp->psr & ((UW)SR_ERL|(UW)SR_IE)) != (UW)SR_IE) || TaskIndependent(isp) ) { goto system_down; } /* Notify BDM of the exception. */ er = BDM_NotifyException(&excmsg.i); if ( er == E_OK ) { return 0; } /* 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 ( ((isp->taskmode & (UW)TMF_CPL(TSD_HDR_VAL_3)) == 0U) || ((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 != 0U) && ((isp->taskmode & (UW)TMF_CPL(TSD_HDR_VAL_3)) < (UW)TMF_CPL(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 0; /** Use BMS to indicate messages **/system_down: BMS_DEBUG_PRINT(("\n***** OS SYSTEM DOWN *****\n")); BMS_DEBUG_PRINT(("INT:%d PC:%08x %08x PSR:%08x TMF:%08x\n" "BVA:%08x %08x tid:%d\n", vecno, isp->epc.hi, isp->epc.lo, isp->psr, isp->taskmode,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -