(toppers-users 773) Re: 割込みハンドラ出口処理について

SHUKUGUCHI Masahiro ms89019 @ mms.co.jp
2003年 3月 11日 (火) 17:50:04 JST


たちさん ご無沙汰しております。

フォローありがとうございます。ご指摘の通りだと思います。
# 添削なんて。。。。

> TOPPERS(の公開されているCPU依存部)は、idleタスクのかわりに
> exit_and_dispatchの中で待ちに入ってます。
> M68Kの場合、割り込みモードで待ちに入っているので、割り込みハ
> ンドラの出入り口処理からret_intは呼び出されません。

カレントタスクが無い状態の処理は以下ですね。

cpu_suppoer.S  73行目あたり

exit_and_dispatch:
	or.w #0x1000, %sr		/* マスタモード */
dispatcher:
	/*
	 *  ここではマスタモード・割込み禁止状態でなければならない.
	 */
	move.l schedtsk, %a0
	move.l %a0, runtsk		/* schedtsk を runtsk に */
	jbeq dispatcher_1		/* runtsk があるか? */
	move.l TCB_msp(%a0), %sp	/* タスクスタックを復帰 */
	move.l TCB_pc(%a0), %a1		/* 実行再開番地を復帰 */
	jmp (%a1)
dispatcher_1:
	stop #0x2000			/* 割込み待ち(割込みモード) */
	/*
	 *  ここで割込みモードに切り換えるのは,ここで発生する割込み処理
	 *  にどのスタックを使うかという問題の解決と,割込みハンドラ内で
	 *  のタスクディスパッチの防止という2つの意味がある.
	 *  この stop 命令は,IPM を 0 にするが,本来は task_intmask に
	 *  設定すべきである.M68040 では,stop 命令のパラメータに定数し
	 *  かとれないため,やむをえず 0 にしている(stop 命令を 8つ並べ
	 *  て,task_intmask の値で飛び分ける手はあるが,そこまでやる意
	 *  義はないと考えた).
	 */
	or.w #0x1700, %sr		/* マスタモード・割込み禁止 */
	tst.l reqflg			/* reqflg が FALSE なら */
	jbeq dispatcher_1		/*      dispatcher_1 へ */
	clr.l reqflg			/* reqflg を FALSE に */
	jbra dispatcher

CPUが割込み状態(=%srが0x2000)でSTOP状態になるので、ここで割込みが
入ると、割込みからの戻り先が割込み状態になりますね。

で、

>                          「戻り先
> が割り込みモードならすぐにリターン」という流れになります。

cpu_config.h:227行目あたり

#define	INTHDR_ENTRY(inthdr)		\
extern void inthdr##_entry(void);	\
asm(".text				\n" \
#inthdr "_entry:			\n" \
"	movem.l %d0-%d1/%a0-%a1, -(%sp)	\n" /* スクラッチレジスタを保存 */ \
"	jsr " #inthdr "			\n" /* 割込みハンドラを呼び出す */ \
"	movem.l (%sp)+, %d0-%d1/%a0-%a1	\n" /* スクラッチレジスタを復帰 */ \
"	btst.b #4, (%sp)		\n" /* 戻り先が割込みモードなら */ \
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
この命令が効いてくるのですね。

"	jbeq 1f				\n" /*           すぐにリターン */ \
"	or.w #0x0700, %sr		\n" /* 割込み禁止 */ \
"	tst.l _kernel_reqflg		\n" /* reqflg が TRUE であれば */ \
"	jbne _kernel_ret_int		\n" /*              ret_int へ */ \
"1:	rte				\n")

> その後、exit_and_dispatchの中からdispatchへ飛びます。
> また、exit_and_dispatchはruntsk==NULLを考慮しています。

はい。そうなると思います。

exit_and_dispatch:
	or.w #0x1000, %sr		/* マスタモード */
dispatcher:
	/*
	 *  ここではマスタモード・割込み禁止状態でなければならない.
	 */
	move.l schedtsk, %a0
	move.l %a0, runtsk		/* schedtsk を runtsk に */
	jbeq dispatcher_1		/* runtsk があるか? */
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ここで、runtsk==NULL を考慮していますね。
# MC68Kのmove命令は、0の移動で ZEROフラグがセットされるので、次の
# 条件分岐が有効になりますね。
## runtsk=NULLならば、dispatcher_1に分岐します。

	move.l TCB_msp(%a0), %sp	/* タスクスタックを復帰 */
	move.l TCB_pc(%a0), %a1		/* 実行再開番地を復帰 */
	jmp (%a1)
dispatcher_1:
	stop #0x2000			/* 割込み待ち(割込みモード) */

宿口雅弘