この章の目次にもどる
前頁:第5章 ITRON拡張機能にもどる

第6章 I-right/V独自の機能

6.1 以下の記述に関する注意

6.2 メモリーモデル

メモリーモデルは 4GB のフラットメモリーモデルとする。 セグメントは使用しない。 ただし、内部的には以下の 7 つのセグメントが存在する。

CODE0
ベースアドレス 0x00000000
セグメントリミット0xffffffff
保護レベル 0
アクセス制限 実行可・読み取り不可
コンフォーミング False
ワードサイズ 32ビット
CODE0C,CODE1C
ベースアドレス 0x00000000
セグメントリミットCODE0 と同じ値
保護レベル 0, 1
アクセス制限 実行可・読み取り不可
コンフォーミング True
ワードサイズ 32ビット
DATA0〜3
ベースアドレス 0x00000000
セグメントリミットCODE0 と同じ値
保護レベル 0, 1, 2, 3
アクセス制限 読み取り可・書き込み可
伸張方向 上方伸張
ワードサイズ 32ビット

コードセグメントは、3 種類ある。

データセグメントは保護レベル別に 4 つあり、 スタックセグメントとしても使用する。
これらのセグメントは、すべてのタスク/ハンドラで共有する。 アプリケーションは、 これらのセグメントの属性 (ディスクリプタの内容) を変更することはできない (変更してはいけない)。 また、他のセグメントを追加することもできない。

上記の様に、 各セグメントはすべて同じアドレス空間を指している。 したがって、 どのセグメントレジスターをベースにしても、 同一のオフセットアドレスは同じメモリーを示すことになる。 また、このことによりいずれの保護レベルからでも すべてのメモリーにアクセスすることが可能である (メモリー保護は働かない)。

これらのセグメントは、アプリケーションからは見えない。 また、セグメントレジスタをアプリケーションで変更することはできない (変更してはいけない)。
セグメントレジスタはタスク付属ではない。 タスクスイッチ時にも (データ) セグメントレジスタは保存・復帰されない。 したがって、セグメントレジスタを変更すると、 他のタスクの動作が異常となったり、 一般保護例外が発生する場合があり、最悪システムダウンとなることもある。

タスク実行時には、CS,SS レジスタには、 タスク生成時に指定された保護レベルと 等しい保護レベルのセグメントが設定される。 ただし、CS には前述のように CODE0 または CODE1C が設定され、 下位 2 ビット (CPL) が対応する保護レベルに一致するように設定される。 ハンドラ実行時には、CS, SS レジスタには、 保護レベル 0 のセグメント (CODE0,DATA0) が設定される。 ただし、コンフォーミング指定された例外ハンドラでは、 CS レジスタにはコンフォーミング属性のセグメント (CODE0C) が設定され、 割り込まれたときの保護レベルで実行される。 また、SS レジスタは割り込まれたときのままとなる。
FS レジスタには、 タスク生成時に保護レベル 3 のデータセグメント (DATA3) が設定される。 拡張 SVC を呼び出すと、FS レジスタの最下位2ビット (RPL) は、 拡張 SVC を呼び出したときの保護レベルを示すように変更される。 (6.8 def_svc() 参照)
DS, ES, GS レジスタには、 保護レベル 3 のデータセグメント (DATA3) がシステム (ITRON) 初期化時に設定され、 その後はシステム (ITRON) では変更しない。 タスクスイッチ時にもタスクのコンテキストとしての保存・復帰は行われない (上述の様に、アプリケーションで変更した場合の動作は保証されない)。

6.3 ページング

用語に関する注意:

ITRON は、タスクスイッチによってページテーブルを切り替える。 ページテーブルの内容およびページフォルト例外などは ITRON では関知しない。

上位レベル (ITRON の外) でページング機能を利用することが可能である。 ページング機能を利用してメモリー保護を行うことも可能である。 ただし、 ITRON 内部 (クリティカルセクション内) を実行中にページフォルト例外や一般保護例外などが発生してはいけない。

タスクスイッチによって切り替えるページテーブルは、 ページディレクトリの先頭の 64 エントリー分である。 したがって、アドレスの 0〜256MB までがタスク固有空間となり、 残りの 256MB〜4GB は共有空間となる。

各タスクの固有空間の分のページテーブル (64 エントリー分 = 256B) は、 アプリケーション側で用意し、タスク生成時に指定する (6.11 cre_tsk() の項を参照)。

ページテーブルの切り替えは次の様な方法をとる。

