2章 linuxカーネル - メモリ管理1

99
2Linuxカーネル - メモリ管理1 mao Web >http://www.pridact.com Twitter >https://twitter.com/rivarten Blog >http://rivartender.blog.fc2.com Mail >[email protected]

Upload: mao999

Post on 23-Feb-2017

1.340 views

Category:

Software


0 download

TRANSCRIPT

Page 1: 2章 Linuxカーネル - メモリ管理1

2章 Linuxカーネル - メモリ管理1

mao

Web >http://www.pridact.comTwitter >https://twitter.com/rivartenBlog >http://rivartender.blog.fc2.comMail >[email protected]

Page 2: 2章 Linuxカーネル - メモリ管理1

はじめに

メモリ管理におけるハードウェア寄りの話

視点・x86プロセッサのメモリ割当て回路・x86_64ではどうなっているか・Linuxカーネルがメモリ割当て回路を どのように利用するか

Page 3: 2章 Linuxカーネル - メモリ管理1

この資料について

・間違っていたらご指摘をお願い致します。・Linux Kernelのバージョンは4.2です。・ページタイトルに*印が付いているページは、 少し踏み込んだ内容になっています。 ざっと全体に目を通したければ、読み飛ばして もらっても構いません。

Page 4: 2章 Linuxカーネル - メモリ管理1

メモリ割当て回路:MMU

・MMU(Memory Management Unit):メモリ管理ユニット CPUのメモリアクセスを処理する装置  1.アドレス変換機能  2.メモリ保護機能  3.キャッシュ制御機能  4.バス調停機能  etc.. メモリ管理ユニット - Wikipedia https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%A2%E3%83%AA%E7%AE%A1%E7%90%86%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88

Page 5: 2章 Linuxカーネル - メモリ管理1

流れ

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 6: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - 概要

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 7: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - 概要(1)

論理アドレス  ↓[セグメンテーション回路]

  ↓リニアアドレス/仮想アドレス  ↓[ページング回路]

  ↓物理アドレス

  MMU内のセグメンテーション回路とページング回路を経由して、  論理アドレスから物理アドレスに変換する。

Page 8: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - 概要(2)

 ・論理アドレス  機械語命令において、オペランドや命令のアドレスを指定する時に使用するアドレス。  セグメントセレクタ(16bit)とオフセット(32bit/64bit)で指定。  セグメントセレクタはセグメントレジスタ(cs)に格納される。  アプリケーションでのアドレスの指定は、オフセットを指定する事になる。  セグメントセレクタについては後述。  ・セグメント  メモリ領域

 ・リニアアドレス/仮想アドレス  一般に言う仮想アドレス。  32bit環境だと4GB。64bit環境(実質48bit)だと256TB。  論理アドレスから物理アドレスに変換する際の、一次変換後のアドレス。  [32bit環境]0x0000 0000~0xffff ffffまでの32bit符号なし整数。  [64bit環境]0x0000 0000 0000 0000~0xffff ffff ffff ffffまでの64bit符号なし整数。        0x0000 0000 7fff ffff→0xffff ffff 8000 0000(符号拡張)

 ・物理アドレス  メモリチップ内のメモリセルを指定する際に実際に使用する。  メモリセルの指定=プロセッサのアドレスピンを通じて、  電気信号をメモリバスに送ること。  32bit環境だと32bit/36bitの符号なし整数。64bit環境では48~52bit。

Page 9: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 10: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(1)

・セグメントディスクリプタ/セグメント識別子 セグメントの特性・属性を示す。

 64bit長(8byte)

・セグメントディスクリプタテーブル セグメントディスクリプタを格納する表。 メモリ上の任意の場所に置かれる。 GDT(Global Descriptor Table) LDT(Local Descriptor Table)

・セグメントセレクタ セグメントディスクリプタを選択する16bitの値。

Page 11: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(2)

・セグメントセレクタ          ・セグメントディスクリプタテーブル ・GDT(Global Descriptor Table)  システムに1つのみ存在するテーブル。

 ・LDT(Local Descriptor Table)  各プロセス固有のテーブル。  プロセスが任意で持つ。

bit 内容

15~3 インデックス値。GDTかLDT内にある、対応するセグメントディスクリプタを示す。

2 TI(Table Indicator)0:GDTにある。  1:LDTにある。

1,0 RPL(Requestor Privilege Level)/リクエスタ特権レベルLinuxカーネルでは、CPL(Current Privilege Level)/現行特権レベルとして扱っている。0:カーネル  3:ユーザ1,2:仮想化マシン

Page 12: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(3)

・セグメントディスクリプタのフィールド内容

フィールド名 内容ベース セグメント先頭のリニアアドレス

G Granularity/粒度。セグメント長の単位。0:byte 1:page

リミット セグメント終端のメモリセルのオフセット=セグメント長。G=0: 1byte~1MB G=1:4KB~4GB

S システムフラグ0:システムセグメント。重要なデータを置く。1:通常のコードセグメント、データセグメント。

タイプ セグメントの種類、アクセス権。

DPL Descriptor Privilege Levelセグメントへのアクセスに必要な特権レベル0:カーネル 3:ユーザ

P Presentセグメント存在フラグ。メインメモリ上に存在するかどうか。0:存在しない 1:存在する(Linuxではセグメント全体をスワップアウトする事はない⇒常に1)

D/B デフォルトのオペレーションサイズ/デフォルトのスタックポインタサイズ0:16bit 1:32bit

AVL 使用可能ビット。OS用。Linuxでは不使用。

Page 13: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(4)

・セグメントディスクリプタの種類 1.コードセグメントディスクリプタ 2.データセグメントディスクリプタ 3.システムセグメントディスクリプタ 4.タスク状態セグメントディスクリプタ  (Task State Segment:TSS) 5.ローカルディスクリプタテーブルディスクリプタ

Page 14: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(5)

・コードセグメントディスクリプタ ・GDT or LDT内にある。 ・コードセグメントを表す。 ・S=1(非システムセグメント)

bit 内容

63~56 ベース(31~24bit)

55 G

54 D(/B)

53 0

52 AVL

51~48 リミット(19~16bit)

47 1

46~45 DPL

44 S=1

43~40 タイプ

39~32 ベース(23~16bit)

31~16 ベース(15~0bit)

15~0 リミット(15~0bit)

Page 15: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(6)

・コードセグメントディスクリプタ ・GDT or LDT内にある。 ・データセグメントを表す。 ・S=1(非システムセグメント) ・スタックセグメントは、汎用データセグメントの1つ。

bit 内容

63~56 ベース(31~24bit)

55 G

54 (D/)B

53 0

52 AVL

51~48 リミット(19~16bit)

47 1

46~45 DPL

44 S=1

43~40 タイプ

39~32 ベース(23~16bit)

31~16 ベース(15~0bit)

15~0 リミット(15~0bit)

Page 16: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(7)

・システムセグメントディスクリプタ ・S=0(システムセグメント)

bit 内容

63~56 ベース(31~24bit)

55 G

54 ―

53 0

52 ―

51~48 リミット(19~16bit)

47 1

46~45 DPL

44 S=0

43~40 タイプ

39~32 ベース(23~16bit)

31~16 ベース(15~0bit)

15~0 リミット(15~0bit)

Page 17: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(8)

・タスク状態セグメントディスクリプタ ・GDT内にある。 ・プロセッサのレジスタ群の内容を退避する為に利用。 ・S=0(システムセグメント)

bit 内容

63~56 ベース(31~24bit)

55 G

54 (D/)B

53 0

52 AVL

51~48 リミット(19~16bit)

47 1

46~45 DPL

44 S=0

43~40 タイプ 11 or 9

39~32 ベース(23~16bit)

31~16 ベース(15~0bit)

15~0 リミット(15~0bit)

Page 18: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(9)

・ローカルディスクリプタテーブルディスクリプタ ・GDT内にある。 ・LDTを含むセグメントを参照。 ・S=0(システムセグメント)

bit 内容

63~56 ベース(31~24bit)

55 G

54 (D/)B

53 0

52 AVL

51~48 リミット(19~16bit)

47 1

46~45 DPL

44 S=0

43~40 タイプ 2

39~32 ベース(23~16bit)

31~16 ベース(15~0bit)

15~0 リミット(15~0bit)

Page 19: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(10)

