Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

4,784 views

Published on

Linuxカーネルのメモリ管理(ハードウェア寄り)
kernel ver 4.2

Published in: Software
  • Be the first to comment

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

  1. 1. 2章 Linuxカーネル - メモリ管理1 mao Web >http://www.pridact.com Twitter >https://twitter.com/rivarten Blog >http://rivartender.blog.fc2.com Mail >official@pridact.com
  2. 2. はじめに メモリ管理におけるハードウェア寄りの話 視点 ・x86プロセッサのメモリ割当て回路 ・x86_64ではどうなっているか ・Linuxカーネルがメモリ割当て回路を  どのように利用するか
  3. 3. この資料について ・間違っていたらご指摘をお願い致します。 ・Linux Kernelのバージョンは4.2です。 ・ページタイトルに*印が付いているページは、  少し踏み込んだ内容になっています。  ざっと全体に目を通したければ、読み飛ばして  もらっても構いません。
  4. 4. メモリ割当て回路: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
  5. 5. 流れ 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  6. 6. 1.アドレス変換機能 - 概要 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  7. 7. 1.アドレス変換機能 - 概要(1) 論理アドレス   ↓ [セグメンテーション回路]   ↓ リニアアドレス/仮想アドレス   ↓ [ページング回路]   ↓ 物理アドレス   MMU内のセグメンテーション回路とページング回路を経由して、   論理アドレスから物理アドレスに変換する。
  8. 8. 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。
  9. 9. 1.アドレス変換機能 - x86におけるセグメンテーション 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  10. 10. 1.アドレス変換機能 - x86におけるセグメンテーション(1) ・セグメントディスクリプタ/セグメント識別子  セグメントの特性・属性を示す。  64bit長(8byte) ・セグメントディスクリプタテーブル  セグメントディスクリプタを格納する表。  メモリ上の任意の場所に置かれる。  GDT(Global Descriptor Table)  LDT(Local Descriptor Table) ・セグメントセレクタ  セグメントディスクリプタを選択する16bitの値。
  11. 11. 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:仮想化マシン
  12. 12. 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では不使用。
  13. 13. 1.アドレス変換機能 - x86におけるセグメンテーション(4) ・セグメントディスクリプタの種類  1.コードセグメントディスクリプタ  2.データセグメントディスクリプタ  3.システムセグメントディスクリプタ  4.タスク状態セグメントディスクリプタ   (Task State Segment:TSS)  5.ローカルディスクリプタテーブルディスクリプタ
  14. 14. 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)
  15. 15. 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)
  16. 16. 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)
  17. 17. 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)
  18. 18. 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)
  19. 19. 1.アドレス変換機能 - x86におけるセグメンテーション(10) ・セグメントディスクリプタへの高速アクセス法  1回のメモリアクセスをする為に、MMUは2回メモリを参照しなければならない為、  そのままでは低速。   1回目:メモリ上のセグメントディスクリプタにアクセス   2回目:セグメントにアクセス  ⇒  各種セグメントレジスタと対応する、  6個のノンプログラマブルな64bit(8byte)長のレジスタを利用。  ノンプログラマブルレジスタ内にセグメントディスクリプタを格納し、  アクセスする事で高速化を図る。  <セグメントレジスタの値を変更する時>  1.セグメントセレクタをセグメントレジスタに書込む。  2.セグメントディスクリプタをメモリからノンプログラマブルレジスタにコピー。  3.ノンプログラマブルレジスタ内のセグメントディスクリプタにアクセス。  4.セグメントにアクセス。  <セグメントレジスタの値を変更しない時>  1.ノンプログラマブルレジスタ内のセグメントディスクリプタにアクセス  2.セグメントにアクセス。
  20. 20. 1.アドレス変換機能 - x86におけるセグメンテーション(11) ・リニアアドレス変換  リニアアドレス = セグメントセレクタ*8            + (gdtr or ldtr) + オフセット   ※gdtr,ldtrのどちらを選択するかは、セレクタのTIフィールドで判別.  ※リアルモード時   リニアアドレス = セグメントセレクタ*16 + オフセット
  21. 21. 1.アドレス変換機能 - x86_64におけるセグメンテーション 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  22. 22. 1.アドレス変換機能 - x86_64におけるセグメンテーション    ・DS,ES,SSのセグメントレジスタは使用されない。  ・CSは使用する。   セグメントのベース、リミットは無視され、フラットメモリモデルとなる。   (Linuxはもともとフラットモデルなので影響なし)  ・DフラグとLフラグ(bit53)の組み合わせで、互換モード、64bitモード決定   Dフラグ=0,Lフラグ=1で64bitモード。   (0章 x86 – 動作モード 遷移手続き参照)  ・FS,GSセグメントはベース、リミット設定可能。   ベースフィールドが32bitしかない為、MSRに設定する。   (Linuxでは使用しない)
  23. 23. 1.アドレス変換機能 - Linuxにおけるセグメンテーション 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  24. 24. 1.アドレス変換機能 - Linuxにおけるセグメンテーション(1) ・Linuxでは、全プロセスで同じ値のセグメントレジスタを利用。  同じリニアアドレス空間を共有してメモリ管理簡略化。 ・Linuxは広範囲アーキテクチャへの移植性を確保する為に、  セグメント機構を限定的に使っているRISCにも対応する必要があり、  セグメント機構は限定的に使用し、ページング機構をメインに利用。 ・アドレス範囲が同じ  ⇒ユーザーモード・カーネルモード問わず   同じ論理アドレスを使用可能。 ・セグメントベース値が0 & (論理アドレス=リニアアドレス)  ⇒常に論理アドレスのオフセットフィールドがリニアアドレスと一致。   基本フラットモデル。   最低でもコードセグメントとデータセグメントが必要。     ※コードセグメントにデータを書き込めない。  
  25. 25. 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
  26. 26. 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)
  27. 27. 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)
  28. 28. 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
  29. 29. 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()システムコール:解放
  30. 30. 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を使わない。
  31. 31. 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
  32. 32. 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
  33. 33. 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
  34. 34. 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は別のタイミングで初期化
  35. 35. 1.アドレス変換機能 – x86におけるページング 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  36. 36. 1.アドレス変換機能 – x86におけるページング(1) - 概要 ・ページング機構  仮想的に連続したメモリ空間や、  他のプログラムから独立したメモリ空間を提供。    ・ページフレーム      リニアアドレスの分割枠    ・ページ      ページフレーム内に配置する実際のデータ    ・ページテーブル(アドレス変換テーブル)      リニアアドレスを物理アドレスにマッピングするデータ構造  cr0制御レジスタのPGフラグ=1でページング有効化。  PGフラグ=0でリニアアドレス=物理アドレス。
  37. 37. 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
  38. 38. 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はキャッシュ的存在。後述。
  39. 39. 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番の例外(ページフォールト例外)を発生させる。
  40. 40. 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
  41. 41. 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は使用していない。
  42. 42. 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ヒット率があまり高くない。
  43. 43. 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
  44. 44. 1.アドレス変換機能 – x86_64におけるページング 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  45. 45. 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アーキテクチャにおけるページング
  46. 46. 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
  47. 47. 1.アドレス変換機能 - x86_64におけるページング(3) PML4 Entry index 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
  48. 48. 1.アドレス変換機能 - x86_64におけるページング(4) PD Entry index 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 PS 0: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
  49. 49. 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
  50. 50. 1.アドレス変換機能 – Linuxにおけるページング 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  51. 51. 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= 物理アドレス
  52. 52. 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 
  53. 53. 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
  54. 54. 1.アドレス変換機能 – Linuxにおけるページング(4) ・Linuxのプロセス処理とページング機構  Linuxのプロセス処理は、ページング機構に大きく依存。  ・プロセス毎に異なる物理アドレス空間を与え、   かつ変換エラーに対して確実な保護機構が働く。  ・データの集まりであるページと、メインメモリ上の   物理アドレスの集まりであるページフレームを区別。   これにより、あるページをページフレーム内に置き、   その後ディスクに退避させた後に、別のページフレーム内に   読み込むことも可能。  ・cr3制御レジスタの内容をプロセスの状態を保存するディスクリプタに退避。   次のプロセスのディスクリプタからcr3制御レジスタの値を読み込む。   これにより、ページング回路も新しいページテーブルを指す様になる。
  55. 55. 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 オフセットフィールドとテーブルフィールドの全ビットをマスクする時に使用。
  56. 56. 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_SHIFT PAE無効:22 PAE有効:30 PGDIR_SIZE PGDの1エントリがマッピングできる領域のサイズ。 PAE無効:4MB PAE有効:1GB PGDIR_MASK オフセット、テーブル、ミドルディレクトリ、アッパーディレクトリの 全ビットをマスクする時に利用。 0xC0000000 PTRS_PER_PTE PTRS_PER_PMD PTRS_PER_PUD PTRS_PER_PGD 各エントリ数を計算。 PAE無効:1024,1,1,1024 (2段) PAE有効:512,512,1,4  (3段)
  57. 57. 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 エントリの保護フラグ
  58. 58. 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エントリをクリアする
  59. 59. 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 対応する実ページが存在するかどうか判定
  60. 60. 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 ⇒ そのページは非線形ディスクファイルマッピングに使用
  61. 61. 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
  62. 62. 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へのポインタで指定し、 変更前のフラグを返す。
  63. 63. 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エントリと同じ
  64. 64. 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エントリの値を作成
  65. 65. 1.アドレス変換機能 – アドレス変換バッファ 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  66. 66. 1.アドレス変換機能 – アドレス変換バッファ(1) ・アドレス変換バッファTLB       (Translation Lookaside Buffer)   ・x86には、リニアアドレス変換を高速化する為の    バッファ/キャッシュが存在する。   ・リニアアドレスを初めて使用する時は、アドレス変換テーブルを    用いて物理アドレスを算出。    この時、物理アドレスをTLBエントリに記憶させる。    次回同じリニアアドレスを使用する時はTLBエントリにアクセス。      ・マルチプロセッサシステムでは、各CPUはローカルTLBを持つ。    各ローカルTLBは同期の必要はない。   ・cr3制御レジスタの内容が変わる    ⇒ローカルTLBの全エントリ無効化     ※使用する変換テーブルが変わり、TLBが古いデータを指す為。
  67. 67. 1.アドレス変換機能 – アドレス変換バッファ(2)* ・TLBの制御(1) - アーキテクチャ非依存  ・TLBキャッシュの同期は自動では行わない。  ・リニアアドレスと物理アドレス間の対応を無効化する処理は、   カーネルが行う。   アーキテクチャ非依存のTLB無効化方法(1) 関数 内容 flush_tlb_all 全TLBエントリ無効化。 Gが設定されているグローバルページ用のTLBエントリも無効化。 カーネルページテーブルエントリを変更した時。 flush_tlb_kernel_range 指定したリニアアドレス範囲の全TLBエントリ無効化。 グローバルページ用のTLBエントリも無効化。 あるアドレス範囲のカーネルページテーブルエントリを変更した時。 flush_tlb カレントプロセスに関連するすべての非グローバルページ用のエント リ無効化。 プロセス切り替えを実行した時。
  68. 68. 1.アドレス変換機能 – アドレス変換バッファ(3)* ・TLBの制御(2) - アーキテクチャ非依存   アーキテクチャ非依存のTLB無効化方法(2) 関数1 内容 flush_tlb_mm 指定したプロセスの指定したリニアアドレス範囲に対応するTLBエン トリ無効化。 プロセスの一部のリニアアドレス範囲を解放した時。 flush_tlb_range 指定したプロセスの指定した範囲のページテーブルに対応するTLB エントリ無効化。 プロセス一部のページテーブルを解放した時。 flush_tlb_pgtables 指定したプロセスの指定したアドレスに対応するページテーブルエン トリのTLBエントリ無効化。 ページフォルトを処理した時。
  69. 69. 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_mm flush_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
  70. 70. 1.アドレス変換機能 – アドレス変換バッファ(5)* ・TLBの制御(4) - TLB無効化タイミング  ・基本的にすべてのプロセス切り替えにおいて、   プロセスが使用するページテーブルを切り替える。   ⇒CPUのローカルTLBエントリも無効化する必要があり、    新しいPGDアドレスをcr3制御レジスタに書き込んだ時に、    ハードウェアによって 自動的に行われる。  ・カーネルがユーザーモードプロセスにページフレームの割り当てを行い、   割り当てたページフレームの物理アドレスをPTEに書き込む場合、   割り当てたリニアアドレスを参照しているローカルTLBエントリを無効化。  ・マルチプロセッサシステムで同じページテーブルを使用しているCPUがあれ   ば、対応するCPUのTLBエントリを無効化実行。  [例外]  ・同じページテーブルを使用している通常プロセス間でのプロセス切り替え   (=同一プロセスに属するスレッド間切り替え)  ・通常プロセスとカーネルスレッド間でプロセス切り替えを行う場合。    カーネルスレッドは固有のページテーブルを持っていない為、    直前に動作していた通常プロセスのページテーブルをそのまま使用する
  71. 71. 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エントリを無効化する。
  72. 72. 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モード
  73. 73. 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エントリ無効化
  74. 74. 1.アドレス変換機能 – 物理メモリレイアウト 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  75. 75. 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)
  76. 76. 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)
  77. 77. 1.アドレス変換機能 – 物理メモリレイアウト(3) ・予約されたページフレーム   このページフレームに存在するページは、   動的に割り当てられたり、ディスクにスワップされる事は無い。   ・予約された物理アドレス領域(ISAホール)。    Linuxは非連続ページフレームは使用しないと決めている。   ・カーネルコードと初期化したデータ構造を含むページフレーム。    通常、物理アドレス0x00100000(1MB)以降のRAMに置かれる。   ・ページフレーム0     BIOSが利用。POST(Power-On Self-Test)中に検知したシステム     のハードウェア設定情報を置く。     ノートPCのBIOSでは、システム初期化後もデータを書き込むことがある。   ・あるコンピュータモデルでは、他のページフレームが予約済みの場合がある。     IBM Think Pad 0xA0ページフレーム→0x9Fページフレームにマッピング。
  78. 78. 1.アドレス変換機能 – 物理メモリレイアウト(4) ・物理アドレスマップの作成手順(1) 1.カーネル起動処理の初期段階   BIOSを呼び出して、物理メモリの大きさを問い合わせる。   物理アドレス範囲とメモリ種類の一覧を作成。 2.物理アドレスマップ作成 3.物理メモリ領域テーブルを解析しカーネルの物理メモリ配置を示す  変数の初期化。            
  79. 79. 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
  80. 80. 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で詳細な物理メモリレイアウトを見られる。      
  81. 81. 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インスタンスは保存用            
  82. 82. 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   
  83. 83. 1.アドレス変換機能 – 物理メモリレイアウト(9) ・Linuxカーネルが使用するページフレーム ※後日更新予定 ページフレーム 範囲 用途 _text ~ _etexts カーネルコード _etext ~ _edata 初期化されたカーネルデータ _edata ~ end 初期化されていないカーネルデータ
  84. 84. 1.アドレス変換機能 – 物理メモリレイアウト(10) ・プロセスのページテーブル  ・ユーザーモード⇒0xC0000000未満を利用  ・カーネルモード⇒0xC0000000以上を利用  ・PAGE_OFFSET = 0xC0000000  ・カーネルがユーザーモードプロセスのデータを取り出したり書き込んだりする    場合には、ユーザーモードのリニアアドレス空間にアクセス  ・PGD前半エントリ:0xC0000000未満,プロセス固有のエントリ  ・PAE無効時:先頭768エントリがプロセス固有  ・PAE有効時:先頭3エントリがプロセス固有  ・残りのエントリ:全プロセス共通。           マスターカーネルPGDの対応するエントリと一致
  85. 85. 1.アドレス変換機能 – 物理メモリレイアウト(11) ・カーネルのページテーブル  ・マスターカーネルPGD    カーネル自身が使用するページテーブル群。    システム初期化後にプロセスやカーネルスレッドが直接使用する事は無い。    高位部エントリは全プロセスのPGDの雛形。    マスターカーネルPGDの変更が、プロセスが利用しているPGDに反映される。  ・カーネルのページテーブルの初期化    0.リアルモード    1.限定したアドレス空間を生成。       カーネルコードセグメント,カーネルデータセグメント,初期のページテーブル,       動的確保のデータ構造の領域。    2.存在する全てのRAMを利用してページテーブルを初期化。    ※ブートの章に詳細記述
  86. 86. 2.メモリ保護機能 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  87. 87. 2.メモリ保護機能(1) ・セグメントへのアクセスチェック   ・リミット   ・タイプ   ・特権レベル ・ページフレームへのアクセスチェック   ・R/W   ・U/S
  88. 88. 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はロード不可。    ・恒常的に以下をチェック        ・コードセグメントにデータを書き込む        ・読み出し専用のデータセグメントにデータを書き込む
  89. 89. 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は特権レベルを下げるために利用
  90. 90. 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 ユーザがカーネル領域にアクセス
  91. 91. 2.メモリ保護機能(5) ・セグメントへのアクセスチェック(4)  ・特権レベルチェック(2) – CSレジスタ更新時の保護    ・mov命令などでCSレジスタの直接変更は不可。     命令が存在しない。    ・CSレジスタ変更の基本ルール      ・移行先セグメントのDPL=CPL ⇒ 許可      ・それ以外は不許可    ・DPL≠CPLセグメントへのCSレジスタ変更(特権レベル切替え)      ・ゲートを用いる       コールゲート,トラップゲート,割り込みゲート,       タスクゲート
  92. 92. 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 ユーザ 読出し専用 読み書き可 スーパーバイザ 読み書き可 読み書き可
  93. 93. 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 読み書き可能
  94. 94. 2.メモリ保護機能 1.アドレス変換機能   概要,   x86におけるセグメンテーション,   x86_64におけるセグメンテーション,   Linuxにおけるセグメンテーション,   x86におけるページング,   x86_64におけるページング,   Linuxにおけるページング,   アドレス変換バッファ,   物理メモリレイアウト, 2.メモリ保護機能 3.キャッシュ制御機能
  95. 95. 3.キャッシュ制御機能(1) ・ハードウェアキャッシュ  ・局所性原理    繰り返し処理を行うプログラムや配列に収められた関連データ、    最後に利用されたアドレス付近は、    高確率で時間をおかず再利用される。  ・キャッシュ方式   1.ダイレクトマップ方式    メインメモリ内にあるラインは、常にキャッシュ内の同じ位置に置く。   2.完全連想キャッシュ方式    メインメモリ内の任意ラインを、キャッシュ内の任意ラインに置く。   3.Nウェイセット連想キャッシュ    メインメモリ内の任意ラインを、キャッシュ内のNライン内の1つに置く。  ・プロセッサのハードウェアキャッシュ   [DRAM]----[キャッシュコントローラ]----[ページング回路] | | [SRAMキャッシュメモリ]
  96. 96. 3.キャッシュ制御機能(2) ・キャッシュコントローラ   ・キャッシュコントローラ内に、キャッシュメモリの1ラインの情報を    示す要素の配列がある。   ・配列要素     タグ:現在割り当てられているメモリの位置     キャッシュライン状態フラグ       
  97. 97. 3.キャッシュ制御機能(3) ・キャッシュ検索   ・物理アドレス     上位:タグ     中位:サブセットのインデックス     下位:ライン内のオフセット   ・検索の流れ     1.物理アドレスからサブセットのインデックス抽出     2.サブセット内にある全ラインのタグと物理アドレスの上位ビット比較     3.上位ビットと同じタグが見つかればキャッシュヒット。      それ以外はキャッシュミス。     4.キャッシュヒットの場合      読み込み時        キャッシュラインからデータを選出し、レジスタに転送      書き込み時       ・ライトスルー         常にRAMとキャッシュラインの両方に書き込む       ・ライトバック         キャッシュラインのみ書き込む         RAM更新は、          ・CPUがキャッシュエントリ無効化(フラッシュ)要求命令を実行した場合。          ・FLUSHハードウェア信号が発生した場合。         ※通常はキャッシュミスのあと     5.キャッシュミスの場合       キャッシュラインはメモリに書込まれ、必要ならばRAMから正しいラインに取り出し、       キャッシュエントリに置く。
  98. 98. 3.キャッシュ制御機能(4) ・キャッシュスヌーピング   ・マルチプロセッサの場合、プロセッサ毎に独立したハードウェアキャッシュがある為、    各キャッシュの同期を行うハードウェア機構が必要。   ・あるCPUが自身のハードウェアキャッシュを更新する時には、    他のCPUのハードウェアキャッシュが同じデータを持っているかどうかを調べる必要あり。    同じデータを持っている場合は、他のCPUに更新を知らせ、正しい値を渡す。    これはハードウェアで行われる。 ・キャッシュの種類   ・L1キャッシュ   ・L2キャッシュ   ・L3キャッシュ      ※数字が上がるにつれて、大容量・低速になっていく。   ※キャッシュ間の整合性はハードウェアが行う。   ※Linuxでは1つのキャッシュとして扱っている。 ・キャッシュの設定   ・Pentium以降は、PCD,PWTを変えることで、    OSがページフレーム毎に異なるキャッシュ方式を持てる。   ・Linuxでは常に、PCD=PWT=0    ページフレームで常にキャッシュ有効&書き込み時はライトバック。
  99. 99. 3.キャッシュ制御機能(5) ・ハードウェアキャッシュの制御  ・L1_CACHE_BYTESマクロ    キャッシュラインのバイト数     ~Pentium4:32byte     Pentium4:128byte  ・ヒット率最適化方針    ・構造体のうち、最も頻繁に使用するメンバを低いオフセットに集めて、     同じラインに乗るようにする。    ・多数のデータを割り当てる時は、全キャッシュラインを均等に使用する様に     データの配置を行う。  ・キャッシュの同期処理    x86:     自動で行う為、カーネルはハードウェアキャッシュのフラッシュ処理は行わない。    同期無しプロセッサ:     カーネルはフラッシュ処理のインターフェイスを提供しているのでそれを利用。   

×