mmu.h #define SEG(type, base, lim, dpl)
トップページ
jupiteroak.hatenablog.com
mmu.h
https://github.com/mit-pdos/xv6-public/blob/master/mmu.h#L42
#define SEG(type, base, lim, dpl) (struct segdesc) \ { ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, \ ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ (uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 }
SEGマクロは、最大サイズが4GBとなるセグメントが、引数で指定されたtype(種類)、base(セグメントのベースアドレス)、lim(リミット値)、dpl(ディスクリプタ特権レベル)を持つように、セグメントディスクリプタ(segdesc構造体)の値を設定します。
引数 type
セグメントの種類を指定する値(4bit)です。
typeはセグメントディスクリプタのbit43-40(segdesc構造体のtype)に格納されます。
引数 base
セグメントのベースアドレス(32bit)です。
ベースアドレスの上位8bitはセグメントディスクリプタのbit63-56(segdesc構造体のbase_31_24)に格納され、ベースアドレスの下位24bitはセグメントディスクリプタのbit39-16(segdesc構造体のbase_23_16とbase_15_0)に格納されます。
引き数 lim
セグメントのサイズを指定するリミット値(セグメントのサイズ-1)を含んだ値(32bit)です。
limの値(32bit)のうち上位20bitをリミット値として利用します。リミット値の上位4bitはセグメントディスクリプタのbit51-48(segdesc構造体のlim_19_16)に格納され、リミット値の下位16bitはセグメントディスクリプタのbit15-0(segdesc構造体のlim_15_0)に格納されます。
引数 dpl
セグメントのアクセスに必要なCPUの特権レベルです。
dplの値はセグメントディスクリプタのbit46-45(segdesc構造体のdpl)に格納されます。
処理の内容
- 前提1
- 前提2
- セグメントディスクリプタのbit15-0(segdesc構造体のlim_15_0)にリミット値を設定する
- セグメントディスクリプタのbit39-16(segdesc構造体のbase_23_16とbase_15_0)にセグメントのベースアドレスを設定する
- セグメントディスクリプタのbit47-40(segdesc構造体のp、dpl、s、type)に値を設定する
- セグメントディスクリプタのbit55-48(segdesc構造体のg、db、rsv1、avl、lim_19_16)に値を設定する
- セグメントディスクリプタのbit63-56(segdesc構造体のbase_31_24)にセグメントのベースアドレスを設定する
前提1
セグメントディスクリプタを表現したデータ構造であるsegdesc構造体(8バイト)です。
mmu.h
https://github.com/mit-pdos/xv6-public/blob/master/mmu.h#L25
// Segment Descriptor struct segdesc { uint lim_15_0 : 16; // Low bits of segment limit uint base_15_0 : 16; // Low bits of segment base address uint base_23_16 : 8; // Middle bits of segment base address uint type : 4; // Segment type (see STS_ constants) uint s : 1; // 0 = system, 1 = application uint dpl : 2; // Descriptor Privilege Level uint p : 1; // Present uint lim_19_16 : 4; // High bits of segment limit uint avl : 1; // Unused (available for software use) uint rsv1 : 1; // Reserved uint db : 1; // 0 = 16-bit segment, 1 = 32-bit segment uint g : 1; // Granularity: limit scaled by 4K when set uint base_31_24 : 8; // High bits of segment base address };
前提2
説明の都合上、便宜的にマクロを書き換えます。
#define SEG(type, base, lim, dpl) (struct segdesc) \ { ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, \ ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ (uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 }
↓
#define SEG(type, base, lim, dpl) (struct segdesc) { ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, (uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 }
セグメントディスクリプタのbit15-0(segdesc構造体のlim_15_0)にリミット値を設定する
((lim) >> 12) & 0xffff,
セグメントディスクリプタのbit15-0(segdesc構造体のlim_15_0)にリミット値の下位16bitを設定します。
limの値(32bit)を12bit右シフト演算し0xffffでマスク処理することにより、リミット値の下位16bitを取得しています。
セグメントディスクリプタのbit39-16(segdesc構造体のbase_23_16とbase_15_0)にセグメントのベースアドレスを設定する
(uint)(base) & 0xffff, ((uint)(base) >> 16) & 0xff,
セグメントディスクリプタのbit39-16(segdesc構造体のbase_23_16とbase_15_0)にセグメントのベースアドレス下位24bitを設定します。
baseの値(32bit)を0xffffでマスク処理することによりセグメントのベースアドレスbit15-0を取得し、 baseの値(32bit)を16bit右シフト演算し0xffでマスク処理することによりセグメントのベースアドレスbit23-16を取得しています。
セグメントディスクリプタのbit47-40(segdesc構造体のp、dpl、s、type)に値を設定する
type, 1, dpl, 1,
セグメントディスクリプタのbit43-40、bit44、bit46-45、bit47(segdesc構造体のtype、s、dpl、p)に、type、1、dpl、1をそれぞれ設定します。
bit43-40(type)
セグメントの種類を指定するフィールドです。
typeの値とセグメントの種類の対応例を以下に示します。
typeの値 | セグメントの種類 |
---|---|
0010 | 読み書き可能データセグメント |
1010 | 実行と読み出し可能コードセグメント |
bit44(Sフラグ)
セグメントディスクリプタでは常に1です。
bit46-45(DPL)
セグメントへのアクセスに必要なCPUの特権レベルを指定するフィールドです。
00...セグメントへのアクセスに必要なCPUの特権レベルがカーネルモードであることを示しています。
11...セグメントへのアクセスに必要なCPUの特権レベルユーザーモードであることを示しています。
bit47(Pフラグ)
セグメントがメモリ上に存在するかしないかを示すフィールドです。
この値が1の時は、セグメントがメモリ上に常に存在することを示しています。
セグメントディスクリプタのbit55-48(segdesc構造体のg、db、rsv1、avl、lim_19_16)に値を設定する
(uint)(lim) >> 28, 0, 0, 1, 1,
セグメントディスクリプタのbit51-48、bit52、bit53、bit54、bit55(segdesc構造体のlim_19_16、avl、rsv1、db、g)にそれぞれ値を設定します。
bit51-48(リミット値)
リミット値の上位4bitをセグメントディスクリプタのbit51-48(segdesc構造体のlim_19_16)に設定します。
imの値(32bit)を28bit右シフト演算し0xfでマスク処理することにより、リミット値の上位4bitを取得しています。
bit52(AVL)
常に0の値です。
bit53(Lフラグ)
常に0の値です。
bit54(Dフラグ)
セグメントで使用されるアドレスサイズやデータサイズを指定するフラグです。
この値が1の時は、セグメントで使用されるアドレスサイズやデータサイズが32bitであることを示しています。
bit55(Gフラグ)
リミット値の単位を指定するフラグです。
この値が1の時は、リミット値の単位がページ(4KB)であることを示しています。