はじめに
- 仮想化はOSにより提供される。物理アドレス空間よりとても広いアドレス空間 (仮想アドレス空間)が使用可能になるためメモリ外にもアドレスを割り振ることができ、嬉しい。
- アドレスマップというものがある。アドレス空間のうちこの領域はこう使う、と予め決められていることがある。今回使用するCora Z7-07Sボードに搭載されているZynq SoCでも同様で、以下のような区分けがされている。
疑問
Cora Z7-07Sボード上にDDR3メモリは512MBの容量があるとのこと。
一方でアドレスマップではDDRに1GB分のアドレス空間が割り当てられている。
OSが介在し仮想化が働くならその余剰分もうまくsdカードなどメモリ外の記憶媒体にも割り当てることが出来る。
もし、OS無しの環境下で512MB分ある物理アドレス空間の外にアクセスするとどんな扱いを受けるのだろうか。
検証
まずはVIVADOでVITISに持ち込むxsaファイル (bitstream)の用意。
ZynqのPS部分だけを使用するためブロック図はとても簡潔。
周辺機器を使用しないため制約ファイルも必用ない。PSからのUART通信で挙動を確認する。
ここの具体的な手順はFPGAプログラミング大全 Xilinx編を参考にされたし。
次にVITISでPS上で動作させる.cを作成する。
プロジェクトを作成するとlscript.ldが自動生成されている。リンカスクリプトにはアドレス空間のどこをどう使うかの区分けが書かれている。本来は見づらいが、画像のようにVITISが見やすく表示してくれていた。
ps7_ddr_0
はアドレスマップに記載されている0010_0000~3FFF_FFFF
の半分の領域を示している。ps7_ram_0
ps7_ram_1
はアドレス空間の上位下位に比較的小さく確保されている。ユーザーが使うような領域ではなさそうなので放置。
ps7_ddr_0
に.text
や.data
セクションが配置されているのでこの領域にプログラムが保存されているとわかる。 (.text領域の始まる開始アドレスなどはリンカが走るまで分からない。設定しようと思えば出来るのだろうか。)
ps7_ddr_0
にはDDRに割かれた1GB分のアドレス空間の半分が割り当てられている。つまり512MBで、これはCora Z7-07Sに搭載されているDDR3メモリの大きさに等しい。
プログラムからアクセスできるアドレスをこのリンカスクリプトでうまく制限している?
本当に仮想化の働かないOS不在の環境下で安全にプログラムを動作させることができるのだろうか。
VITISがVIVADOで宣言したシステムに応じてxparameters.h
を用意してくれる。この中にアドレス空間の上限下限が記載されているため活用する。.c内で物理アドレスの外へ書き込むプログラムを作成した。
#define XPAR_PS7_DDR_0_BASEADDRESS 0x100000
#define XPAR_PS7_DDR_0_HIGHADDRESS 0x20000000
#include "xparameters.h"
#include "xil_printf.h"
#define OUT_OF_DDR *((volatile unsigned char *) XPAR_PS7_DDR_0_HIGHADDRESS)
int main(void){
OUT_OF_DDR = 'A';
xil_printf("%c\r\n", OUT_OF_DDR);
return 0;
}
512MB領域の丁度外側1byteの位置にAを書き込んで読み出すという処理。
ビルド (コンパイル)は成功。リンカが領域外アクセスにエラーを出すものと思っていたため驚いた。
実行する。
OUT_OF_DDR = 'A'
するとxil_exception.c
内の無限ループに案内された。
CPU側から例外として扱われた。
結論
OSの無い環境下で物理アドレス空間の外にアクセスすると例外として処理される。
参考
Zynq-7000 SoC テクニカルリファレンス マニュアル https://docs.amd.com/v/u/ja-JP/ug585-Zynq-7000-TRM