・セグメントディスクリプタへの高速アクセス法

 1回のメモリアクセスをする為に、MMUは2回メモリを参照しなければならない為、 そのままでは低速。  1回目:メモリ上のセグメントディスクリプタにアクセス  2回目:セグメントにアクセス ⇒ 各種セグメントレジスタと対応する、 6個のノンプログラマブルな64bit(8byte)長のレジスタを利用。 ノンプログラマブルレジスタ内にセグメントディスクリプタを格納し、 アクセスする事で高速化を図る。

 <セグメントレジスタの値を変更する時> 1.セグメントセレクタをセグメントレジスタに書込む。 2.セグメントディスクリプタをメモリからノンプログラマブルレジスタにコピー。 3.ノンプログラマブルレジスタ内のセグメントディスクリプタにアクセス。 4.セグメントにアクセス。

 <セグメントレジスタの値を変更しない時> 1.ノンプログラマブルレジスタ内のセグメントディスクリプタにアクセス 2.セグメントにアクセス。

Page 20: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるセグメンテーション(11)

・リニアアドレス変換

 リニアアドレス = セグメントセレクタ*8            + (gdtr or ldtr) + オフセット

  ※gdtr,ldtrのどちらを選択するかは、セレクタのTIフィールドで判別.

 ※リアルモード時  リニアアドレス = セグメントセレクタ*16 + オフセット

Page 21: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86_64におけるセグメンテーション

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 22: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86_64におけるセグメンテーション

  ・DS,ES,SSのセグメントレジスタは使用されない。

 ・CSは使用する。  セグメントのベース、リミットは無視され、フラットメモリモデルとなる。  (Linuxはもともとフラットモデルなので影響なし)

 ・DフラグとLフラグ(bit53)の組み合わせで、互換モード、64bitモード決定  Dフラグ=0,Lフラグ=1で64bitモード。  (0章 x86 – 動作モード 遷移手続き参照)

 ・FS,GSセグメントはベース、リミット設定可能。  ベースフィールドが32bitしかない為、MSRに設定する。  (Linuxでは使用しない)

Page 23: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 24: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(1)

・Linuxでは、全プロセスで同じ値のセグメントレジスタを利用。 同じリニアアドレス空間を共有してメモリ管理簡略化。

・Linuxは広範囲アーキテクチャへの移植性を確保する為に、 セグメント機構を限定的に使っているRISCにも対応する必要があり、 セグメント機構は限定的に使用し、ページング機構をメインに利用。

・アドレス範囲が同じ ⇒ユーザーモード・カーネルモード問わず  同じ論理アドレスを使用可能。

・セグメントベース値が0 & (論理アドレス=リニアアドレス) ⇒常に論理アドレスのオフセットフィールドがリニアアドレスと一致。  基本フラットモデル。  最低でもコードセグメントとデータセグメントが必要。    ※コードセグメントにデータを書き込めない。

 

Page 25: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(2)

・Linuxにおける主なセグメントの種類(x86)

 1.ユーザコードセグメント __USER_CS 2.ユーザデータセグメント __USER_DS 3.カーネルコードセグメント __KERNEL_CS 4.カーネルデータセグメント __KERNEL_DS

・Linuxにおける主なセグメントの種類(x86_64)

 1.32bitユーザコードセグメント __USER32_CS 2.32bitユーザデータセグメント __USER32_DS 3.64bitユーザーコードセグメント __USER_CS 4.64bitユーザーデータセグメント __USER_DS 5.32bitカーネルコードセグメント __KERNEL32_CS 6.64bitカーネルコードセグメント __KERNEL_CS 7.64bitカーネルデータセグメント __KERNEL_DS

Page 26: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(3)

・__USER_CS

フィールド名 値

ベース 0x00000000

G 1

リミット 0xFFFFF

S 1

タイプ 5

DPL 3

D/B 1

P 1

・__USER_DS

フィールド名 値

ベース 0x00000000

G 1

リミット 0xFFFFF

S 1

タイプ 1

DPL 3

D/B 1

P 1

Linuxにおける主なセグメントの種類(x86)(1)

Page 27: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(4)

・__KERNEL_CS

フィールド名 値

ベース 0x00000000

G 1

リミット 0xFFFFF

S 1

タイプ 5

DPL 0

D/B 1

P 1

・__KERNEL_DS

フィールド名 値

ベース 0x00000000

G 1

リミット 0xFFFFF

S 1

タイプ 1

DPL 0

D/B 1

P 1

Linuxにおける主なセグメントの種類(x86)(2)

Page 28: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(5)

・LinuxにおけるGDT(1) x86 versionセグメントセレクタ 内容 セグメントセレクタ 内容

[0]0x00 nullセグメント [16]0x80 TSS descriptor

[1]0x08 reserved(null seg) [17]0x88 LDT descriptor

[2]0x10 reserved(BOOT_CS) [18]0x90 PnP BIOS 32bit code

[3]0x18 reserved(BOOT_DS) [19]0x98 PnP BIOS 16bit code

[4]0x20 unused(BOOT_TSS) [20]0xA0 PnP BIOS data

[5]0x28 unused [21]0xA8 PnP BIOS 16bit ts1

[6]0x30 TLS entry 1(glibc) [22]0xB0 PnP BIOS 16bit ts2

[7]0x38 TLS entry 2(Wine) [23]0xB8 APM CS 32bit BIOS code

[8]0x40 TLS entry 3 [24]0xC0 APM CS 32bit BIOS code

[9]0x48 reserved [25]0xC8 APM DS data

[10]0x50 reserved [26]0xD0 ESPFIX small SS

[11]0x58 reserved [27]0xD8 per-cpu

[12]0x60 __KERNEL_CS [28]0xE0 stack_canary-20

[13]0x68 __KERNEL_DS [29]0xE8 unused

[14]0x73(70+3) __USER_CS [30]0xF0 unused

[15]0x7B(78+3) __USER_DS [31]0xF8 double-fault TSS

Page 29: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(6)

・LinuxにおけるGDT(2)

 1.TSS(Task State Segment)  ・システムのプロセッサ毎に用意しているセグメントディスクリプタ。  ・TSSのリニアアドレス空間は、__KERNEL_DSのリニアアドレス空間の一部にマッピング。  ・タイプ = 9 or 11(32bit TSSを有効化)

 2.LDT(Local Descriptor Table)  ・標準初期設定のLDTのセグメント。  ・通常、全てのプロセスがこのセグメントを共有。

 3.TLS(Thread-Local Storage)  ・マルチスレッドアプリケーションにおける、スレッド固有データを保持するセグメント。   set_thread_area()システムコール:確保   get_thread_area()システムコール:解放

Page 30: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(7)

・LinuxにおけるGDT(3)

 4.PnP(Plug-and-Play)  ・PnPドライバはBIOS機能を呼び出し、PnPデバイスが使用しているハードウェアを検出。  ・専用のコードセグメントとデータセグメントを利用する。

 5.APM(Advanced Power Management)  ・APMドライバは、APMデバイスの状態を取得・設定する際に、BIOS機能を呼び出す。  ・専用のコードセグメントとデータセグメントを利用する。

 6.double-fault TSS  ・カーネルがダブルフォルト例外を処理する為に使用する特別なTSS。

・LinuxにおけるLDT

  Linuxのユーザーモードアプリケーションのほとんどは、LDTを使わない。

Page 31: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(8)

・__USER32_CS

フィールド名 値

ベース 0x00000000

G 1

リミット 0xFFFFF

S 1

タイプ 5

DPL 3

D 1

L 0

P 1

・__USER32_DS __USER_DS

フィールド名 値

ベース 0x00000000

G 1

リミット 0xFFFFF

S 1

タイプ 1

DPL 3

D 1

L 0

P 1

Linuxにおける主なセグメントの種類(x86_64)(1)

・__USER_CS

フィールド名1 値

ベース 0x00000000

G 1

リミット 0xFFFFF

S 1

タイプ 5

DPL 3

D 0

L 1

P 1

Page 32: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(9)

・__KERNEL32_CS

フィールド名 値

ベース -

G 1

リミット -

S 1

タイプ 5

DPL 0

D 1

L 0

P 1

・__KERNEL_DS

フィールド名 値

ベース -

G 1

リミット -

S 1

タイプ 1

DPL 0

D 1

L 0

P 1

Linuxにおける主なセグメントの種類(x86_64)(2)

・__KERNEL_CS

フィールド名1 値

ベース -

G 1

リミット -

S 1

タイプ 5

DPL 0

D 0

L 1

P 1

Page 33: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(10)

・LinuxにおけるGDT x86_64 versionセグメントセレクタ 内容 セグメントセレクタ 内容

