ページング
i386の仮想アドレス→物理アドレス変換を行なうテーブルを設定する処理。
pmap_enter(pmap, v, pn, prot, flags, wired)
pv_entryはpmapを参照。
pmap_enter(pmap, v, pn, prot, flags, wired)
PageDirectory,PageTableを設定して指定仮想アドレス(v)に物理ページ(pn:ページフレーム番号)をマッピングする。protでは許可するアクセス種別(Write可,Read可,コードの実行可)を指定する。
pmapから仮想アドレス(v)に該当するPageTableEntry(pte)を割出しPTEを設定する。また、物理ページから対応仮想アドレスを引くためのpv_entryも合わせて更新する。
PTEの2^9〜11bitのAvailフィールド(OSが自由に使ってよい領域)はxnuでは以下のように使用している。
#define INTEL_PTE_GLOBAL 0x00000100
#define INTEL_PTE_WIRED 0x00000200
pmapから仮想アドレス(v)に該当するPageTableEntry(pte)を割出しPTEを設定する。また、物理ページから対応仮想アドレスを引くためのpv_entryも合わせて更新する。
PTEの2^9〜11bitのAvailフィールド(OSが自由に使ってよい領域)はxnuでは以下のように使用している。
#define INTEL_PTE_GLOBAL 0x00000100
#define INTEL_PTE_WIRED 0x00000200
pmap_enter()の処理概要
old_pa = pte_to_pa(*pte);[参考]
if (old_pa == pa) {
PTEが存在して、マップする物理アドレスにも変更がない場合の処理
ページをReadOnlyに変更するなど属性を変更する時はこちらに入る
ProtectionなどBitを再設定してPTEに書き込んで終了
}
if (old_pa != (pmap_paddr_t) 0) {
すでに別の物理アドレスにマップされていた場合の処理。
指定ページにマップしなおすので、マップ済みの物理ページの
pv_entryを探しマップを切り放す(pv_h->pmap = PMAP_NULL)。
ページが共有されている場合はpv_hがnextチェーンされているので
チェーンをたどりエントリを探す。
} else {
新規マッピング
統計のみ更新以下の処理でマッピングを行なう
}
if (valid_page(i386_btop(pa))) {
マップ対象の物理ページのpv_entryを探して
pv_entryを作成する。
pv_h->va = v;
pv_h->pmap = pmap;
pv_h->next = PV_ENTRY_NULL;
物理ページが共有されていてpv_hが設定済みなら
pv_hのnextポインタに新しいエントリをつなぐ
pv_e->va = v;
pv_e->pmap = pmap;
pv_e->next = pv_h->next;
pv_h->next = pv_e;
}
PTEを作成して設定
pv_entryはpmapを参照。