MMU(メモリマネージメントユニット)

MMUの設定

ARMプロセッサを使用する場合、メモリ領域に合わせてメモリタイプ(第10回参照)を設定します。プログラムやデータを配置する領域は、ノーマルメモリでキャッシュを有効に設定し、ペリフェラルを配置する領域は、デバイスメモリまたはストロングリオーダメモリに設定します。SCTLR(システム制御レジスタ)のIビットとCビットで命令キャッシュとデータキャッシュを有効にできますが、データキャッシュはMMUを有効にしないと使用できません。MMUを搭載するARMプロセッサを使用する場合、メモリタイプ(ノーマルメモリ・デバイスメモリ・ストロングリオーダメモリ)・キャッシュ・アクセス権の設定はMMUで行いますので、設定を理解しなければなりません。

【MMUと命令キャッシュ動作設定一覧表】
命令キャッシュ設定
SCTLR Iビット
MMU動作設定
SCTLR Mビット
命令キャッシュ
動作設定
無効 無効 無効
無効 有効 無効
有効 無効 有効
有効 有効 変換テーブルの設定による
【MMUとデータキャッシュ動作設定一覧表】
データキャッシュ設定
SCTLR Cビット
MMU動作設定
SCTLR Mビット
データキャッシュ
動作設定
無効 無効 無効
無効 有効 無効
有効 無効 無効
有効 有効 変換テーブルの設定による

MMUの動作概要

仮想アドレスから物理アドレスへのアドレス変換は、MMUとTLB(トランスレーション・ルックアサイド・バッファ)を使用します。アドレス変換は、テーブルウォークユニットで変換テーブルを参照して自動的に変換を行い、TLBのキャッシュも行います。変換テーブルに、メモリタイプ・キャッシュ属性・バッファ属性を設定できます。

変換テーブルは、第1レベルテーブルと第2レベルテーブルで構成します。第1レベルテーブルでは、16Mバイトと1Mバイトの単位で仮想アドレスから物理アドレスに変換を行い、第2レベルテーブルを使用することで、より細かい64Kバイトと4Kバイトの単位で仮想アドレスから物理アドレスに変換できます。仮想アドレスから物理アドレスに変換する単位をページサイズと呼び、16Mバイトを「スーパーセクション」、1Mバイトを「セクション」、64Kバイトを「ラージページ」、4Kバイトを「スモールページ」と呼びます。

図1

仮想アドレスから物理アドレス変換動作

MMUは、次の手順に従って、アドレス変換を行います。

  • ①仮想アドレス[31:20]ビットから、第1レベルテーブルの該当する1ワード(4バイト)の第1レベル記述子を参照。
  • ②第1レベル記述子の設定で、物理アドレスを求めるか、第2レベルテーブルを参照するかを決定。
  • ③第2レベルテーブルを使用する場合、仮想アドレス[19:12]ビットから、第2レベルテーブルの該当する1ワード(4バイト)の第2レベル記述子を参照し物理アドレスを求める。
  • ④第1レベルテーブルは、物理メモリ空間に16Kバイトのサイズで16Kバイト境界に配置し、第2レベルテーブルは、物理メモリ空間に1Kバイトのサイズで1Kバイト境界に配置。

変換テーブルとページサイズ

第1レベルテーブルの先頭アドレスは、TTBR0(変換テーブルベースレジスタ0)またはTTBT1(変換テーブル ベースレジスタ1)に設定しますので、第1レベルテーブルは2種類使用できます。第1レベルテーブルを1種類使用する場合は、TTBR0を使用します。

ページサイズ 第1レベルテーブル 第2レベルテーブル
スーパーセクション(*1)(16Mバイト) ×
セクション(1Mバイト) ×
ラージページ(64Kバイト)
スモールページ(4Kバイト)
  • (*1)スーパーセクションのサポートはオプションです。

第1レベル記述子の形式