[0]0x00 nullセグメント [8]0x40 TSS

[1]0x08 __KERNEL32_CS [9]0x48 unused

[2]0x10 __KERNEL_CS [10]0x50 LDT

[3]0x18 __KERNEL_DS [11]0x58 unused

[4]0x23(20+3) __USER32_CS [12]0x63(60+3) TLS 1(GS_TLS_SEL)

[5]0x2B(28+3) __USER_DS__USER32_DS

[13]0x6B(68+3) TLS 2(FS_TLS_SEL)

[6]0x33(30+3) __USER_CS [14]0x70 TLS 3

[7]0x38 unused [15]0x7B(78+3) __PER_CPU_SEG

Page 34: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるセグメンテーション(11)*

・Linuxにおけるセグメントのデータ構造/初期化

 ・desc_struct構造体   64bit(8byte)のセグメントディスクリプタの構造体   [ver4.2 arch/x86/include/asm/desc_defs.h:22]

 ・セグメントの識別子定義   [ver4.2 arch/x86/include/asm/segment.h]

 ・gdt_page構造体   GDT   ・定義[ver4.2 arch/x86/include/asm/desc.h:42]

   ・初期化[ver4.2 arch/x86/kernel/cpu/common.c:94]

   ・TLS,TSS,LDTは別のタイミングで初期化

Page 35: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – x86におけるページング

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 36: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – x86におけるページング(1) - 概要

・ページング機構 仮想的に連続したメモリ空間や、 他のプログラムから独立したメモリ空間を提供。

   ・ページフレーム     リニアアドレスの分割枠

   ・ページ     ページフレーム内に配置する実際のデータ

   ・ページテーブル(アドレス変換テーブル)     リニアアドレスを物理アドレスにマッピングするデータ構造

 cr0制御レジスタのPGフラグ=1でページング有効化。 PGフラグ=0でリニアアドレス=物理アドレス。

Page 37: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – x86におけるページング(2)

・通常ページング

  ・リニアアドレス   リニアアドレス32bit。4KBページ。

   ページディレクトリ、ページテーブル共に2^10=1024エントリのテーブルを持つ。    各エントリは、メモリ上の任意の場所に配置される。    

  ・物理アドレス変換    ・cr3制御レジスタ      (ページディレクトリ・base) + ページディレクトリoffset = ページテーブルbase    ・ページテーブルbase + ページテーブルoffset = ページbase    ・ページbase + ページoffset = 物理アドレス

    ※ページウォーク      変換の為にページテーブルを辿っていくこと。      メモリの複数箇所を読み取り計算しなければならない為、時間がかかる。

index bit数 内容

31~22 10bit ページディレクトリoffset

21~12 10bit ページテーブルoffset

リミット 12bit ページoffset

Page 38: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるページング(3)

・各テーブルエントリのフィールド(1)

フィールド 内容

G グローバルページテーブルエントリの場合のみ使用。頻繁に使用するページがTLBから追い出されるのを防ぐ事が出来るフラグ。

(Pentium Pro以降)cr4制御レジスタのPGEフラグ=1で有効化。0:TLBからクリアする 1:TLBからクリアしない

PS ページサイズページディレクトリエントリの場合のみ使用。0:4KB 1:2MB or 4MB

D ダーティページテーブルエントリの場合のみ使用。ページング回路は、ページフレームに対する書き込み処理が行われる度に、Dフラグを1にする。Dフラグを0にするのはOS。0:ページテーブル/ページは書き込まれていない1:ページテーブル/ページは書き込まれたメモリの内容をディスクに書き戻す必要があるかの判定に使用

※TLBはキャッシュ的存在。後述。

Page 39: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるページング(4)

・各テーブルエントリのフィールド(2)フィールド 内容

A アクセス済みページング回路は、対応するページフレームにアクセスする度に、Aフラグを1にする。Aフラグを0にするのはOS。0:ページテーブル/ページはアクセスされていない1:ページテーブル/ページはアクセス済みあるタイミングでクリアし、その後全エントリのAフラグをチェックすると、最近アクセスされたかどうか判定できる。スワップデバイスに退避するページを選択するのに利用。

PCD ページレベルキャッシュディスエーブル0:キャッシング可能 1:キャッシング禁止

PWT ページレベルライトスルー0:ライトバックキャッシング可能1:ライトスルーキャッシング可能

U/S ユーザ/スーパーバイザ0:スーパーバイザ 1:ユーザ

R/W アクセス権0:R 読み取り専用 1:RW 読み書き可能

P 存在0:ページテーブル/ページが存在しない 1:ページテーブル/ページが存在する0⇒ページング回路は、変換失敗したリニアアドレスをcr2制御レジスタに保存。  その後、14番の例外(ページフォールト例外)を発生させる。

Page 40: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるページング(5)

ページディレクトリエントリPDE

index bit数 内容

31~12 20 ページテーブルbase

11~9 3 -(AVAIL未使用)

8 1 -(G未使用)

7 1 PS=0

6 1 -(D未使用)

5 1 A

4 1 PCD

3 1 PWT

2 1 U/S

1 1 R/W

0 1 P

ページテーブルエントリPTE

index bit数 内容

31~12 20 ページフレームbase

11~9 3 -(AVAIL未使用)

8 1 G=0

7 1 -(PS未使用)

6 1 D

5 1 A

4 1 PCD

3 1 PWT

2 1 U/S

1 1 R/W

0 1 P

Page 41: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – x86におけるページング(6)

・拡張ページングPSE(Page Size Extension)  PDEのPS=1 & cr4制御レジスタPSE=1  ⇒4MBページサイズ  PDE毎に設定する為、  4KBページと4MBページを混在させる事も可能。

  ※PSE-36(Page Size Extension-36)   Pentium Ⅲから導入されたが、Linuxは使用していない。

Page 42: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – x86におけるページング(7)

・物理アドレス拡張PAE(Physical Address Extension)

 ・OS1GB問題  Linuxのリニアアドレス4GBの内約   ユーザーモードプロセス:3GB  OS:1GB  OSは1GBでやりくりする必要あり。巨大サーバでは足りない  ・対策(Pentium Pro以降)  アドレスピン32本→36本に拡張⇒物理アドレス空間4GB→64GB利用可能

  ・リニアアドレスは32bitのまま  ・ページテーブルエントリのページフレームbase 20bit→24bit     64GB RAMを2^24個のページフレームに分割  ・ページテーブルエントリのサイズ32bit→64bit     ページフレームbase 24bit + オフセット 12bit = 36bitでオーバーの為。  ・ページディレクトリポインタテーブルPDPT(Page Directory Pointer Table)導入     各エントリ64bitの4エントリ。ページディレクトリの上階層に置く。cr3制御レジスタでbase指定

 ※ページテーブル操作が可能なのはOSのみ  ⇒OSは物理アドレスを最大64GB利用可能。   ユーザーモードプロセスは4GBのまま。 ※PAE有効kernelは無効kernelを使用した場合よりも、最大で50%の性能低下。  PAE有効kernelでは、ページテーブル構造の階層が1つ多い為、  TLBがミスヒットした場合のペナルティーが大きい。  メモリを大量に管理している為、TLBヒット率があまり高くない。

Page 43: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86におけるページング(8)

index bit数 内容

31~30 2 PDPT offset

29~21 9 PDE offset

20~12 9 PTE offset

11~0 12 Page offset

index bit数 内容

31~30 2 PDPT offset

29~21 9 PDE offset

20~0 20 Page offset

・PAE有効時の32bitリニアアドレスの内約

 ・PDEのPSフラグ=0(4KBページ)

   cr3制御レジスタ:PDPT base

 ・PDEのPSフラグ=1(2MBページ)

   cr3制御レジスタ:PDPT base

Page 44: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – x86_64におけるページング

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 45: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86_64におけるページング(1)

アーキテクチャ 有効アドレスbit数

ページング階層数 リニアアドレス分割方法

alpha 43 3 10 + 10 + 10 + 13

ia64 39 3 11 + 11 + 11 + 14

ppc64 41 3 10 + 10 + 9 + 12

sh64 41 3 10 + 10 + 9 + 12

x86_64 48 4 9 + 9 + 9 + 9 + 12

・64bitアーキテクチャにおけるページング

Page 46: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86_64におけるページング(2)

・64bitモードのページング(1)

  ・リニアアドレス48bit  ・PDPT、ページマップレベル4(Page Map Level 4)を導入   合計で4階層のアドレス変換テーブル(PML4,PDPT,PD,PT)。

    cr3制御レジスタ:PML4 base

index bit数 内容

63~49 16 符号拡張

47~39 9 PML4 offset

38~30 9 PDPT offset

29~21 9 PD offset

20~12 9 PT offset

11~0 12 Page offset

Page 47: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86_64におけるページング(3)

PML4 Entryindex bit数 内容

63 1 XD

62~52 11 -(AVAIL未使用)

51~40 12 -(予約済み,PDPT base未使用,0)

39~12 28 PDPT base

11~9 3 -(AVAIL未使用)

8 1 -(G未使用)

7 1 -(予約済み,PS=0)

6 1 -(D未使用)

5 1 A

4 1 PCD

3 1 PWT

2 1 U/S

1 1 R/W

0 1 P

PDPT Entry・64bitモードのページング(2)

index bit数 内容

63 1 XD

62~52 11 -(AVAIL未使用)

51~40 12 -(予約済み,PD base,0)

39~12 28 PD base

11~9 3 -(AVAIL未使用)

8 1 -(G未使用)

7 1 -(予約済み,PS=0)0:4KB 1:1GB

6 1 -(D未使用)

5 1 A

4 1 PCD

3 1 PWT

2 1 U/S

1 1 R/W

0 1 P

Page 48: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86_64におけるページング(4)

PD Entryindex bit数 内容

63 1 XD

62~52 11 -(AVAIL未使用)

51~40 12 -(予約済み,PT base,0)

39~12 28 PT base

11~9 3 -(AVAIL未使用)

8 1 -(G未使用)

7 1 PS0:4KB 1:2MB

6 1 -(D未使用)

5 1 A

4 1 PCD

3 1 PWT

2 1 U/S

1 1 R/W

0 1 P

PT Entry

・64bitモードのページング(3)

index bit数 内容

63 1 XD

62~52 11 -(AVAIL未使用)

51~40 12 -(予約済み,Page base,0)

39~12 28 Page base

11~9 3 -(AVAIL未使用)

8 1 G

7 1 PAT

6 1 D

5 1 A

4 1 PCD

3 1 PWT

2 1 U/S

1 1 R/W

0 1 P

Page 49: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - x86_64におけるページング(5)

・64bitモードのページング(4)  ページサイズが3通り:4KB,2MB,1GB   4KB     ・フラグ       PDPE:PS=0,PDE:PS=0     ・変換パス       PML4E→PDPE→PDE→PTE→Page     ・リニアアドレス分割       9,9,9,9,12   2MB     ・フラグ       PDPE:PS=0,PDE:PS=1     ・変換パス       PML4E→PDPE→PDE→Page     ・リニアアドレス分割       9,9,9,0,21   1GB     ・フラグ       PDPE:PS=1     ・変換パス       PML4E→PDPE→Page     ・リニアアドレス分割       9,9,0,0,30

Page 50: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – Linuxにおけるページング

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 51: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – Linuxにおけるページング(1)

・32bit/64bit両対応の4階層アドレス変換テーブル

・リニアアドレス内約  ・PGD:ページグローバルディレクトリ  ・PUD:ページアッパーディレクトリ  ・PMD:ページミドルディレクトリ  ・PTE:ページテーブル  ・Page offset

   ※リニアアドレス内約の各bit数はアーキテクチャ/設定依存。    階層を減らすには、リニアアドレスにおける該当テーブルのbit数を0にする。    ただし、ディレクトリエントリは各々1つずつ残し、    ポインタを辿る処理を残すことで32bit/64bit両対応。

・物理アドレス変換  ・cr3制御レジスタ    (PGD base) + PGD offset = PUD base  ・PUD base + PUD offset = PMD base  ・PMD base + PMD offset = PTE base  ・PTE base + PTE offset = Page base  ・Page base + Page offset= 物理アドレス

Page 52: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – Linuxにおけるページング(2)

・PAE無効 & 32bitアーキテクチャ  ・2階層 ⇒ PUD,PMDのbit数=0  ・Linuxとx86のページ変換テーブル対応    PGD = x86 PD    PUD = なし    PMD = なし    PTE = x86 PT

・PAE有効 & 32bitアーキテクチャ  ・3階層 ⇒ PUDのbit数=0  ・Linuxとx86のページ変換テーブル対応    PGD = x86 PDP    PUD = なし    PMD = x86 PD    PTE = x86 PT 

Page 53: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – Linuxにおけるページング(3)

・64bitアーキテクチャ 64bitモード  ・4階層  ・Linuxとx86_64のページ変換テーブル対応    PGD = x86_64 PML4    PUD = x86_64 PDP    PMD = x86_64 PD    PTE = x86_64 PT

Page 54: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – Linuxにおけるページング(4)

・Linuxのプロセス処理とページング機構 Linuxのプロセス処理は、ページング機構に大きく依存。

 ・プロセス毎に異なる物理アドレス空間を与え、  かつ変換エラーに対して確実な保護機構が働く。

 ・データの集まりであるページと、メインメモリ上の  物理アドレスの集まりであるページフレームを区別。  これにより、あるページをページフレーム内に置き、  その後ディスクに退避させた後に、別のページフレーム内に  読み込むことも可能。

 ・cr3制御レジスタの内容をプロセスの状態を保存するディスクリプタに退避。  次のプロセスのディスクリプタからcr3制御レジスタの値を読み込む。  これにより、ページング回路も新しいページテーブルを指す様になる。

Page 55: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるページング(5)*

・ページテーブル操作(1) マクロ(1)マクロ 内容

PAGE_SHIFT オフセットフィールドのビット長。x86:12。PAGE_SIZEマクロがページ長を返す為に使用。

PAGE_SIZE ページ長を返す

PAGE_MASK 0xFFFFF000を返し、オフセットフィールドのビットをマスクする時に使用。

PMD_SHIFT リニアアドレスのオフセットフィールドとテーブルフィールドのビット長の合計。PMDの1エントリがマッピングするビット長。PAE無効:22 PAE有効:21

PMD_SIZE PMDの1エントリがマッピングできる領域の大きさ。PAE無効:2^22(4MB) PAE有効:2^21(2MB)

PMD_MASK オフセットフィールドとテーブルフィールドの全ビットをマスクする時に使用。

Page 56: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるページング(6)*

・ページテーブル操作(2) マクロ(2)

[ver4.2 arch/x86/include/asm/pgtable-2level_types.h][ver4.2 arch/x86/include/asm/pgtable-3level_types.h]

マクロ 内容

PUD_SHIFT PUDの1エントリがマッピングできる領域サイズのビット合計。x86:PUD_SHIFT=PMD_SHIFT

PUD_SIZE PUDの1エントリがマッピングできる領域のサイズ。x86:4MB or 2MB(PMDに依存)

PUD_MASK オフセット、テーブル、ミドルディレクトリの全ビットをマスクする時に利用。

PGDIR_SHIFT PGDの1エントリがマッピングできる領域サイズのビット合計。x86:PGDIR_SHIFT=PMD_SHIFT,PUD_SHIFTPAE無効:22 PAE有効:30

PGDIR_SIZE PGDの1エントリがマッピングできる領域のサイズ。PAE無効:4MB PAE有効:1GB

PGDIR_MASK オフセット、テーブル、ミドルディレクトリ、アッパーディレクトリの全ビットをマスクする時に利用。0xC0000000

PTRS_PER_PTEPTRS_PER_PMDPTRS_PER_PUDPTRS_PER_PGD

各エントリ数を計算。PAE無効:1024,1,1,1024 (2段)PAE有効:512,512,1,4  (3段)

Page 57: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるページング(7)*

・ページテーブル操作(3) ページ変換テーブルのエントリ

 ・型変換マクロ  符号なし整数→エントリの型   __pte,__pmd,__pud,__pgd,__pgprot  エントリの型→符号なし整数   pte_val,pmd_val,pud_val,pgd_val,pgprot_val

 ・指定値書き込み   set_pte,set_pmd,set_pud,set_pgd,set_pte_atomic

型 内容

pgd_t PGDエントリ

pud_t PUDエントリ

pmd_t PMDエントリ

pte_t PTエントリ

pgprot_t エントリの保護フラグ

Page 58: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるページング(8)*

・ページテーブル操作(4) ページ割り当て関数(1) PGD,PUDマクロ 内容

pgd_alloc PGDの作成

pgd_free PGDの解放

pgd_offset リニアアドレスに対応するPGDエントリのアドレスを取得

pgd_none PGDエントリが空かどうか判定

pgd_bad PGDエントリが不正かどうか判定

