mmu.h #define SETGATE(gate, istrap, sel, off, d)

トップページ
jupiteroak.hatenablog.com


mmu.h
https://github.com/mit-pdos/xv6-public/blob/master/mmu.h#L168

#define SETGATE(gate, istrap, sel, off, d)                \
{                                                         \
  (gate).off_15_0 = (uint)(off) & 0xffff;                \
  (gate).cs = (sel);                                      \
  (gate).args = 0;                                        \
  (gate).rsv1 = 0;                                        \
  (gate).type = (istrap) ? STS_TG32 : STS_IG32;           \
  (gate).s = 0;                                           \
  (gate).dpl = (d);                                       \
  (gate).p = 1;                                           \
  (gate).off_31_16 = (uint)(off) >> 16;                  \
}

SETGATEマクロは、引数gateで指定された割り込みディスクリプタ(ゲートディスクリプタ)に値を設定して、割り込みベクタ番号とハンドラ(例外ハンドラ、または、割り込みハンドラ)の対応関係をつくります。

引数 gate
設定対象となる割り込みディスクリプタ(struct gatedesc構造体)です。

引数 istrap
設定対象となる割り込みディスクリプタ(gatedesc構造体)を、トラップゲートとして利用する場合は1を、割り込みゲートとして利用する場合は0を指定します。

引数 sel
ハンドラ(例外ハンドラ、または、割り込みハンドラ)が格納されているコードセグメントのセレクタ値です。
セレクタ値は割り込みディスクリプタのbit31-16(gatedesc構造体のcs)に格納されます。

引数 off
コードセグメント内にあるハンドラ(例外ハンドラ、または、割り込みハンドラ)のオフセットアドレスです。
オフセットアドレスの上位16bitは割り込みディスクリプタのbit63-48(gatedesc構造体のoff_31_16)に格納され、オフセットアドレスの下位16bitは割り込みディスクリプタのbit15-0(gatedesc構造体のoff_15_0 )に格納されます。

引数 d
ハンドラ(例外ハンドラ、または、割り込みハンドラ)の実行に必要なCPUの特権レベルです。
dの値は割り込みディスクリプタのbit46-45(gatedesc構造体のdpl)に格納されます。


処理の内容

前提

割り込みディスクリプタを表現したデータ構造であるgatedesc構造体(8バイト)です

struct gatedesc {
  uint off_15_0 : 16;   // low 16 bits of offset in segment
  uint cs : 16;         // code segment selector
  uint args : 5;        // # args, 0 for interrupt/trap gates
  uint rsv1 : 3;        // reserved(should be zero I guess)
  uint type : 4;        // type(STS_{IG32,TG32})
  uint s : 1;           // must be 0 (system)
  uint dpl : 2;         // descriptor(meaning new) privilege level
  uint p : 1;           // Present
  uint off_31_16 : 16;  // high bits of offset in segment
};

割り込みディスクリプタのbit15-0(gatedesc構造体のoff_15_0 )にオフセットアドレスを設定する

(gate).off_15_0 = (uint)(off) & 0xffff;  

割り込みディスクリプタのbit15-0(gatedesc構造体のoff_15_0 )に、オフセットアドレスの下位16bitを設定します。
off(32bit)を0xffffでマスク処理することにより、オフセットアドレスの下位16bitを取得しています。

割り込みディスクリプタのbit39-16(gatedesc構造体のrsv1、args、cs)に値を設定する

(gate).cs = (sel);
(gate).args = 0;
(gate).rsv1 = 0;    

割り込みディスクリプタのbit31-16、bit36-32、bit39-37(gatedesc構造体のcs、args、rsv1)に、sel、0、0をそれぞれ設定します。

bit31-16(セグメントセレクタ)

ハンドラ(例外ハンドラ、または、割り込みハンドラ)が格納されているコードセグメントのセレクタ値を設定するフィールドです。

bit36-32

予約済みのフィールドで、常に 00000 です。

bit39-37

常に 000 です。

割り込みディスクリプタのbit47-40(gatedesc構造体のp、dpl、s、type)に値を設定する

(gate).type = (istrap) ? STS_TG32 : STS_IG32;
(gate).s = 0;
(gate).dpl = (d);
(gate).p = 1;      

割り込みディスクリプタのbit43-40、bit44、bit46-45、bit47(gatedesc構造体のtype、p、dpl、s)に、(istrap) ? STS_TG32 : STS_IG32、0、d、1をそれぞれ設定します。

bit43-40(type)

割り込みディスクリプタがトラップゲート(例外で使用する割り込みディスクリプタ)か割り込みゲート(ハードウェア割り込みで使用する割り込みディスクリプタ)かを指定するフィールドです。
トラップゲートとして利用する場合は(istrap = 1)、1111(#define STS_TG32 0xF)が格納されます。
割り込みゲートとして利用する場合(istrap = 0)は、1110(#define STS_IG32 0xE)が格納されます。

bit44(Sフラグ)

割り込みディスクリプタでは、常に0です。

bit46-45(DPL)

ハンドラ(例外ハンドラor割り込みハンドラ)の実行に必要なCPUの特権レベルを指定するフィールドです。
00...ハンドラの実行に必要なCPUの特権レベルがカーネルモードであることを示しています。
11...ハンドラの実行に必要なCPUの特権レベルがユーザーモードであることを示しています。

bit47(Pフラグ)

セグメントがメモリ上に存在するかしないかを示すフィールドです。
この値が1の時は、セグメントがメモリ上に常に存在することを示しています。

割り込みディスクリプタのbit63-48(gatedesc構造体のoff_31_16)にオフセットアドレスを設定する

(gate).off_31_16 = (uint)(off) >> 16;

割り込みディスクリプタのbit63-48(gatedesc構造体のoff_31_16)に、オフセットアドレスの上位16bitを設定します。
offの値(32bit)を16bit右シフト演算することで、オフセットアドレス上位16bitの値を取得しています。