ページテーブルの切り替え
図 1 : ページテーブルの切り替え

実際に CPU に与えるページテーブルは1つであり、 その一部 (固有空間部分) にタスク生成時に指定された固有空間分のページテーブルをコピーする。 コピーはタスクスイッチごとに行われ、 タスクごとのページテーブルから CPU のページテーブルへコピーする。 CPU のページテーブルからタスクごとのページテーブルへ書き戻すことはしない。 なお、コピーするのはページディレクトリの部分だけであり、 その内容には関知しない。 したがって、現在実行中のタスクのページテーブルを書き換えるときは、 タスクごとのページテーブルと、 CPU のページテーブル (ページディレクトリ) の両方を変更する必要がある。 共有空間のページテーブルは CPU のページテーブルにしか存在しないため、 CPU のページテーブルのみを変更すればよい。 CPU のページテーブルの位置は、 PDBR (CR3) レジスタを読み出すことで得られる。

6.4 I/O 保護モード

I/O 保護モードは次の様に設定され、 すべてのタスク/ハンドラで共通となる。 アプリケーションでこれらの設定を変更することはできない (変更してはいけない)。

    I/O 保護レベル (EFLAGS:IOPL)    = 1
    TSS I/O 許可ビットマップ        = すべて禁止(1)

つまり、保護レベル0および1で実行されているときは、 すべての I/O にアクセス可能。 逆に、保護レベル 2 および 3 で実行されているときは、 すべての I/O にアクセスできない。

6.5 例外/割込一覧

ベクター番号内容 
0 除算エラー
1 デバッグ例外
2 NMI 割込
3 ブレークポイント
4 INTO 検出のオーバーフロー
5 BOUND の範囲外
6 無効オペコード
7 デバイスが使用不可
8 ダブルフォルト
9 コプロセッサのセグメントオーバーラン
10無効タスクステートセグメント
11セグメント不在
12スタックフォルト
13一般保護
14ページフォルト
15インテル予約
16浮動小数点エラー
17アライメントチェック
18マシンチェック
19〜31インテル予約
32〜111DOS 予約
112〜119外部割込 PIC No.2
112IRQ8 リアルタイムクロック
113IRQ9 予備 (リダイレクト IRQ2)
114IRQ10予備
115IRQ11予備
116IRQ12マウス
117IRQ13数値演算プロセッサ
118IRQ14ハードディスク
119IRQ15予備
120〜127外部割込 PIC No.1
120IRQ0タイマー
121IRQ1キーボード
122IRQ2カスケード PIC No.2
123IRQ3シリアル2
124IRQ4シリアル1
125IRQ5パラレル3
126IRQ6フロッピーディスク
127IRQ7パラレル1, パラレル2
128ITRON ディスパッチャ呼び出し
129ITRON システムコール/拡張 SVC 呼び出し
130ITRON ret_int 専用呼び出し
131〜143予備
144〜255未使用
DOS 予約および外部割込は OADG 仕様による。 ただし、PIC No.1 のベクターは、OADG 仕様とは異なる。 OADG 仕様では、8〜15 に割り当てられており、 CPU 例外とベクターが重なるため移動した。

☆印は、ITRON が利用している割込である。

6.6 ITRON で使用する例外/割込

外部割込
例外

6.7 システムコール/拡張 SVC 呼び出し

システムコール呼び出しインターフェースは、次の例のようになる。

システムコール呼び出しインターフェース
図 2 : システムコール呼び出しインターフェース

アセンブラから呼び出す場合にも、 C 言語の呼び出し規則に則って、 スタック上にパラメータを積み、call xxx_yyy の様に呼び出す。 または、上記の様に eax に機能コードとパラメータ数、 edx にパラメータの先頭アドレスをセットして int 129 を直接呼び出してもよい。 ただし、レジスタの保存規則などはC 言語の場合と同じである。

eax < 0 ならシステムコール、 eax >= 0 なら拡張 SVC となる。

拡張 SVC の呼び出しも、 システムコールと同じ呼び出しシーケンスとなる。 ただし、eax には拡張機能コードを設定する。 パラメータ数を含めるか否かは、 拡張 SVC を提供する側で決定する事項なので、ITRON では規定しない。 eax の下位 8 ビットが拡張 SVC 番号となる。 残りの上位部分は最上位ビット (MSB) を除いて無視する。 最上位ビット (MSB) は 0 でなければならない。

6.8 def_svc()

6.9 def_int()

        typedef struct t_dint {
                ATR     intatr;         /* 割込みハンドラ属性 */
                FP      inthdr;         /* 割込みハンドラアドレス */
        } T_DINT;

TA_HLNG を指定した場合

TA_ASM を指定した場合

6.10 ret_int()

6.11 cre_tsk()

6.12 vget_tsp() / vset_tsp()

タスク固有空間の取得/設定を行う。

        typedef struct {
                VW      uatb;   /* タスク固有空間ページテーブルのアドレス */
                VW      lsid;   /* タスク固有空間 ID */
        } T_TSKSPC;

uatb, lsidcre_tsk() での指定と同じ。

6.13 vget_reg() / vset_reg()

6.14 vget_cpr() / vset_cpr()

        ER vget_cpr( T_COPREG *pk_copreg, ID tskid, INT copno )
        ER vset_cpr( ID tskid, INT copno, T_COPREG *pk_copreg )

        typedef struct {
                UH      cw;             /* Control Word */
                UH      rsv1;
                UH      sw;             /* Status Word */
                UH      rsv2;
                UH      tw;             /* Tag Word */
                UH      rsv3;
                UW      ip;             /* IP */
                UH      cs;             /* CS */
                UH      op;             /* opcode */
                UW      of;             /* operand offset */
                UH      os;             /* operand selector */
                UH      rsv4;
                UB      st[8][10];      /* st(0)〜st(7) */
        } T_COP0REG;
        typedef union {
                T_COP0REG       cop0;
        #if 0
                T_COP1REG       cop1;
                T_COP2REG       cop2;
                T_COP3REG       cop3;
                T_COP4REG       cop4;
                T_COP5REG       cop5;
                T_COP6REG       cop6;
                T_COP7REG       cop7;
        #endif
        } T_COPREG;

6.15 ref_cfg()

        typedef struct t_rcfg {
            INT timer_period;           /* タイマー割込間隔 (ms) */
            INT default_slice_time;     /* デフォルト連続実行時間 (ms) */
            UW  cpu_type;               /* CPU タイプ */
        } T_RCFG;
timer_period

タイマー割込の発生間隔を示す。

default_slice_time

同一優先度のタスクは、ラウンドロビンスケジューリングが行われる。
default_slice_time がデフォルトのスライス間隔(ミリ秒)となる。

cpu_type

現在システムが動作している CPU に関する情報が設定される。下位 16bit は、ITRON 仕様で定める CPU コードであり、 上位 16bit にインプリメント依存の付加情報が追加される。
get_ver() で得られる CPU 情報が OS を実行可能な CPU タイプであるのに対し、 ref_cfg() では現在動作している CPU タイプを返す。

        #define TCPU_unknown    0               /* CPU 未定義 */
        #define TCPU_G100       0x00000009      /* Gmicro/100 */
        #define TCPU_G200       0x0000000a      /* Gmicro/200 */
        #define TCPU_G300       0x0000000b      /* Gmicro/300 */
        #define TCPU_G400       0x00000018      /* Gmicro/400 */
        #define TCPU_G500       0x00000019      /* Gmicro/500 */
        #define TCPU_ix86       0x00000060      /* Intel x86 系 */
        #define TCPU_i386       0x00000063      /* i386 SX/DX シリーズ */
        #define TCPU_i486       0x00000064      /* i486 SX/DX シリーズ */
        #define TCPU_Pentium    0x00000065      /* Pentium シリーズ */
        #define TCPU_PentiumPro 0x00000066      /* PentiumPro シリーズ */
        #define TCPU_FPU        0x00010000      /* FPU 付 */

浮動小数点演算コプロセッサ(FPU)が搭載されている場合に TCPU_FPU が OR される。i486DX や Pentium では FPU が内蔵されているので、必ず OR されていることになる。

6.16 強制例外ハンドラ

ハンドラは、下記のエントリールーチンを持つ必要がある。

        hll_fexchdr_startup:
                xchgl   (%esp), %eax            // 汎用レジスタ保存
                pushl   %ecx
                pushl   %edx
                pushfl                          // フラグ保存
                pushl   %eax                    // fexcode
                call    fexchdr                 // call fexchdr(fexcode)
                addl    $4, %esp
                popfl                           // フラグ復帰
                popl    %edx                    // 汎用レジスタ復帰
                popl    %ecx
                popl    %eax
                ret                             // 割り込まれた場所へ戻る

6.17 使用ハードウエア

ITRON では下記のハードウエアを使用している。


この章の目次にもどる
前頁:第5章 ITRON拡張機能にもどる