はりぼて日記
2007 | 01 | 02 | 03 | 04 | 05 | 07 | 08 | 10
2006 | 11 | 12
10月 12 (金曜日) 2007
13:26
27日目2
 
P577

えーっと、まず、GDTをもう一回復習。

GDTはメモリ内の設けられた特別な意味を持つ領域。
(メモリのどこにするかは原則自由。GDTRというレジスタに番地を
設定すればそれでいい。)

たとえばGDTRに、0x10000を設定したとする。すると以降、CPUはここから
8,191までの範囲をGDTとして扱うようになる。
GDTは表。一個(一行?)に各要素があり、次の行へ移る。
(とりあえず1行は8バイト。64ビットある。これ刻みに行が移る)

┌────┬────┬───┬────┬─────┬───┐
│アドレス│GDT番号 │大きさ│開始番地│  属性 │   │
├────┼────┼───┼────┼─────┼───┤
│0x10000 │ 0  │   │    │     │   │
├────┼────┼───┼────┼─────┼───┤
│0x10008 │ 1  │   │    │     │   │
├────┼────┼───┼────┼─────┼───┤
│0x10010 │ 2  │   │    │     │   │
├────┼────┼───┼────┼─────┼───┤
│    │    │   │    │     │   │
  :     :   :    :    :    :
├────┼────┼───┼────┼─────┼───┤
│0x1FFF0 │ 8190 │   │    │     │   │
├────┼────┼───┼────┼─────┼───┤
│0x1FFF8 │ 8191 │   │    │     │   │
└────┴────┴───┴────┴─────┴───┘


これに対して普通にGDTを一個設置したい場合は各項目に書式に
したがってデーアを当て込めばいい。たとえば、
・あるセグメントを0x80000〜0x90000(64kb)として作りたい
・このセグメントはアプリが使う(コード)
・とりあえず0、1はOSで使われているようなので、2番とする。

こうしたい場合、

├────┼────┼───┼────┼─────┼───┤
│0x10010 │ 2  │64kb │0x80000 │アプリ用C │   │
├────┼────┼───┼────┼─────┼───┤


こう設定すればいい。
これでメモリ0x80000〜0x90000がアプリ用のセグメントとして管理
されるようになる。アクセスする場合はセグメント2番として行う。

IDTというのがある。IDTは割り込みが来た時にどの番地にジャンプ
するのかを、同じようにメモリの一部にずらーっと書いてある。
どこからどこまでがIDTなのか?という設定も、同じくレジスタ
に書き込めばいい。IDTLレジスタにIDTのスタート地点としたい
番地を設置してOK。

さてここで問題が生じる。
マルチタスクでは他に、TSSという設定一覧表が必要になる。
TSSはレジスタの退避エリア&タスクの設定が書かれた表である。
この流れで行けば、CPUのどこかにTSSLなんてレジスタがありそう
だがこれはない。
TSSはGDTで設置する。つまり、どこか適当な番号のセグメントを
設置して、そこはメモリとかではなくTSSなんだという属性を
与える。例えば、

・メモリ0xA0000を、あるタスクのTSSとして設置したい。
・TSSはどこにでも設置できるが大きさが決まっている(それ以上いらない)

なんて場合は、

├────┼────┼───┼────┼─────┼───┤
│0x10018 │ 3  │104b │0xA0000 │TSS用   │   │
├────┼────┼───┼────┼─────┼───┤

こうしてあげれば0xA0000〜0xA0103までがTSSになる。

・・・はっはぁ・・・・

こうやって整理してみたら、ちょっとわかってきたぞ??

TSSはGDTのように専用のレジスタを使ってポンと設定できない。
変則的だがGDT内に、「俺はTSSだー!」と設定するわけ。
同じような考え方でLDTを作るわけ。
LDTはGDTとそっくりな構造だけど、「どこからどこまでがLDTか?」
という設定をレジスタではなくGDTセグメントにて設定するわけ。

たとえばLDTを0xB0000に設置したいとする。流れからすると、LDTLなんて
レジスタがCPUにありそうだが違う。TSSと同じく、どこか適当な
GDTに設置する。(空いているところでいいようだ。)
具体的には

├────┼────┼───┼────┼─────┼───┤
│0x10020 │ 4  │15b  │0xB0000 │LDT用   │   │
├────┼────┼───┼────┼─────┼───┤


これで0xB0000から始まる、GDTとそっくりな表が形成される。
大きさを表すパラメータ。(今回は15bとしている)これは最大値(64KB)は決まっているがいくつでも構わない。GDT
の場合は開始番地をレジスタに設置した瞬間、自動的に最大値まで
が確保されるが、LDTは必要な分だけでよい。今回は2個しか
必要じゃないのでこれでいい

この作業を行った後には、

┌────┬────┬───┬────┬─────┬───┐
│アドレス│LDT番号 │大きさ│開始番地│  属性 │   │
├────┼────┼───┼────┼─────┼───┤
│0xB0000 │ 0  │   │    │     │   │
├────┼────┼───┼────┼─────┼───┤
│0xB0008 │ 1  │   │    │     │   │
└────┴────┴───┴────┴─────┴───┘

こんな感じでLDTが作られる。
仮にこのLDTで0xC0000から始まる64KBのセグメントを二つ作るとしよう。


┌────┬────┬───┬────┬─────┬───┐
│アドレス│LDT番号 │大きさ│開始番地│  属性 │   │
├────┼────┼───┼────┼─────┼───┤
│0xB0000 │ 0  │64KB │0xC0000 │アプリ用C │   │
├────┼────┼───┼────┼─────┼───┤
│0xB0008 │ 1  │64KB │0xD0000 │アプリ用D │   │
└────┴────┴───┴────┴─────┴───┘

こうなる。

さて!!!!!!!!!!!!

このLDTで定義されているセグメント(0xC0000〜)を使えるのは
誰か? 誰でも使えるのか?? いやそれでは困る。

そこで、各タスクを管理しているTSSに、このLDTを使ってもいいと
設定をする。このLDTを作っているのはGDTの4番である。
TSS内のldtrに4番と指定を入れると、このLDT(で定義されているセグメントのメモリエリア)(0xC0000〜0xDFFFF)は
このTSSからしかアクセスできなくなる。
(ちょっち言い方が変かな? ldtrを4番と指定されているTSSからしかアクセスできなくなるが正しいかな






こういうことかあぁぁぁぁ!!!!!!!!!!!
 
30日を過ぎたBlogにはコメントできません。

Referer  (44)
(1) 2 3 4 5 6 7 8 9 10 » 

PopnupBlog V3 Denali created by Bluemoon inc.