📄 cpu_calls.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel * * Copyright (C) 2004 by Ken Sakamura. All rights reserved. * T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * * Version: 1.01.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2004/6/28. * *---------------------------------------------------------------------- *//* * cpu_calls.c (VR4131) * CPU-Dependant System Call */#include "kernel.h"#include "task.h"#include "check.h"#include "cpu_task.h"#include <sys/sysinfo.h>#include <tk/sysdef.h>#include "cpu_insn.h"/* * Dispatch enable/disable */SYSCALL ER c_tk_dis_dsp( UW *psr ){ CHECK_CTX(!in_loc()); /* Change PSR saved in stack */ *psr &= ~SR_IM(1); return E_OK;}/* * Dispatch enable */SYSCALL ER c_tk_ena_dsp( UW *psr ){ CHECK_CTX(!in_loc()); /* Change PSR saved in stack */ *psr |= SR_IM(1); return E_OK;}/* ------------------------------------------------------------------------ *//* For saving monitor exception handler */EXPORT MONHDR SaveMonHdr;/* * High level programming language *//* High level programming language interrupt handler entry */EXPORT FP hll_inthdr[N_INTVEC];/* High level programming language interrupt handler 'gp' */EXPORT VP hll_inthdr_gp[N_INTVEC];/* High level programming language routine */IMPORT void inthdr_startup();/* For default handler */IMPORT void defaulthdr_startup();/* * Interrupt handler definition */SYSCALL ER _tk_def_int P2( UINT dintno, T_DINT *pk_dint ){ FP inthdr; CHECK_PAR(dintno >= 0 && dintno < N_INTVEC); if ( pk_dint != NULL ) { /* Set interrupt handler */ CHECK_RSATR(pk_dint->intatr, TA_HLNG|TA_GP); if ( dintno >= 1 && dintno <= 4 ) { /* TA_HLNG is not available in 1-4 */ if ( (pk_dint->intatr & TA_HLNG) != 0 ) return E_PAR; } inthdr = pk_dint->inthdr; if ( (pk_dint->intatr & TA_GP) != 0 ) gp = pk_dint->gp; BEGIN_CRITICAL_SECTION; if ( (pk_dint->intatr & TA_HLNG) != 0 ) { hll_inthdr[dintno] = inthdr; hll_inthdr_gp[dintno] = gp; inthdr = ( dintno == EIT_DEFAULT )? defaulthdr_startup: inthdr_startup; } define_inthdr(dintno, inthdr); END_CRITICAL_SECTION; } else { /* Free interrupt handler */ switch ( dintno ) { case VECNO_DEFAULT: inthdr = SaveMonHdr.default_hdr; break; case VECNO_INTERRUPT: inthdr = SaveMonHdr.interrupt_hdr; break; case VECNO_SYSCALL: inthdr = SaveMonHdr.syscall_hdr; break; case VECNO_WATCH: inthdr = SaveMonHdr.watch_hdr; break; case VECNO_MONITOR: inthdr = SaveMonHdr.monitor_hdr; break; case VECNO_BREAK: inthdr = SaveMonHdr.break_hdr; break; case VECNO_IP2: inthdr = SaveMonHdr.ip2_hdr; break; case VECNO_GPIO: inthdr = SaveMonHdr.gpio_hdr; break; case VECNO_FPGA: inthdr = SaveMonHdr.fpga_hdr; break; default: inthdr = NULL; } BEGIN_CRITICAL_SECTION; define_inthdr(dintno, inthdr); hll_inthdr[dintno] = NULL; END_CRITICAL_SECTION; } return E_OK;}/* ------------------------------------------------------------------------ *//* * Get/Set task space */SYSCALL ER _tk_get_tsp( ID tskid, T_TSKSPC *pk_tskspc ){ TCB *tcb; ER ercd = E_OK; CHECK_TSKID_SELF(tskid); CHECK_INTSK(); tcb = get_tcb_self(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else { pk_tskspc->uatb = tcb->tskctxb.uatb; pk_tskspc->lsid = tcb->tskctxb.lsid; } END_CRITICAL_SECTION; return ercd;}/* * Set task space */SYSCALL ER _tk_set_tsp( ID tskid, T_TSKSPC *pk_tskspc ){ TCB *tcb; ER ercd = E_OK; CHECK_TSKID_SELF(tskid); CHECK_INTSK(); tcb = get_tcb_self(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST) { ercd = E_NOEXS; } else { tcb->tskctxb.uatb = pk_tskspc->uatb; tcb->tskctxb.lsid = pk_tskspc->lsid; /* When it is the currently running task, switch the current space */ if ( tcb == ctxtsk ) { change_space(tcb->tskctxb.lsid); } } END_CRITICAL_SECTION; return ercd;}/* ------------------------------------------------------------------------ *//* * Set task register contents */LOCAL void set_reg( TCB *tcb, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ){ SStackFrame *ssp; UW psr; INT i; ssp = (VP)tcb->tskctxb.ssp.lo; psr = ssp->rng0_3.psr; if ( cregs != NULL ) ssp = (VP)cregs->ssp.lo; if ( regs != NULL ) { ssp->rng0_3.at = regs->at; ssp->rng0_3.v[0] = regs->v[0]; ssp->rng0_3.v[1] = regs->v[1]; for ( i = 0; i < 4; ++i ) { ssp->rng0_3.a[i] = regs->a[i]; } for ( i = 0; i < 8; ++i ) { ssp->rng0_3.t[i] = regs->t[i]; ssp->rng0_3.s[i] = regs->s[i]; } ssp->rng0_3.t8 = regs->t[8]; ssp->rng0_3.t9 = regs->t[9]; ssp->rng0_3.gp = regs->gp; ssp->rng0_3.fp = regs->fp; ssp->rng0_3.ra = regs->ra; ssp->rng0_3.hi = regs->hi; ssp->rng0_3.lo = regs->lo; } if ( eit != NULL ) { ssp->rng0_3.epc = eit->pc; ssp->rng0_3.psr = psr; ssp->rng0_3.taskmode = eit->taskmode; } if ( cregs != NULL ) { tcb->tskctxb.ssp = cregs->ssp; tcb->tskctxb.uatb = cregs->uatb; tcb->tskctxb.lsid = cregs->lsid; if ( (tcb->tskatr & TA_RNG3) != 0 ) { /* Only RNG 1-3 */ ((DW*)tcb->isstack)[-1] = cregs->usp; } }}/* * Set task register contents */SYSCALL ER _tk_set_reg( ID tskid, T_REGS *pk_regs, T_EIT *pk_eit, T_CREGS *pk_cregs ){ TCB *tcb; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); CHECK_INTSK(); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else { set_reg(tcb, pk_regs, pk_eit, pk_cregs); } END_CRITICAL_SECTION; return ercd;}/* * Get task register contents. */LOCAL void get_reg( TCB *tcb, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ){ SStackFrame *ssp; INT i; ssp = (VP)tcb->tskctxb.ssp.lo; if ( regs != NULL ) { regs->at = ssp->rng0_3.at; regs->v[0] = ssp->rng0_3.v[0]; regs->v[1] = ssp->rng0_3.v[1]; for ( i = 0; i < 4; ++i ) { regs->a[i] = ssp->rng0_3.a[i]; } for ( i = 0; i < 8; ++i ) { regs->t[i] = ssp->rng0_3.t[i]; regs->s[i] = ssp->rng0_3.s[i]; } regs->t[8] = ssp->rng0_3.t8; regs->t[9] = ssp->rng0_3.t9; regs->gp = ssp->rng0_3.gp; regs->fp = ssp->rng0_3.fp; regs->ra = ssp->rng0_3.ra; regs->hi = ssp->rng0_3.hi; regs->lo = ssp->rng0_3.lo; } if ( eit != NULL ) { eit->pc = ssp->rng0_3.epc; eit->psr = ssp->rng0_3.psr & ~SR_EXL; eit->taskmode = ssp->rng0_3.taskmode; /* Set PSR.CU1 to indicate the state of TA_FPU attribute */ if ( (tcb->tskatr & TA_FPU) != 0 ) eit->psr |= SR_CU1; } if ( cregs != NULL ) { cregs->sstktop = tcb->isstack; cregs->ssp = tcb->tskctxb.ssp; cregs->uatb = tcb->tskctxb.uatb; cregs->lsid = tcb->tskctxb.lsid; cregs->usp = ((DW*)tcb->isstack)[-1]; }}/* * Get task register contents. */SYSCALL ER _tk_get_reg( ID tskid, T_REGS *pk_regs, T_EIT *pk_eit, T_CREGS *pk_cregs ){ TCB *tcb; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); CHECK_INTSK(); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else { get_reg(tcb, pk_regs, pk_eit, pk_cregs); } END_CRITICAL_SECTION; return ercd;}/* * Set task coprocessor register */SYSCALL ER _tk_set_cpr( ID tskid, INT copno, T_COPREGS *pk_copregs ){ ATR copatr = TA_COP0 << copno; TCB *tcb; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); CHECK_PAR((copatr & available_cop) != 0); CHECK_INTSK(); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else if ( (tcb->tskatr & copatr) == 0 ) { ercd = E_PAR; } else {#if TA_FPU /* If the current FPU context belongs to 'tcb,' disable it. */ if ( fpu_ctxtsk == tcb ) fpu_ctxtsk = NULL; /* Set FPU register */ memcpy(tcb->isstack, pk_copregs, sizeof(T_COP0REGS));#endif } END_CRITICAL_SECTION; return ercd;}/* * Get task coprocessor register */SYSCALL ER _tk_get_cpr( ID tskid, INT copno, T_COPREGS *pk_copregs ){ ATR copatr = TA_COP0 << copno; TCB *tcb; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); CHECK_PAR((copatr & available_cop) != 0); CHECK_INTSK(); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else if ( (tcb->tskatr & copatr) == 0 ) { ercd = E_PAR; } else {#if TA_FPU IMPORT void save_fpuctx( T_COP0REGS *save_area ); if ( fpu_ctxtsk == tcb ) { /* Because the current FPU context belongs to 'tcb,' retrieve directly from the register */ save_fpuctx(&pk_copregs->cop0); } else { /* Retrieve directly from the saved context */ memcpy(pk_copregs, tcb->isstack, sizeof(T_COP0REGS)); }#endif } END_CRITICAL_SECTION; return ercd;}/* ------------------------------------------------------------------------ *//* * Debugger support function */#if USE_DBGSPT/* * Set task register */SYSCALL ER _td_set_reg( ID tskid, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ){ TCB *tcb; ER ercd = E_OK; CHECK_TSKID(tskid); tcb = get_tcb(tskid); if ( tcb == ctxtsk ) return E_OBJ; BEGIN_DISABLE_INTERRUPT; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else { set_reg(tcb, regs, eit, cregs); } END_DISABLE_INTERRUPT; return ercd;}/* * Get task register */SYSCALL ER _td_get_reg( ID tskid, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ){ TCB *tcb; ER ercd = E_OK; CHECK_TSKID(tskid); tcb = get_tcb(tskid); if ( tcb == ctxtsk ) return E_OBJ; BEGIN_DISABLE_INTERRUPT; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else { get_reg(tcb, regs, eit, cregs); } END_DISABLE_INTERRUPT; return ercd;}#endif /* USE_DBGSPT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -