Cortex-AはMMU(メモリ管理ユニット)とTLB(トランスレーション・ルックアサイド・バッファ)を用いて、仮想アドレスを物理アドレスに変換します。
Cortex-AのMMUでは、4KB、64KB、1MB、16MBをサポートするページテーブル エントリを有し、各エントリには、仮想アドレス、ページサイズ、物理アドレスとメモリタイプ属性が格納されます。
このメモリタイプ属性には、次のようなものがあります。
これに加えて、実行禁止属性も設定できますので、不当メモリアクセスを検出するにはMMUを活用することが有効です。
しかし、Cortex-Aプロセッサを使用する場合、MMUの設定が比較的複雑であることに加え、設定を間違えてしまうとそもそもプログラムのロードが出来なかったり、すぐに例外が発生してプログラムが起動しないなど、プログラムを動かすまでに苦労が多いのが実態です。
MMUの活用が有効と分かっていても、難しくて使えない、面倒で使わない、そんな障壁を解消するため、SOLIDでは誰でも簡単にMMUを使えるようメモリタイプ属性の自動設定機能を設けています。
まずビルド時、ロードモジュールを生成する際にはリンカスクリプトで指示された内容に従い、以下の様なメモリセクション属性や、論理<->物理変換などのテーブルが生成されます。
.text(コード領域)
.rodata(ライト不可のデータ、定数など)
.data(リード/ライト可、実行不可)
.bss(リード/ライト可、実行不可)
SOLIDで対象ハードウエア(SoCやボードなど)を選択した時点で自動的にデフォルトのリンカスクリプトが選択されますので、ユーザーは特にリンカスクリプトの内容を意識する必要はありません。
次にプログラムに実行時は、ビルド時に作られた前述のテーブル情報をもとにSOLIDがMMUのTLBやページテーブルを設定するためのランタイムを生成し、そのランタイムを初期化処理の一部として実行します。このためユーザーは、自身のプログラムの中で煩雑なMMUの設定が不要になります。
また、論理<->物理アドレスの対応や、メモリセクション属性は、SOLIDのメモリマップデザイナで、分かりやすく参照、簡単に変更ができます(図1-1)。メモリマップデザイナ上で行った変更は、MMUの設定内容にも反映されます。
なおプログラムのリリース時には、MMU設定内容はSOLIDコアサービス(ターゲットの資源管理などを行うソフトウェア)の一部として提供されます。
図1-1. SOLIDメモリマップデザイナで、メモリ属性や論理<->物理アドレス対応を参照・変更
このようにセクションの種別に合わせたメモリセクション属性が設定されるため、プログラム実行中に不当なアクセス(ライト不可領域へのライトアクセスなど)があればただちにプロセッサ例外が発生します。プロセッサ例外が発生した場合、SOLIDデバッガでは例外の種類を判定し、それをデバッガ画面上に表示します(第一回の解説でご紹介)。
SOLIDには論理アドレス空間に自動的にセクションデータを配置する機能があります。その際、セクションとセクションの間に隙間を空け、その隙間には物理アドレスを割り当てないことで、プログラムの暴走(図2-2)やスタックメモリの突き抜け(図2-3)などを、プロセッサのアクセス例外として検出できるようにしています。
図2-2. プログラム暴走時は、コード領域境界でバグを自動検出
図2-3. スタック突き抜け時は、スタックメモリ領域境界でバグを検出
Cortex-A MMUのメモリエントリサイズは、4KB、64KB、1MB、16MBという単位で管理されます。もしプログラムで指定したスタックメモリがこの単位と異なる場合は、SOLIDはスタックの上限(スタックを積む方向)にアドレス境界を合わせて配置します(図2-4)。というのも、スタックメモリに関わるバグの殆どが、スタックの積み過ぎ(想定を超えた多重割り込みなど)が原因だからです。
図2-4. スタック上限をメモリエントリ境界に合わせて配置する
なお、論理空間上は隙間をあけてメモリを配置しますが、物理空間においては極力隙間を空けずにメモリを配置することでメモリを効率的に利用します。またSOLIDがターゲットとしているRTOSベースのシステムにおいては1つの論理空間に全てのメモリを配置することで、メモリスワッピングなどによるリアルタイム性への影響を受けないようにしています。
このアクセス例外によるバグ検出機能においては、実行プログラムサイズおよび実行時間に対するオーバーヘッドは発生しません。