第1レベルテーブルは、1ワード(4バイト)の第1レベル記述子で設定します。[1:0]ビットで、「フォルト」「ページテーブル」「セクション」「スーパーセクション」を選択します。「ページテーブル」の場合、第2レベルテーブルの先頭アドレスを1Kバイト境界で設定し、「セクション」の場合は物理アドレスの[31:20]、「スーパーセクション」の場合は物理アドレスの[31:24]に設定します。他の設定に関しては、下記レベル記述子設定についてを参照ください。

図2

第2レベル記述子の形式

第2ベルテーブルは、1ワード(4バイト)の第2ベル記述子で設定します。[1:0]ビットで、「フォルト」「ラージページ」「スモールページ」を選択します。「ラージページ」の場合は物理アドレスの[31:16]、「スモールページ」の場合は物理アドレスの[31:12]に設定します。他の設定に関しては、下記レベル記述子設定についてを参照ください。

図3

レベル記述子設定について

第1レベル記述子と第2レベル記述子で行う各種設定を説明します。

メモリタイプとキャッシュ設定一覧

メモリタイプとキャッシュ設定および共有設定を行います。共有設定は、メモリタイプの設定によって設定ができない場合があります。TEX[2]=1の場合、キャッシュを内部属性と外部属性を個別に設定します。

TEX[2:0] C B メモリタイプ 設定内容 共有設定
000 0 0 ストロングリオーダ ストロングリオーダ 共有可能
000 0 1 デバイス 共有デバイス 共有可能
000 1 0 ノーマル 外部および内部ライトスルー
ライトアロケートなし
Sビット
000 1 1 ノーマル 外部および内部のライトバック
ライトアロケートなし
Sビット
001 0 0 ノーマル 外部と内部でキャッシュ不可 Sビット
001 0 1 - 予約 -
001 1 0 - 実装定義 -
001 1 1 ノーマル 外部・内部ライトバック
ライトアロケートあり
Sビット
010 0 0 デバイス 非共有デバイス 共有不可
010 0 1 - 予約 -
010 1 X - 予約 -
011 X X - 予約 -
1BB A A ノーマル キャッシュ可能メモリ
BB = 外部属性 AA = 内部属性
Sビット

TEX[2]=1設定時の設定一覧

キャッシュの内部属性と外部属性の設定は次の形式で設定します。(内部属性:L1キャッシュ、内部属性:L2キャッシュ)

外部属性 内部属性 キャッシュ属性
TEX[1] TEX[0] C B
0 0 0 0 キャッシュ不可
0 1 0 1 ライトバック・ライトアロケート
1 0 1 0 ライトスルー・ライトアロケートなし
1 1 1 1 ライトバック・ライトアロケートなし

アクセス権設定

AP[2:0]で、ページサイズ毎にアクセス権の設定ができます。複数のアクセス属性を変更する場合、第1レベルテーブルの「ドメイン」を利用することで、効率的にアクセス権の設定変更ができます。詳しくは、下記ドメインの使用方法を参照ください。

AP[2:0] 特権動作設定 非特権動作設定 内容
000 アクセス不可 アクセス不可 アクセス不可
001 読み出し/書き込み アクセス不可 特権アクセスのみ
010 読み出し/書き込み 読み出し ユーザモードの書み込み不可
011 読み出し/書き込み 読み出し/書込み 完全アクセス
100 - - 予約
101 読み出し アクセス不可 特権読み出し
110 読み出し アクセス不可 読み出し専用
111 - - 予約

その他の設定

設定 内容
XN 実行禁止を設定します。この領域から命令フェッチができるかどうかを示します。
S S=0:ノーマルメモリ領域が共有できません。
S=1:ノーマルメモリ領域が共有できます。
※エントリがデバイスメモリ・ストロングリオーダメモリの場合、無視されます。
nG 非グローバルを設定します。
nG=0:変換はグローバルです。
nG=1:変換はアドレス空間識別子(ASID)に関連します。
NS “セキュア” アクセスビットを設定します。
第15回:TrustZone(セキュリティ拡張機能)」で説明します。
ドメイン DACRで定義されるアクセスパーミッションを選択します。
詳しくは、下記「ドメインの使用方法」を参照ください。

ドメインの使用方法

第1レベル記述子の「ページテーブル」「セクション」のドメイン([8:5]ビット)設定は、DACR(ドメインアクセス制御レジスタ)のD15からD0を選択します。「スーパーセクション」は、ドメイン設定がないのでD0が選択されます。アクセス設定はページサイズごとに行いますが、複数ページのアクセス権を変更する場合、複数の第1レベル記述子を変更と同時に、TLBメンテナンスを行わなければなりません。DACRのドメイン番号の設定値を書き換えることで、変換テーブルのアクセス許可設定を無視できます。

図4

【DACR】

【ドメイン設定一覧表】
設定値 設定内容
0b00 アクセス不可設定
0b01 クライアント設定(変換テーブルのアクセス許可ビット設定になります)
0b10 予約
0b11 マネージャ設定(変換テーブルのアクセス許可ビットはチェックしません)

テーブルを使用したアドレス変換

第1レベルテーブルを使用したアドレス変換

第1レベルテーブルを使用した「セクション」で、仮想アドレスから物理アドレスに変換する動作を説明します。第1レベルテーブルは、0x000F_0000番地から配置し、仮想アドレス0x0010_0000番地を物理アドレスに変換します。

  • ①仮想アドレスの[31:20]ビットを使用して、第1レベルテーブルのオフセットアドレスを求める。
  • ②第1レベルテーブルは、仮想アドレス1Mバイト単位毎に、第1レベル記述子が保存されているので、以下の計算式で第1レベルテーブルのアドレスを求める。
    アドレスオフセット = 仮想アドレス[31:20]ビット×4 =0x001×4=0x004
    テーブルアドレス
     = 第1レベルテーブルアドレス+アドレスオフセット
     = 0x000F_0000+0x004 = 0x000F_0004
  • ③0x000F_0004番地の第1レベル記述子を読み出し、第1レベル記述子の[31:20]ビットが、物理アドレスの[31:20]ビットになり、仮想アドレスの[19:0]ビットは、物理アドレスの[19:0]ビットになります。
図5

セクションのアドレス変換設定例

第1レベルテーブルを使用し、「セクション」で仮想アドレスから物理アドレスに変換する場合の設定例を説明します。連続して配置されていない仮想アドレス3領域を、連続した物理アドレス空間に配置します。

仮想アドレス メモリ設定 物理アドレス
0xFFFF_FFFF
0xFFF0_0000
ノーマルメモリ
1Mバイト
0x004F_FFFF
0x0040_0000
0xFFEF_FFFF
0x4020_0000
アクセス禁止空間 -
0x401F_FFFF
0x4000_0000
ノーマルメモリ
2Mバイト
0x003F_FFFF
0x0020_0000
0x3FFF_FFFF
0x0020_0000
アクセス禁止空間 -
0x001F_FFFF
0x0000_0000
ノーマルメモリ
2Mバイト
0x001F_FFFF
0x0000_0000

第1レベルテーブルの設定を行う場合、仮想アドレスの[31:20]ビットでテーブルを参照し、テーブルの[31:20]ビットが物理アドレスの[31:20]ビットになり、物理アドレスの[19:0]ビットは仮想アドレスの[19:0]ビットになります。例えば、0x400n_nnnn番地を変換する場合、第1レベルテーブルのオフセットは0x400×4=0x1000になり、テーブルの[31:20]ビットに0x002を設定します。仮想アドレスの0x400n_nnnn番地をアクセスした場合、物理アドレスの0x002n_nnnn番地にアクセスします。

図6

第2レベルテーブルを使用したアドレス変換