pgd_clear PGDエントリをクリアする

pud_alloc_one PUDの作成

pud_free PUDの解放

pud_offset リニアアドレスに対応するPMDエントリのアドレスを取得

pud_none PUDエントリが空かどうか判定

pud_bad PUDエントリが不正かどうか判定

pud_clear PUDエントリをクリアする

Page 59: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるページング(9)*

・ページテーブル操作(5) ページ割り当て関数(2) PMD,PTEマクロ 内容

pmd_alloc PMDの作成

pmd_free PMDの解放

pmd_offset リニアアドレスに対応するPMDエントリのアドレスを取得

pmd_none PMDエントリが空かどうか判定

pmd_bad PMDエントリが不正かどうか判定

pmd_clear PMDエントリをクリアする

pte_alloc_one PTEの作成

pte_alloc_one_kernel PTEの作成(カーネル空間用)

pte_free PTEの解放

pte_free_kernel PTEの解放(カーネル空間用)

pte_offset_map リニアアドレスに対応するPTエントリのアドレス取得

pte_offset_map_nested 同上(一度に2つのPTを参照する際に使用)

pte_offset_kernel リニアアドレスに対応するPTエントリのアドレス取得(マスターカーネルPGD)

pte_unmap pte_offset_mapを使用した際、使用し終わったら呼ぶ

pte_unmap_nested pte_offset_map_nestedを使用した際、使用し終わったら呼ぶ

pte_none PTEが空かどうか判定

pte_present 対応する実ページが存在するかどうか判定

Page 60: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるページング(10)*

・ページテーブル操作(6) ページフラグ読み取り関数マクロ 内容

pte_user U/Sの値を読み取る

pte_read U/Sの値を読み取るx86ではページの読み込みを禁止は出来ない

pte_write R/Wの値を読み取る

pte_exec U/Sの値を読み取るx86ではコードの実行に対して保護は出来ない

pte_dirty Dの値を読み取る

pte_young Aの値を読み取る

pte_file Dの値を読み取るP=0 & D=1 ⇒ そのページは非線形ディスクファイルマッピングに使用

Page 61: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるページング(11)*

・ページテーブル操作(7) ページフラグ変更関数(1) PTEマクロ 内容

mk_pte_huge PTEのページ長とPフラグを設定

pte_wrprotect R/Wフラグ=0

pte_rdprotect U/Sフラグ=0

pte_exprotect U/Sフラグ=0

pte_mkwrite R/Wフラグ=1

pte_mkread U/Sフラグ=1

pte_mkexec U/Sフラグ=1

pte_mkclean Dフラグ=0

pte_mkdirty Dフラグ=1

pte_mkold Aフラグ=0

pte_mkyoung Aフラグ=1

Page 62: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるページング(12)*

・ページテーブル操作(8) ページフラグ変更関数(2) PTEマクロ 内容

pte_modify(p,v) PTエントリpの全アクセス権の値を指定値vにする

ptep_set_wprotect pte_wrprotectと同様だが、PTEへのポインタで指定

ptep_set_access_flags D=1⇒ページのアクセス権を指定値に設定し、  flush_tlb_page()関数を呼び出す    

ptep_mkdirty pte_mkdirtyと同様だが、PTEへのポインタで指定

ptep_test_and_clear_dirty pte_mkcleanと同様だが、PTEへのポインタで指定し、変更前のフラグを返す。

ptep_test_and_clear_young pte_mkoldと同様だが、PTEへのポインタで指定し、変更前のフラグを返す。

Page 63: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるページング(13)*

・ページテーブル操作(9) PTEエントリ操作関数/マクロ(1)マクロ 内容

pgd_index(addr) リニアアドレスaddrと対応するPGDエントリのインデックスを返す

pgd_offset(mm,addr) メモリディスクリプタmmとリニアアドレスaddrを受け取り、addrに対応するPGDエントリのリニアアドレスを返す。PGDはmm内のポインタが指している。

pgd_offset_k(addr) リニアアドレスaddrに対応するマスターカーネルPGDのリニアアドレスを返す

pgd_page(pgd) PGDエントリpgdが指すPUDのあるページフレームを見つけ、そのページフレームを管理するページディスクリプタのアドレスを返す。2階層/3階層ページングシステム ⇒ pgd_page = pud_page

pud_offset(pgd,addr) PGDエントリpgdとリニアアドレスaddrを受け取り、addrに対応するPUDのリニアアドレスを返す。2階層/3階層ページングシステム ⇒ pgdを返す

pud_page(pud) PUDエントリpudが指すPMDのリニアアドレスを返す。2階層ページングシステム ⇒ pud_page = pmd__page

pmd_index(addr) リニアアドレスaddrと対応するPMDエントリのインデックスを返す

pmd_offset(pud,addr) PUDエントリpudとリニアアドレスaddrを受け取り、addrに対応するPMDにリニアアドレスを返す。2階層ページングシステム ⇒ pudを返す

pmd_page(pmd) PMDエントリpmdが指すPTエントリのリニアアドレスを返す。2階層ページングシステム ⇒ pmdはPGDエントリと同じ

Page 64: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 - Linuxにおけるページング(14)*

・ページテーブル操作(10) PTEエントリ操作関数/マクロ(2)マクロ 内容

mk_pte(p,prot) ページディスクリプタpとアクセス権protを引数として受け取り、PTEを作成

pte_index(addr) リニアアドレスaddrをマッピングしているPTEのインデックスを返す

pte_page(x) PTエントリxが参照しているページディスクリプタのアドレスを返す

pte_to_pgoff(pte) PTエントリの中身から、PTが指しているページを非線形ファイルマッピングしているファイルでのオフセットを求める

pgoff_to_pte(offset) 非線形ファイルマッピングするページ用のPTエントリの値を作成

Page 65: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – アドレス変換バッファ

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 66: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – アドレス変換バッファ(1)

・アドレス変換バッファTLB      (Translation Lookaside Buffer)

  ・x86には、リニアアドレス変換を高速化する為の   バッファ/キャッシュが存在する。

  ・リニアアドレスを初めて使用する時は、アドレス変換テーブルを   用いて物理アドレスを算出。   この時、物理アドレスをTLBエントリに記憶させる。   次回同じリニアアドレスを使用する時はTLBエントリにアクセス。    ・マルチプロセッサシステムでは、各CPUはローカルTLBを持つ。   各ローカルTLBは同期の必要はない。

  ・cr3制御レジスタの内容が変わる   ⇒ローカルTLBの全エントリ無効化    ※使用する変換テーブルが変わり、TLBが古いデータを指す為。

Page 67: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – アドレス変換バッファ(2)*

・TLBの制御(1) - アーキテクチャ非依存

 ・TLBキャッシュの同期は自動では行わない。 ・リニアアドレスと物理アドレス間の対応を無効化する処理は、  カーネルが行う。

  アーキテクチャ非依存のTLB無効化方法(1)

関数 内容

flush_tlb_all 全TLBエントリ無効化。Gが設定されているグローバルページ用のTLBエントリも無効化。

カーネルページテーブルエントリを変更した時。

flush_tlb_kernel_range 指定したリニアアドレス範囲の全TLBエントリ無効化。グローバルページ用のTLBエントリも無効化。

あるアドレス範囲のカーネルページテーブルエントリを変更した時。

flush_tlb カレントプロセスに関連するすべての非グローバルページ用のエントリ無効化。

プロセス切り替えを実行した時。

Page 68: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – アドレス変換バッファ(3)*

・TLBの制御(2) - アーキテクチャ非依存  アーキテクチャ非依存のTLB無効化方法(2)

関数1 内容

flush_tlb_mm 指定したプロセスの指定したリニアアドレス範囲に対応するTLBエントリ無効化。

プロセスの一部のリニアアドレス範囲を解放した時。

flush_tlb_range 指定したプロセスの指定した範囲のページテーブルに対応するTLBエントリ無効化。

プロセス一部のページテーブルを解放した時。

flush_tlb_pgtables 指定したプロセスの指定したアドレスに対応するページテーブルエントリのTLBエントリ無効化。

ページフォルトを処理した時。

Page 69: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – アドレス変換バッファ(4)*

