コプロセッサの概要
コプロセッサとは?
Armプロセッサ(Cortex-Mシリーズを除く)を使用する場合、プロセッサ機能のキャッシュやMMUなどの設定はコプロセッサで行うため、コプロセッサレジスタを理解しなければなりません。コプロセッサは、メモリ空間に配置されていないため、専用命令を使用し、読み込みおよび書き込みを行います。メモリ空間に配置されないことで、4Gバイトすべてのメモリ空間を有効に使用できるメリットがあります。特権モードでしかアクセスできないコプロセッサレジスタがありますので、ご利用のプロセッサの「テクニカルリファレンスマニュアル(*1)」を参照ください。
- コプロセッサは、16個のコプロセッサが定義されています。
- CP15(コプロセッサ15)は、システム制御機能を提供します。
- CP11(コプロセッサ11)は、倍精度の浮動小数点演算をサポートします。
- CP10(コプロセッサ10)は、単精度の浮動小数点演算に加えて、VFPアドバンスドSIMDの両方のアーキテクチャの機能拡張をサポートします。
(*1)英語版「Cortex-A9 Technical Reference Manual Revision:r4p1」または、日本語版「Cortex-A9 テクニカルリファレンス マニュアルリビジョン:r2p2」を参照ください。
コプロセッサのアクセス命令
コプロセッサのアクセスは、MRC/MCR命令で行います。特権モードでしかアクセスできないコプロセッサレジスタがありますので、注意して使用します。
MRC命令
MRC命令は、コプロセッサレジスタからプロセッサレジスタに読み込みを行います。
MRC{ cond } coproc,# opcode1,Rd,CRn,CRm {, # opcode2 }
設定項目 | 設定内容 |
---|---|
cond | 任意の条件コードを指定します。 |
coproc | 命令が実行されるコプロセッサの名前を指定します。 コプロセッサcp15の場合は、p15設定となります。 |
opcode1 | 3ビットコプロセッサ固有のオペコードを指定します。 |
opcode2 | オプションとしての3ビットコプロセッサ固有のオペコードを指定します。 |
Rd | デスティネーションプロセッサレジスタを指定します。r15(PC)は設定できません。 |
CRn | コプロセッサレジスタを指定します。 |
CRm | コプロセッサレジスタを指定します。 |
MCR命令
MCR命令は、プロセッサレジスタからコプロセッサレジスタに書き込みを行います。
MCR{ cond } coproc,#opcode1,Rd,CRn,CRm {, # opcode2 }
設定項目 | 設定内容 |
---|---|
cond | 任意の条件コードを指定します。 |
coproc | 命令が実行されるコプロセッサの名前を指定します。 コプロセッサcp15の場合は、p15設定となります。 |
opcode1 | 3ビットコプロセッサ固有のオペコードを指定します。 |
opcode2 | オプションとしての3ビットコプロセッサ固有のオペコードを指定します。 |
Rd | ソースプロセッサレジスタを指定します。r15(PC)は設定できません。 |
CRn | コプロセッサレジスタを指定します。 |
CRm | コプロセッサレジスタを指定します。 |
コプロセッサへのアクセス方法
Armコンパイラを使用して、コプロセッサにアクセスする場合、“__asm
”キーワードを使用したインラインアセンブリ言語またはアセンブリ言語で作成します。
C/C++コンパイラでのコプロセッサにアクセスする例
インラインアセンブリ言語を使用する場合、アセンブリ命令を__asm{….}でまとめて記述できます。
void enable_caches( void ) { unsigned long reg; __asm { MRC p15,0,reg,c1,c0,0 // SCTLR(システム制御レジスタ)を読み込み ORR reg,reg,#(0x1 << 12) // 命令キャッシュを許可(SCTLR.I [12]) ORR reg,reg,#(0x1 << 2) // データキャッシュを許可(SCTLR.D [2]) ORR reg,reg,#(0x1 << 11) // プログラムフロー予測を許可(SCTLR.Z [11]) MCR p15,0,reg,c1,c0,0 // SCTLRを書き込み //================================================================== // Cortex-A9のデータプリフェッチ機能を許可 //================================================================== MRC p15,0,reg,c1,c0,1 // ACTLR(補助制御レジスタ)を読み込み ORR reg,reg,#(0x1 << 2) // データプリフェッチ起動を有効 (ACTLR.DP[2]) MCR p15,0,reg,c1,c0,1 // ACTLRを書き込み } }
アセンブリ言語のコプロセッサにアクセスする例
「AAPCS(Armアーキテクチャのプロシージャコール標準)」に従って、アセンブリプログラムを作成することで、C/C++言語から関数としてコプロセッサアクセス命令を実行することができます。
EXPORT enable_caches ; キャッシュ・分岐予測の許可 enable_caches FUNCTION MRC p15,0,r0,c1,c0,0 ; SCTLRを読み込み ORR r0,r0,#(0x1 << 12) ; 命令キャッシュを許可(SCTLR.I[12]) ORR r0,r0,#(0x1 << 2) ; データキャッシュを許可します。(SCTLR.D[2]) ORR r0,r0,#(0x1 << 11) ; プログラムフロー予測を許可します。(SCTLR.Z[11]) MCR p15,0,r0,c1,c0,0 ; SCTLRを書き込み ;================================================================== ; データプリフェッチ機能を許可 ;================================================================== MRC p15,0,r0,c1,c0,1 ; ACTLRを読み込み ORR r0,r0,#(0x1 << 2) ; データプリフェッチ起動を有効 (ACTLR.DP[2]) MCR p15,0,r0,c1,c0,1 ; ACTLRを書き込み BX lr ENDFUNC
コプロセッサ設定例
Cortex-A9プロセッサの初期化処理を行う場合、コプロセッサ15(CP15)に設定を行います。今回は、以下の設定に関して説明します。
- TLB (変換ルックアサイドバッファ)と分岐予測のアレイを無効化
- 命令/データキャッシュの無効化
- VFP/NEONのアクセス権と設定
- ベクタアドレスの変更設定
- キャッシュ・MMU・分岐予測の設定
TLBと分岐予測器のアレイの無効化
TLBと分岐予測器は、リセット時に初期化されませんので、初期化時に無効化します。
【サンプルプログラム】
;================================================================== ; TLBと分岐予測器アレイの無効化 ;================================================================== MOV r0,#0 ; 初期値を設定 MCR p15,0,r0,c8,c7,0 ; TLB全体無効化 MCR p15,0,r0,c7,c5,6 ; 分岐予測器アレイ無効化
TLBIALL (全体の無効化レジスタ)
- 統一TLB全体を無効化し、独立した命令TLBとデータTLBが実装されている場合は、同時に無効化します。
- 引数レジスタ<Rd>の設定値は無視し、特権モードのみで実行できます。
【レジスタへのアクセス命令】
MCR p15,0,<Rd>,c8,c7,0 ; TLB全体無効化の書き込み
BPIALL (分岐予測器アレイの無効化レジスタ)
- 分岐予測器アレイ全体を無効化します。
- 引数レジスタ<Rd>の設定値は無視し、特権モードのみで実行できます。
【レジスタへのアクセス命令】
MCR p15,0,<Rd>,c7,c5,6 ; 分岐予測器アレイ全体無効化の書き込み
命令/データキャッシュの無効化
リセット時にキャッシュは無効化されませんので、L1データキャッシュとL1命令キャッシュの無効化が必要です。データキャッシュは、ラインとウェイ毎に無効化が必要になりますので、CCSIDR (キャッシュサイズ識別レジスタ) から、キャッシュの情報を取得し無効化します。
【サンプルプログラム】
MOV r0,#0 ; 初期値に設定 MCR p15,0,r0,c7,c5,0 ; 命令キャッシュ全体の無効化 ; ; データキャッシュの無効化を行います。 ; MOV r10,#0 ; データキャッシュを選択 MCR p15,2,r10,c0,c0,0 ; キャッシュサイズ選択レジスタ(CSSELR)で ; データキャッシュを選択 ISB ; 命令同期バリア命令で再フェッチ MRC p15,1,r1,c0,c0,0 ; CCSIDRを読み込み AND r2,r1,#7 ; キャッシュラインサイズを取得(b001=8ワード/ライン) ADD r2,r2,#4 ; DCISWレジスタのセット番号のシフト数を求める LDR r4,=0x3FF ; 最大ウェイ数マスク設定値を設定 ANDS r4,r4,r1,LSR #3 ; r4レジスタにウェイ数を設定 CLZ r5,r4 ; DCISWレジスタのウェイ番号のシフト数を求める LDR r7,=0x7FFF ; セット数マスク設定値を設定 ANDS r7,r7,r1,LSR #13 ; r7レジスタにセット数を設定 ; 0x7F=12Kbyte/0xFF=32Kbyte/0x1FF=64Kbyte Loop2 MOV r9,r4 ; r9レジスタにウェイ数を設定 Loop3 ORR r11,r10,r9,LSL r5 ; ウェイ番号とキャッシュ番号を設定 ORR r11,r11,r7,LSL r2 ; セット番号を設定 MCR p15,0,r11,c7,c6,2 ; DCISWレジスタでセット/ウェイによる ; データキャッシュラインの無効化 SUBS r9,r9,#1 ; ウェイ番号を-1 BGE Loop3 ; ウェイ毎の初期化を実施 SUBS r7,r7,#1 ; セット番号を-1 BGE Loop2 ; セット毎の初期化を実施
ICIALLU(命令キャッシュ全体の無効化レジスタ)
- すべての命令キャッシュを無効化および分岐先キャッシュをフラッシュします。
- 引数レジスタ<Rd>の設定値は無視し、特権モードのみで実行可能です。
【レジスタへのアクセス命令】
MCR p15,0,<Rd>,c7,c5,0 ; ICIALLUの書き込み
CSSELR (キャッシュサイズ選択レジスタ)
- CCSIDRの選択に使用します。
- 特権モードのみで、読み込み/書き込みできます。
【レジスタへのアクセス命令】
MCR p15,2,<Rd>,c0,c0,0 ; CSSELR読み込み MCR p15,2,<Rd>,c0,c0,0 ; CSSELR書き込み
【レジスタフォーマット】
ビット | 名称 | 機能 |
---|---|---|
3:1 | レベル | キャッシュのレベルを示します。 0b000:レベル1キャッシュ~0b110:レベル7キャッシュ Cortex-A9プロセッサ内のキャッシュレベルは1レベルとなりますので、0b000となります。 |
0 | InD | 命令/データビット。 0:データまたは統一キャッシュ 1:命令キャッシュ |
CCSIDR(キャッシュサイズ識別レジスタ)
- キャッシュのアーキテクチャに関する情報を提供します。
- プロセッサからアクセス可能なキャッシュ毎に、CCSIDRが実装されています。
- CSSELRで、CCSIDRを選択します。
- 特権モードのみで、読み込みすることが出来ます。
【レジスタへのアクセス命令】
MRC p15,1,<Rd>,c0,c0,0 ; CCSIDR読み込み
【レジスタフォーマット】
ビット | 名称 | 機能 |
---|---|---|
31 | WT | ライトスルーのサポート状態を示します。 0=該当機能がサポートされていません。 1=該当機能がサポートされています。 |
30 | WB | ライトバックのサポート状態を示します。 0=該当機能がサポートされていません。 1=該当機能がサポートされています。 |
29 | RA | リードアロケートのサポート状態を示します。 0=該当機能がサポートされていません。 1=該当機能がサポートされています。 |
28 | WA | ライトアロケートのサポート状態を示します。 0=該当機能がサポートされていません。 1=該当機能がサポートされています。 |
27:13 | NumSets | 「キャッシュラインのセット数-1」を示します。 0の場合は、1セットとなります。 |
12:3 | Associativity | 「キャッシュのアソシエティビィ-1」を示します。 0の場合は、アソシエティビィは1となります。 |
2:0 | LineSize | (log2(キャッシュラインのワード数))-2を示します。 ライン長が4ワードの場合:log2(4)=2, LineSizeエントリ=0 ライン長が8ワードの場合:log2(8)=2, LineSizeエントリ=1 |
- 命令キャッシュ値を読み出した場合、[31:28]ビットは、0b0010となります。
- データキャッシュ値を読み出した場合、[31:28]ビットは、0b0111となります。
セット/ウェイによるDCISW(データキャッシュの無効化レジスタ)
- セット/ウェイの設定するデータキャッシュラインの無効化を行います。
- 特権モードのみで、書き込みすることができます。
【レジスタへのアクセス命令】
MCR p15,0,<Rd>,c7,c6,2 ; セット/ウェイによるデータキャッシュ無効化の書き込み
【Cortex-A9のレジスタフォーマット】
名前 | 機能 |
---|---|
レベル | 操作対象のキャッシュレベル-1 |
セット | 操作対象のセット番号 |
ウェイ | 操作対象のウェイ番号 |
セット/ウェイによるDCCSW(データキャッシュのクリーニングレジスタ)
- セット/ウェイによるデータキャッシュラインのクリーンを行います。
- 特権モードのみで、書き込みできます。
【レジスタへのアクセス命令】
MCR p15,0,<Rd>,c10,c6,2 ; セット/ウェイによるデータキャッシュのクリーンの書き込み
【Cortex-A9のレジスタフォーマット】
名前 | 機能 |
---|---|
レベル | 操作対象のキャッシュレベル-1 |
セット | 操作対象のセット番号 |
ウェイ | 操作対象のウェイ番号 |
VFP/NEONのアクセス権と稼働設定
リセット時に、VFP/NEONのアクセスは禁止・非稼働状態に初期化されますので、初期化処理の中でアクセス権を設定し、稼働状態に設定することが必要です。
サンプルプログラムでは、コプロセッサ10(CP10)とコプロセッサ11(CP11)を完全アクセス設定を行い、アドバンスドSIMD拡張機能とVFP拡張機能を稼働に設定します。
【サンプルプログラム】
;===================================================================== ; NEON/VFPのアクセス許可 ; CP10/CP11の完全アクセス設定 ;===================================================================== MRC p15,0,r0,c1,c0,2 ; CPACRを読み込み ORR r0,r0,#(0xF << 20) ; CP10/CP11完全アクセス設定 MCR p15,0,r0,c1,c0,2 ; CPACRを書き込み ISB ; 命令同期バリアで再フェッチ ;===================================================================== ; VFPをNEON動作開始 ;===================================================================== MOV r0,#0x40000000 ; VMSR FPEXC,r0 ; 浮動小数点例外レジスタでENビットを書き込み
CPACR(コプロセッサアクセス制御レジスタ)
- コプロセッサCP10とCP11へのアクセス許可設定とアドバンストSIMDの拡張機能とVFPレジスタのレジスタアクセス制限を設定します。
- 特権モードのみで、読み込み/書き込みできます。
【レジスタへのアクセス命令】
MRC p15,0,<Rd>,c1,c0,2 ; CPACR読み込み MCR p15,0,<Rd>,c1,c0,2 ; CPACR書き込み
【レジスタフォーマット】
ビット | 名称 | 内容 |
---|---|---|
31 | ASEDIS | アドバンストSIMD拡張機能の非稼働を設定します。 0=未定義命令になることはありません。 1=「Armアーキテクチャリファレンスマニュアル」で、アドバンストSIMD 拡張機能の一部であるが、VFPv3命令ではないとされているすべての命令エンコードが未定義になります。 |
30 | D32DIS | VFPレジスタのD16~D31の使用を不可能にします。 0=未定義命令になることはありません。 1=レジスタのD16~D31のいずれかにアクセスする場合、「Armアーキテクチャ リファレンスマニュアル」でVFPv3命令とされているすべての命令エンコードが未定義になります。 |
23:22 | cp11 | コプロセッサのアクセス許可を設定します。 0b00=アクセス拒否が発生します(アクセスを行うと未定義例外が発生します)。 0b01=特権アクセスのみ可能です(ユーザモードのアクセスで未定義例外が発生します)。 0b10=予約。 0b11=完全アクセス。 |
21:20 | cp10 | コプロセッサのアクセス許可を設定します。 0b00=アクセス拒否が発生します(アクセスを行うと未定義例外が発生します)。 0b01=特権アクセスのみ可能です(ユーザモードのアクセスで未定義例外が発生します)。 0b10=予約。 0b11=完全アクセス。 |
FPEXC(浮動小数点例外レジスタ)
- FPEXCでは、アドバンスドSIMD拡張機能とVFP拡張機能のグローバルな稼働/非稼働を制御できます。
【レジスタへのアクセス命令】
VMRS { cond } Rd, extsysreg ; NEON/VFPレジスタからArmレジスタの読み込み VMSR { cond } extsysreg , Rd ; ArmレジスタからNEON/VFPレジスタの書き込み
【レジスタフォーマット】
ビット | 名称 | 内容 |
---|---|---|
31 | EX | 例外ビット。アドバンスドSIMDシステムとVPFシステムを記憶するため、どの程度の情報を保存する必要が有るかを示すステータスビットです。 0=D0~D15/D16~D31(実装されている場合)/FPSCR/FPEXC 1=すべてのコンテキストスイッチシステムで処理する必要のある、他の状態が存在します。 |
30 | EN | アドバンスドSIMD拡張機能とVFP拡張機能を稼働/非稼働設定します。 0=アドバンスドSIMD拡張機能とVFP拡張機能が非稼働になります。(リセット時の初期値) 1=アドバンスドSIMD拡張機能とVFP拡張機能が稼働になります。 |
ベクタアドレスの変更設定
VBAR(ベクタベースレジスタ)にアドレスを設定することで、例外ベクタアドレスを変更できます。
SCTLRのVビットが1の場合、VBARによる再マッピングはできません。
【サンプルプログラム】
;=================================================================== ; VBARを使用して、ベクタアドレスを変更 ;=================================================================== LDR r0,=Vectors ; ベクタ先頭アドレスを設定 MCR p15,0,r0,c12,c0,0 ; VBARに書き込み
VBAR
- セキュリティ拡張機能が実装され、上位例外ベクタが選択されていない場合は、ベクタベースアドレスレジスタ(VBAR)によって、モニタモードで処理されない例外の例外ベースドレスが提供されます。
- 上位例外ベクタは常にベースドレスが0xFFFF_0000で、ベクタベースアドレスレジスタの影響は受けません。
- 特権モードのみで、読み込み/書き込みできます。
【レジスタへのアクセス命令】
MRC p15,0,<Rd>,c12,c0,0 ; VBAR読み込み MCR p15,0,<Rd>,c12,c0,0 ; VBAR書き込み
【レジスタフォーマット】
ビット | 名称 | 内容 |
---|---|---|
31:4 | ベクタベースアドレス | 16バイト境界でベクタベースアドレスを設定します。 |
キャッシュ・MMU・分岐予測の稼働設定
SCTLRで、キャッシュとMMU(第12回参照)の稼働状態に設定を行います。MMUを稼働するためには、各種設定を行っていただくことが必要になります。
あわせて読みたい
【サンプルプログラム】
MRC p15,0,r0,c1,c0,0 ; SCTLRを読み込み ORR r0,r0,#(0x1 << 12) ; 命令キッシュを稼働(SCTLR.I [12]) ORR r0,r0,#(0x1 << 2) ; データキッシュを稼働(SCTLR.D [2]) ORR r0,r0,#(0x1 << 11) ; プログラムフロー予測を稼働(SCTLR.Z [11]) ORR r0,r0,#(0x1 << 0) ; MMUを稼働(SCTLR.M [0]) MCR p15,0,r0,c1,c0,0 ; SCTLRを書き込み ;================================================================== ; データプリフェッチ機能を許可します。 ;================================================================== MRC p15,0,r0,c1,c0,1 ; ACTLRを読み込み ORR r0,r0,#(0x1 << 2) ; データプリフェッチを稼働(ACTLR.DP[2]) MCR p15,0,r0,c1,c0,1 ; ACTLRを書き込み
SCTLR
- キャッシュ・MMU等のプロセッサの各種設定を行います。
- 特権モードのみで、読み込み/書き込みできます。
【レジスタへのアクセス命令】
MRC p15,0,<Rd>,c1,c0,0 ; SCTLR読み込み。 MCR p15,0,<Rd>,c1,c0,0 ; SCTLR書き込み。
【レジスタフォーマット】
ビット | 名称 | アクセス | 内容 |
---|---|---|---|
30 | TE | バンク | Thumb例外イネーブル。 |
29 | AFE | バンク | アクセスフラグイネーブルビット。 |
28 | TRE | バンク | MMU内のTEX再マップ機能を制御します。 |
27 | NMFI | 読み出し専用 | マスク不能FIQのサポート。 |
25 | EE | バンク | 例外発生時の意CPSR.Eビットの設定方法を決定します。 0=リトルエンディアンの設定を行います。 1=ビックエンディアンの設定を行います。 |
17 | HA | - | RAZ/WI(読み込み値0または、書き込み無視します。) |
15 | RR | セキュア変更用 | キャッシュ、BTAC、マイクロTLBの置き換え方式を設定します。 0=ランダム置き換え(リセット時の初期値)。 1=ラウンドロビン置き換え(非セキュアでは、読み出し専用です)。 |
13 | V | バンク | 例外ベクタのベースアドレスを選択します。 0=通常の例外ベクタ0x00000000番地。 1=上位例外ベクタ0xFFFF0000番地(リマップ禁止)。 |
12 | I | バンク | 命令キャッシュの動作を設定します。 0=命令キャッシュは非稼働です(リセット時の初期値)。 1=命令キャッシュは稼働です。 |
11 | Z | バンク | プログラムフロー予測を可能にします。 0=プログラムフロー予測が非稼働です(リセット時の初期値)。 1=プログラムフロー予測が稼働です。 |
10 | SW | バンク | SWP/SWPB許可ビット 0=SWPおよびSWPBは未定義です(リセット時の初期値)。 1=SWPおよびSWPBは正常に動作します。 |
2 | C | バンク | データキャッシュの動作設定を行います。 0=データキャッシュは非稼働です(リセット時の初期値)。 1=データキャッシュは稼働です。 |
1 | A | バンク | 非整列データのアクセスアライメントフォールトの検出を行います。 0=アライメントフォールトチェック禁止(リセット時の初期値)。 1=ライメントフォールトチェック許可。 |
0 | M | バンク | MMUを稼働します。 0=MMUが非稼働です(リセット時の初期値)。 1=MMUが稼働です。 |
ACTLR
- 特権モードのみで、読み込み/書き込みできます。
【レジスタへのアクセス命令】
MRC p15,0,<Rd>,c1,c0,1 ; ACTLR読み込み MCR p15,0,<Rd>,c1,c0,1 ; ACTLR書き込み
【レジスタフォーマット】
ビット | 名称 | 内容 |
---|---|---|
9 | パリティ | パリティチェックのサポート(実装されている場合) 0=非稼働です(リセット時の初期値)。 1=稼働しています。 |
8 | 1ウェイでの割り当て | 1キャッシュウェイの割り当てを可能にします。 0=禁止です(リセット時の初期値)。 |
7 | EXCL | 排他キャッシュビット 0=非稼働です(リセット時の初期値)。 1=稼働しています。 |
6 | SMP | Cortex-A9プロセッサがコヒーレンシの一部かどうか示します。 |
3 | 0のフルライン書き込み | 0のフルライン書き込みモードを可能にします。 リセット時は、0です。 |
2 | L1プリフェッチイネーブル | データサイドのプリフェッチ設定 0=非稼働です(リセット時の初期値)。 1=稼働しています。 |
1 | L2プリフェッチヒントイネーブル | プリフェッチヒントイネーブル設定。 リセット時は、0です。 |
0 | FW | キャッシュおよびTLB保守のブロードキャスト。 0=非稼働です(リセット時の初期値)。 1=稼働しています。 |
今回は、初期化をする時に設定が必要なコプロセッサを中心に解説しました。普通にプログラミングしていると、アクセスすることは少ないと思いますが(笑)、例外が発生した時に問題解決に役立つレジスタもありますので、マニュアルを読んでおくことをお勧めします。
こちらも是非
“もっと見る” Cortex-A編
初期化処理
リセット例外からmain()関数を呼び出すまでの初期化は、ユーザが作成する部分とArmコンパイラが実行する部分に分けることができます。コードのコピーや初期化変数/未初期化変数の初期化は、リンカのメモリ配置設定を処理系ライブラリが実行します。
PMU(パフォーマンス監視ユニット)
PMUに関連するレジスタは、ユーザモードでのアクセスは禁止されていますので、PMUSERENR(ユーザイネーブルレジスタ)を特権モードでユーザモードアクセス許可を設定します。PMUSERENRについては、 後述の該当項目を参照ください。
TrustZone(セキュリティ拡張機能)
TrustZoneはCortex-Aシリーズの拡張機能で、大規模OSやアプリケーションが動作するノーマルワールドとセキュリティ関連が動作するセキュアワールドを導入しています。TrustZoneでは、ノーマルワールドメモリ空間とセキュアワールドメモリ空間の分離が可能です。