第1レベルテーブルと第2レベルテーブルを使用した「スモールページ」で、仮想アドレスから物理アドレス変換を行う場合の動作を説明します。第1レベルテーブルは、0x000F_0000番地から配置し、仮想アドレス0x0020_0000番地を物理アドレスに変換します。

  • ①仮想アドレスの[31:20]ビットを使用して、第1レベルテーブルのオフセットアドレスを求る。
  • ②第1レベルテーブルは、仮想アドレス1Mバイト単位ごとに、第1レベル記述子が保存されているので、以下の計算式で第1レベルテーブルのアドレスを求める。
    アドレスオフセット = 仮想アドレス[31:20]ビット×4=0x002×4=0x008
    テーブルアドレス
     = 第1レベルテーブルアドレス+アドレスオフセット
     = 0x000F_0000+0x008 = 0x000F_0008
  • ③0x000F_0008番地の第1レベル記述子を読み出し、第1レベル記述子の[31:10]ビットが第2レベルテーブルの先頭アドレスになる。
  • ④仮想アドレスのビット[19:12]は、仮想アドレス空間アクセス場所を4Kバイト単位で示す。
    アドレスオフセット = 仮想アドレス[19:12]ビット×4 = 0x00×4 = 0x000
  • ⑤第2レベルテーブルの第2レベル記述子を読み出し、第2レベル記述子の[31:12]ビットが物理アドレスの[31:12]ビットになり、仮想アドレスの[11:0]ビットは物理アドレスの[11:0]ビットになる。
図7

スモールページのアドレス設定例

第1レベルテーブルと第2レベルテーブルを使用し、「スモールページ」で、仮想アドレスから物理アドレスに変換する場合の設定例を説明します。仮想アドレス0x4000_0000番地から32Kバイトの空間を4Kバイト単位で物理アドレス0x0010_0000番地および0x0020_0000番地を先頭に配置します。

仮想アドレス メモリ設定 物理アドレス
0xFFFF_FFFF
0x4000_8000
アクセス禁止空間 -
0x4000_7FFF
0x4000_7000
ノーマルメモリ
32Kバイト
0x0020_3FFF
0x0020_3000
0x4000_6FFF
0x4000_6000
0x0010_3FFF
0x0010_3000
0x4000_5FFF
0x4000_5000
0x0020_2FFF
0x0020_2000
0x4000_4FFF
0x4000_4000
0x0010_2FFF
0x0010_2000
0x4000_3FFF
0x4000_3000
0x0020_1FFF
0x0020_1000
0x4000_2FFF
0x4000_2000
0x0010_1FFF
0x0010_1000
0x4000_1FFF
0x4000_1000
0x0020_0FFF
0x0020_0000
0x4000_0FFF
0x4000_0000
0x0010_0FFF
0x0010_0000
0x3FFF_FFFF
0x0010_0000
アクセス禁止空間 -
0x000F_FFFF
0x0000_0000
ノーマルメモリ
1Mバイト
0x000F_FFFF
0x0000_0000

第1レベルテーブルを仮想アドレスの[31:20]ビットでテーブルを参照し、第2レベルテーブルの先頭アドレスを求めます。仮想アドレスの[19:12]ビットで第2レベルテーブルを参照し、テーブルの[31:12]が物理アドレスの[31:12]になり、物理アドレスの[11:0]ビットは仮想アドレスの[11:0]ビットになります。例えば、0x4000_0nnn番地を変換する場合、第1レベルテーブルのオフセットは0x400×4=0x1000になり、テーブルの[31:10]ビットに設定されている第2レベルテーブルの先頭アドレスを求めます。第2レベルテーブルのオフセットは0x00×4=0x00になり、テーブルの[31:12]ビットに0x00100を設定します。仮想アドレスの0x4000_0nnn番地をアクセスした場合、物理アドレスの0x0010_0nnn番地にアクセスします。

図8

サンプルプログラム

第1レベルテーブルで「セクション」を選択した場合のサンプルプログラムを説明します。仮想アドレス = 物理アドレスとして配置します。

第1レベルテーブル作成サンプルプログラム