・TLBの制御(3) - アーキテクチャ依存

 ・Pentiumの全モデルで、cr3制御レジスタに値が書き込まれたときに、  非府グローバルページに対応するTLBエントリを無効化。 ・PentiumPro以降のモデルでは、invlpgアセンブリ言語命令を使用して、  指定したリニアアドレスに対応するTLBエントリを無効化する。

  アーキテクチャ依存のTLB無効化方法 – PentiumPro以降のプロセッサ用のTLB無効化マクロ

 ・x86では、flush_tlb_pgtable()は何もしない。  ページテーブルを親ページテーブルから解放する場合に何もしなくてよい。

 ・マルチプロセッサ用のTLB無効化方法  あるCPUで実行している関数は、他のCPUにプロセッサ間割り込みを送り、  そのCPUにTLB無効化関数を実行させる。

関数 内容 利用しているメソッド

__flush_tlb() cr3制御レジスタに同じ値を再設定する

flush_tlb,flush_tlb_mmflush_tlb_range

__flush_tlb_global() cr4制御レジスタのPGE=0にしてグローバルページを無効にし、cr3制御レジスタの値を再設定して、再度PGE=1にする。

flush_tlb_all,flush_tlb_kernel_range

__flush_tlb_single(addr) addrを引数として、invlpgアセンブリ言語命令を実行。

flush_tlb_range

Page 70: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – アドレス変換バッファ(5)*

・TLBの制御(4) - TLB無効化タイミング

 ・基本的にすべてのプロセス切り替えにおいて、  プロセスが使用するページテーブルを切り替える。  ⇒CPUのローカルTLBエントリも無効化する必要があり、   新しいPGDアドレスをcr3制御レジスタに書き込んだ時に、   ハードウェアによって 自動的に行われる。 ・カーネルがユーザーモードプロセスにページフレームの割り当てを行い、  割り当てたページフレームの物理アドレスをPTEに書き込む場合、  割り当てたリニアアドレスを参照しているローカルTLBエントリを無効化。 ・マルチプロセッサシステムで同じページテーブルを使用しているCPUがあれ  ば、対応するCPUのTLBエントリを無効化実行。

 [例外] ・同じページテーブルを使用している通常プロセス間でのプロセス切り替え  (=同一プロセスに属するスレッド間切り替え) ・通常プロセスとカーネルスレッド間でプロセス切り替えを行う場合。   カーネルスレッドは固有のページテーブルを持っていない為、   直前に動作していた通常プロセスのページテーブルをそのまま使用する

Page 71: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – アドレス変換バッファ(6)*

・TLBの制御(5) – マルチプロセッサ環境における         無駄なTLB無効化対策(1)

 ・遅延TLBモード(Lazy TLB Mode)   いくつかのCPUが同じページテーブルを使用していて、TLBを無効化する必要がある場合、   カーネルスレッドを実行しているCPUのTLB無効化を延期させる。   ※flush_tlb_all()ではこのモードを使用しない。

   ・カーネルスレッドは固有のページテーブルを持っていない為、    通常プロセスのページテーブルをそのまま使用している。    カーネルスレッドはユーザーモードのアドレス空間にアクセスしないので、    ユーザーモードのリニアアドレス空間に対応するTLBエントリを無効化する必要は無い。   ・TLBエントリ無効化要求が発行されても、遅延TLBモードのCPUはTLBエントリを無効化しない。    カレントプロセスのユーザーモードアドレスのTLBエントリが使えない事を覚えておく。    遅延TLBモードのCPUが、     ・違うページテーブルを持つプロセスに切り替わった場合      ⇒即ハードウェアが自動的にTLBエントリを無効化し、非遅延TLBモードに戻す。     ・直前のカーネルスレッドと同じページテーブルを持つ通常プロセスに切り替わった場合      ⇒延期していたTLB無効化処理を行う。       この遅延した無効化処理は、すべての非グローバルなTLBエントリを無効化する。

Page 72: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – アドレス変換バッファ(7)*

・TLBの制御(6) – マルチプロセッサ環境における         無駄なTLB無効化対策(2)

 ・cpu_tlbstate変数    ・struct tlb_state構造体をCPU毎に使える様に定義。     宣言(DECLARE_PER_CPU_SHARED_ALIGNEDマクロ)       [ver4.2 arch/x86/include/asm/tlbflush.h:18]     定義(DEFINE_PER_CPU_SHARED_ALIGNEDマクロ)      [ver4.2 arch/x86/mm/init.c:736]    ・active_mmメンバ:カレントプロセスのメモリディスクリプタmm_struct構造体              [ver4.2 include/linux/mm_types.h:392]    ・メモリディスクリプタのcpu_vm_mask_varメンバ      TLBの無効化を要求するプロセッサ間割り込みを受け付けるCPUのインデックス値。      カレントプロセスのメモリディスクリプタに属している場合のみ有効。    ・stateメンバ      TLBSTATE_OK  :非遅延TLBモード      TLBSTATE_LAZY :遅延TLBモード

Page 73: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – アドレス変換バッファ(8)*

・TLBの制御(7) – マルチプロセッサ環境における         無駄なTLB無効化対策(3)

 ・遅延TLBモードの利用

   1.CPUがカーネルを実行する場合、     ・cpu_tlbstate::stateメンバをTLBSTATE_LAZYにする。     ・カレントプロセスのメモリディスクリプタのcpu_vm_mask_varメンバに、      遅延TLBモードのCPUを含むシステム上の全CPUインデックスに対応する      全てのビットを1にする。   2.別のCPUが、指定されたページテーブルに関連する全てのCPUのTLBエントリを無効化する    場合、該当するメモリディスクリプタのcpu_vm_mask_varメンバのインデックスが示して    いる全てのCPUに対して、プロセッサ間割り込みを送る。   3.CPUがTLB無効化を要求するプロセッサ間割り込みを受け取り、    カレントプロセスのページテーブルに影響がある事を確認した場合、    ・cpu_tlbstate::state = TLBSTATE_LAZY     ⇒TLB無効化を行わない      実行しているプロセスのメモリディスクリプタのcpu_vm_mask_varメンバから、      自分のCPUに対応するビットを0にする。

  ・遅延TLBモードにある限り、TLB無効化関連のプロセッサ間割り込みを受け付けない。  ・直前のカーネルスレッドと同じページテーブルを使用するプロセッサに切り替わった場合、   カーネルは__flush_tlb()を実行し、そのCPU上のすべての非グローバルTLBエントリ無効化

Page 74: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 75: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(1)

・予約された物理アドレス領域(1) 

  ・PC/ATアーキテクチャには、   予約された物理アドレス領域が存在する。  ・PC/AT互換機は、互換性維持の為に、   この領域を確保しておかなければならない。

  ※OSはこの領域を確保しておかなければならない。   この領域は、通称ISAホール/メモリホール。

アドレス(0x00000~0xFFFFF) 用途

0x00000 ~ 0x9FFFF BIOS使用可能(640KB)  16bit環境ではメインメモリとして利用

0xA0000 ~ 0xBFFFF ビデオRAM(VGA) (128KB)

0xC0000 ~ 0xC7FFF ビデオBIOS ROM (32KB)

0xC8000 ~ 0xEFFFF 拡張カード ROM (160KB)

0xF0000 ~ 0xFFFFF PC/AT互換PC BIOS ROM (64KB)

Page 76: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(2)

・予約された物理アドレス領域(2)

  ・先頭640KB(0x00000~0x9FFFF)のソフトウェア的用途

  ・0x00300~0x003FFは、BIOS用スタックの場合もある  ・拡張BIOS全てのワークエリアが0x9FC000から始まる保証は無い。

アドレス(0x00000~0x9FFFF) 用途

0x00000 ~ 0x003FF リアルモード用割り込みベクタ(1KB)

0x00400 ~ 0x004FF BIOS データ領域 (256byte)

0x00500 ~ 0x07BFF 未使用 (29KB + 768byte)

0x07C00 ~ 0x07DFF ブートローダ(ブートセクタが読み込まれる) (512byte)

0x07E00 ~ 0x9FBFF 未使用 (607KB + 512byte)

0x9FC00 ~ 0x9FFFF 拡張BIOS(ATA,APM,ACPI,MP...etc)のワークエリア (1KB)

Page 77: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(3)

・予約されたページフレーム  このページフレームに存在するページは、  動的に割り当てられたり、ディスクにスワップされる事は無い。

  ・予約された物理アドレス領域(ISAホール)。   Linuxは非連続ページフレームは使用しないと決めている。

  ・カーネルコードと初期化したデータ構造を含むページフレーム。   通常、物理アドレス0x00100000(1MB)以降のRAMに置かれる。

  ・ページフレーム0    BIOSが利用。POST(Power-On Self-Test)中に検知したシステム    のハードウェア設定情報を置く。    ノートPCのBIOSでは、システム初期化後もデータを書き込むことがある。

  ・あるコンピュータモデルでは、他のページフレームが予約済みの場合がある。    IBM Think Pad 0xA0ページフレーム→0x9Fページフレームにマッピング。

Page 78: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(4)

・物理アドレスマップの作成手順(1)

1.カーネル起動処理の初期段階  BIOSを呼び出して、物理メモリの大きさを問い合わせる。  物理アドレス範囲とメモリ種類の一覧を作成。

2.物理アドレスマップ作成

3.物理メモリ領域テーブルを解析しカーネルの物理メモリ配置を示す 変数の初期化。        

Page 79: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(5)*

・物理アドレスマップの作成手順(2)

1.カーネル起動処理の初期段階  BIOSを呼び出して、物理メモリの大きさを問い合わせる。  物理アドレス範囲とメモリ種類の一覧を作成。

   ・BIOS-e820機能を利用(AXレジスタ0xE820時のINT 0x15の動作/機能)

   ・コールスタック    main()[ver4.2 arch/x86/boot/main.c:135]    →detect_memory()[ver4.2 arch/x86/boot/memory.c:122]          →detect_memory_e820()[ver4.2 arch/x86/boot/memory.c:20]       ・boot_params::e820_map構造体配列に格納。        (struct boot_params構造体メンバのstruct e820entry構造体の配列)         ・struct boot_params構造体 [ver4.2 arch/x86/include/uapi/asm/bootparam.h:114]          インスタンス [ver4.2 arch/x86/kernel/setup.c:145]         ・struct e820entry構造体 [ver4.2 arch/x86/include/uapi/asm/e820.h:58]

struct e820entry { __u64 addr; /* start of memory segment */ __u64 size; /* size of memory segment */ __u32 type; /* type of memory segment */} __attribute__((packed));

       ・type        1:usable,2:reserved,3:ACPI data,4:ACPI NVS(Non Volatile Sleeping,不揮発)      

※BIOS機能参考 http://www.ctyme.com/intr/int.htm

Page 80: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(6)*

・物理アドレスマップの作成手順(3)

<例>(x86,1.5GBメモリ,実機)のdmesg結果