第1レベルテーブルの構築をRAM領域に作成するサンプルプログラムです。プログラムは、0x0番地から1Mバイトの領域をノーマルメモリ/内部キャッシュはライトバック/ライトアロケートなし/外部キャッシュ不可に設定します。他の領域はストロングリオーダメモリの設定を行い、第1レベルテーブルは0x0010_0000番地から配置します。ドメインは、D16を参照する設定にします。

								LEVEL1_BASE_ADDR  EQU 0x00100000  ; 第1レベルテーブルの先頭アドレス
								VECTOR_BASE_ADDR  EQU 0x00000000  ; ベクタテーブル先頭アドレス

								;
								;  TTBCR(テーブル変換ベース制御レジスタ)/TTBR0の設定
								;
								  MOV   r0,#0x0                ; TTBCR 0x0の初期値
								  MCR   p15,0,r0,c2,c0,2       ; TTBCRの書き込み
								  LDR   r0,=LEVEL1_BASE_ADDR   ; 第1レベルテーブルアドレスを設定
								  MOV   r1,#0x48               ; TTBR0の初期化を実施
								                               ; TTBR0.IRGN[6.0]=01:ノーマルメモリ
								                               ; 内部ライトバック書き込み割り当てキャッシュ可能
								                               ; TTBR0.S[1]=0:共有不可設定
								                               ; TTBR0.RGN[4:3]=01:ノーマルメモリ
								                               ; 外部ライトバック・ライトアロケート・キャッシュ可能
								  ORR   r0,r0,r1               ; TTBR0の設定値を設定
								  MCR   p15,0,r0,c2,c0,0       ; TTBR0の書き込み
								;
								; 第1レベルテーブルの作成
								;
								  LDR   r0,=LEVEL1_BASE_ADDR   ; 第1レベルテーブルアドレスを設定
								  LDR   r1,=0xfff              ; ループカウンタを初期化
								  LDR   r2,=0x00000de2         ; テーブルの初期設定値を設定
								init_ttb_1
								  ORR   r3,r2,r1,LSL#20        ; ベースアドレスを設定
								  STR   r3,[r0,r1,LSL#2]       ; 第1記述子書き込み
								  SUBS  r1,r1,#1               ; ループカウンタを-1
								  BPL   init_ttb_1             ; 変換テーブル作成終了?
								;
								; ベクタ領域の第1記述子を変更
								;
								  LDR   r1,=VECTOR_BASE_ADDR   ; ベクタの先頭アドレスを設定
								  LSR   r1,#20                 ; 1Mバイト境界にアドレスを設定
								  ORR   r3,r2,r1,LSL#20        ; テーブルの初期値を求める
								  ORR   r3,r3,#0x0c            ; ノーマルメモリ内部キャッシュ可能設定
								  ORR   r3,r3,#0x1000          ; 外部キャッシュ不可設定
								  STR   r3,[r0,r1,LSL#2]       ; テーブルエントリを設定
								

ドメインの初期化

ドメイン設定は、D0からD15の全ての設定を「クライアント」に設定しています。第1レベル記述子のドメイン設定値(5ビットから8ビットの範囲を設定)がDACRを参照します。「クライアント」設定は、第1レベル記述子のアクセス設定に準じます。

								;==================================================
								; ドメインアクセス制御レジスタの全クライアント設定
								;==================================================
								  LDR  r0,=0x55555555         ; クライアント設定
								  MCR  p15,0,r0,c3,c0,0       ; DACRに書き込み
								

MMUの稼働設定

MMUは、リセット時は非稼働に設定されているので、終了後に全ての設定を有効にします。第1レベルテーブルの設定(4096個の第1レベル記述子)/TTBCRの設定/TTBR0/TTBR1/DACRの各設定が適切であることを確認した後に、SCTLRのMビットを有効に設定します。

								;
								; MMUを稼働状態に設定
								;
								  MRC  p15,0,r0,c1,c0,0     ; SCTLRを読み込み
								  ORR  r0,r0,#0x1           ; MMUを稼働状態に設定 (SCTLR.M[0])
								  MCR  p15,0,r0,c1,c0,0     ; SCTLRに書き込み