[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable[ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved[ 0.000000] BIOS-e820: [mem 0x00000000000e6000-0x00000000000fffff] reserved[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000005f72fbff] usable[ 0.000000] BIOS-e820: [mem 0x000000005f72fc00-0x000000005f72ffff] ACPI NVS[ 0.000000] BIOS-e820: [mem 0x000000005f730000-0x000000005f73ffff] ACPI data[ 0.000000] BIOS-e820: [mem 0x000000005f740000-0x000000005f7effff] ACPI NVS[ 0.000000] BIOS-e820: [mem 0x000000005f7f0000-0x000000005f7fffff] reserved[ 0.000000] BIOS-e820: [mem 0x00000000e0000000-0x00000000efffffff] reserved[ 0.000000] BIOS-e820: [mem 0x00000000fed13000-0x00000000fed19fff] reserved[ 0.000000] BIOS-e820: [mem 0x00000000fed1c000-0x00000000fed9ffff] reserved

※cat /proc/iomemで詳細な物理メモリレイアウトを見られる。

    

Page 81: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(7)*

・物理アドレスマップの作成手順(3)

2.物理アドレスマップ作成

  ・コールスタック   start_kernel() [ver4.2 init/main.c:497]   →setup_arch() [ver4.2 arch/x86/kernel/setup.c:862]    →setup_memory_map() [ver4.2 arch/x86/kernel/e820.c:1085]     →x86_init.resources.memory_setup() [関数ポインタで以下を呼び出し]      →default_machine_specific_memory_setup() [ver4.2 arch/x86/kernel/e820.c:1047]        ・append_e820_map()関数でe820map構造体に格納        ・struct e820map構造体 [ver4.2 arch/x86/include/uapi/asm/e820.h:64]         e820インスタンス(ver4.2 arch/x86/kernel/e820.c:42)          e820インスタンスは編集用,e820_saveインスタンスは保存用        

Page 82: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(8)*

・物理アドレスマップの作成手順(4)

3.物理メモリ領域テーブルを解析しカーネルの物理メモリ配置を示す変数の初期化。

    ・max_pfn    setup_arch()     ・max_pfn = e820_end_of_ram_pfn(); [ver4.2 arch/x86/kernel/setup.c:1063]

  ・max_low_pfn    setup_arch()     ・find_low_pfn_range(); [ver4.2 arch/x86/kernel/setup.c:1072] x86     ・[ver4.2 arch/x86/kernel/setup.c:1078-1081] x86_64

  ※後日追記予定  ・min_low_pfn    ・num_physpages  ・totalram_pages  ・totalhigh_pages  ・highmem_pages  ・highstart_pfn  ・highend_pfn  

Page 83: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(9)

・Linuxカーネルが使用するページフレーム

※後日更新予定

ページフレーム 範囲 用途

_text ~ _etexts カーネルコード

_etext ~ _edata 初期化されたカーネルデータ

_edata ~ end 初期化されていないカーネルデータ

Page 84: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(10)

・プロセスのページテーブル

 ・ユーザーモード⇒0xC0000000未満を利用 ・カーネルモード⇒0xC0000000以上を利用 ・PAGE_OFFSET = 0xC0000000 ・カーネルがユーザーモードプロセスのデータを取り出したり書き込んだりする   場合には、ユーザーモードのリニアアドレス空間にアクセス

 ・PGD前半エントリ:0xC0000000未満,プロセス固有のエントリ ・PAE無効時:先頭768エントリがプロセス固有 ・PAE有効時:先頭3エントリがプロセス固有 ・残りのエントリ:全プロセス共通。          マスターカーネルPGDの対応するエントリと一致

Page 85: 2章 Linuxカーネル - メモリ管理1

1.アドレス変換機能 – 物理メモリレイアウト(11)

・カーネルのページテーブル

 ・マスターカーネルPGD   カーネル自身が使用するページテーブル群。   システム初期化後にプロセスやカーネルスレッドが直接使用する事は無い。   高位部エントリは全プロセスのPGDの雛形。   マスターカーネルPGDの変更が、プロセスが利用しているPGDに反映される。

 ・カーネルのページテーブルの初期化   0.リアルモード   1.限定したアドレス空間を生成。      カーネルコードセグメント,カーネルデータセグメント,初期のページテーブル,      動的確保のデータ構造の領域。

   2.存在する全てのRAMを利用してページテーブルを初期化。   ※ブートの章に詳細記述

Page 86: 2章 Linuxカーネル - メモリ管理1

2.メモリ保護機能

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 87: 2章 Linuxカーネル - メモリ管理1

2.メモリ保護機能(1)

・セグメントへのアクセスチェック  ・リミット  ・タイプ  ・特権レベル

・ページフレームへのアクセスチェック  ・R/W  ・U/S

Page 88: 2章 Linuxカーネル - メモリ管理1

2.メモリ保護機能(2)

・セグメントへのアクセスチェック(1)

 ・リミットチェック   論理アドレスのオフセット値をチェック   G=0: 0≦offset≦リミット   G=1: 0≦offset≦(リミット*4KB)

 ・タイプチェック   ・読み込み、書き込み、実行のチェック   ・セグメントレジスタにセレクタをロードする時にチェック       ・CSレジスタにはコードセグメント(4~7)のセレクタのみロード可能。0はロード不可。       ・DS,ES,FS,GSレジスタにはデータセグメント(0~3)のみロード可能。       ・SSレジスタには書き込み可能なデータセグメント(1,3)のみロード可能。0はロード不可。

   ・恒常的に以下をチェック       ・コードセグメントにデータを書き込む       ・読み出し専用のデータセグメントにデータを書き込む

Page 89: 2章 Linuxカーネル - メモリ管理1

2.メモリ保護機能(3)

・セグメントへのアクセスチェック(2)

 ・特権レベルチェック(1) - 概要

   ・特権レベルはプログラム(コードセグメント)に割り当てる権限。   ・CPL/DPL/RPLの値     0,1,2:カーネル/スーパーバイザ(0:ホストOS,1~2:仮想化マシン)     3 :ユーザ     ※小さい方が特権レベルが高い   ・DPL=0のコードセグメントを実行している時のCPUのCPL=0   ・基本的にDPL=CPL   ・CSレジスタに対してビット操作できる命令は存在しない。    ⇒CPLを変えるにはゲートを用いる   ・RPLは特権レベルを下げるために利用

Page 90: 2章 Linuxカーネル - メモリ管理1

2.メモリ保護機能(4)

・セグメントへのアクセスチェック(3)

 ・特権レベルチェック(2) – DSレジスタ更新時の保護   MAX(CPL,RPL) > DPL ⇒ 保護違反       (・CPL≦DPL⇒ロード可能       (・RPL≦DPL⇒ロード可能ex.特権レベルとRPLの目的 GDT

 セグメントセレクタ

 ※ユーザーがシステムコールにRPL=0のセレクタを渡し、カーネル領域にアクセスする事も出来てしまう。 ⇒RPL=0のセレクタを渡しても、カーネルはRPL=3に書換え、カーネル領域にアクセス不可にする。  この様な、特権レベルを下げる目的でRPLを用いる。   

インデックス DPL

3 0

4 3

インデックス TI RPL セレクタ CPL アクセス可否

4 0 3 0x23 3 DPL=RPL=CPL可能。ユーザがユーザ領域にアクセス

3 0 0 0x18 0 DPL=RPL=CPL可能。カーネルがカーネル領域にアクセス

3 0 3 0x1B 0 CPL=DPL≠RPLユーザがカーネル領域にアクセス

Page 91: 2章 Linuxカーネル - メモリ管理1

2.メモリ保護機能(5)

・セグメントへのアクセスチェック(4)

 ・特権レベルチェック(2) – CSレジスタ更新時の保護

   ・mov命令などでCSレジスタの直接変更は不可。    命令が存在しない。   ・CSレジスタ変更の基本ルール     ・移行先セグメントのDPL=CPL ⇒ 許可     ・それ以外は不許可   ・DPL≠CPLセグメントへのCSレジスタ変更(特権レベル切替え)     ・ゲートを用いる      コールゲート,トラップゲート,割り込みゲート,      タスクゲート

Page 92: 2章 Linuxカーネル - メモリ管理1

2.メモリ保護機能(6)

・ページフレームへのアクセスチェック(1)

 ・R/W   0:R 1:RW ・U/S   0:スーパーバイザ 1:ユーザ

モード U/S=0 U/S=1

ユーザ 不可 可能

スーパーバイザ 可能 可能

モード R/W=0 R/W=1

ユーザ 読出し専用 読み書き可

スーパーバイザ 読み書き可 読み書き可

Page 93: 2章 Linuxカーネル - メモリ管理1

2.メモリ保護機能(7)

・ページフレームへのアクセスチェック(2) ・WPフラグ  CopyOnWriteを実現する為に利用。  2つ以上のプロセスから共有されているユーザーページを読出し専用として設定しておくと、  OSはCPUの例外発生によってユーザーページへの書き込みを検出し、  その時点で新しいページを割り当ててコピー出来る様になる。

 WP=0 WP=1

 ・NSフラグ(No eXcute)/実行不可フラグ  64bitページテーブルエントリ毎に実行不可フラグを設定可能  Pentium4以降 & cr4制御レジスタPAE=1

モード U/S R/W アクセス権

ユーザ 0 0 アクセス不可

ユーザ 0 1 アクセス不可

ユーザ 1 0 読み出し専用

ユーザ 1 1 読み書き可能

スーパーバイザ 0 0 読み書き可能

スーパーバイザ 0 1 読み書き可能

スーパーバイザ 1 0 読み書き可能

スーパーバイザ 1 1 読み書き可能

モード U/S R/W アクセス権

ユーザ 0 0 アクセス不可

ユーザ 0 1 アクセス不可

ユーザ 1 0 読み出し専用

ユーザ 1 1 読み書き可能

スーパーバイザ 0 0 読み書き可能

スーパーバイザ 0 1 読み書き可能

スーパーバイザ 1 0 読み出し専用

スーパーバイザ 1 1 読み書き可能

Page 94: 2章 Linuxカーネル - メモリ管理1

2.メモリ保護機能

1.アドレス変換機能  概要,  x86におけるセグメンテーション,  x86_64におけるセグメンテーション,  Linuxにおけるセグメンテーション,  x86におけるページング,  x86_64におけるページング,  Linuxにおけるページング,  アドレス変換バッファ,  物理メモリレイアウト,2.メモリ保護機能3.キャッシュ制御機能

Page 95: 2章 Linuxカーネル - メモリ管理1

3.キャッシュ制御機能(1)

・ハードウェアキャッシュ

 ・局所性原理   繰り返し処理を行うプログラムや配列に収められた関連データ、   最後に利用されたアドレス付近は、   高確率で時間をおかず再利用される。

 ・キャッシュ方式  1.ダイレクトマップ方式   メインメモリ内にあるラインは、常にキャッシュ内の同じ位置に置く。  2.完全連想キャッシュ方式   メインメモリ内の任意ラインを、キャッシュ内の任意ラインに置く。  3.Nウェイセット連想キャッシュ    メインメモリ内の任意ラインを、キャッシュ内のNライン内の1つに置く。

 ・プロセッサのハードウェアキャッシュ  [DRAM]----[キャッシュコントローラ]----[ページング回路] | | [SRAMキャッシュメモリ]

Page 96: 2章 Linuxカーネル - メモリ管理1

3.キャッシュ制御機能(2)

・キャッシュコントローラ  ・キャッシュコントローラ内に、キャッシュメモリの1ラインの情報を   示す要素の配列がある。  ・配列要素    タグ:現在割り当てられているメモリの位置    キャッシュライン状態フラグ     

Page 97: 2章 Linuxカーネル - メモリ管理1

3.キャッシュ制御機能(3)

・キャッシュ検索  ・物理アドレス    上位:タグ    中位:サブセットのインデックス    下位:ライン内のオフセット  ・検索の流れ    1.物理アドレスからサブセットのインデックス抽出    2.サブセット内にある全ラインのタグと物理アドレスの上位ビット比較    3.上位ビットと同じタグが見つかればキャッシュヒット。     それ以外はキャッシュミス。    4.キャッシュヒットの場合     読み込み時       キャッシュラインからデータを選出し、レジスタに転送     書き込み時      ・ライトスルー        常にRAMとキャッシュラインの両方に書き込む      ・ライトバック        キャッシュラインのみ書き込む        RAM更新は、         ・CPUがキャッシュエントリ無効化(フラッシュ)要求命令を実行した場合。         ・FLUSHハードウェア信号が発生した場合。        ※通常はキャッシュミスのあと    5.キャッシュミスの場合      キャッシュラインはメモリに書込まれ、必要ならばRAMから正しいラインに取り出し、      キャッシュエントリに置く。

Page 98: 2章 Linuxカーネル - メモリ管理1

3.キャッシュ制御機能(4)

・キャッシュスヌーピング  ・マルチプロセッサの場合、プロセッサ毎に独立したハードウェアキャッシュがある為、   各キャッシュの同期を行うハードウェア機構が必要。  ・あるCPUが自身のハードウェアキャッシュを更新する時には、   他のCPUのハードウェアキャッシュが同じデータを持っているかどうかを調べる必要あり。   同じデータを持っている場合は、他のCPUに更新を知らせ、正しい値を渡す。   これはハードウェアで行われる。

・キャッシュの種類  ・L1キャッシュ  ・L2キャッシュ  ・L3キャッシュ    ※数字が上がるにつれて、大容量・低速になっていく。  ※キャッシュ間の整合性はハードウェアが行う。  ※Linuxでは1つのキャッシュとして扱っている。

・キャッシュの設定  ・Pentium以降は、PCD,PWTを変えることで、   OSがページフレーム毎に異なるキャッシュ方式を持てる。  ・Linuxでは常に、PCD=PWT=0   ページフレームで常にキャッシュ有効&書き込み時はライトバック。

Page 99: 2章 Linuxカーネル - メモリ管理1

3.キャッシュ制御機能(5)

・ハードウェアキャッシュの制御

 ・L1_CACHE_BYTESマクロ   キャッシュラインのバイト数    ~Pentium4:32byte    Pentium4:128byte

 ・ヒット率最適化方針   ・構造体のうち、最も頻繁に使用するメンバを低いオフセットに集めて、    同じラインに乗るようにする。   ・多数のデータを割り当てる時は、全キャッシュラインを均等に使用する様に    データの配置を行う。

 ・キャッシュの同期処理   x86:    自動で行う為、カーネルはハードウェアキャッシュのフラッシュ処理は行わない。   同期無しプロセッサ:    カーネルはフラッシュ処理のインターフェイスを提供しているのでそれを利用。