Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 14767] ファイルの概要

このコミットは、GoランタイムにおけるFreeBSD/ARMアーキテクチャでの命令キャッシュフラッシュの不具合を修正するものです。具体的には、sysarchシステムコールが引数をレジスタではなくスタックで渡すことを要求するというFreeBSD/ARMの特性に対応し、runtime·cacheflush関数が正しく動作するように修正しています。

コミット

commit c2d2bfcc4908ca7ab94abf5479f28694b2d1efa8
Author: Dave Cheney <dave@cheney.net>
Date:   Tue Jan 1 21:47:42 2013 +1100

    runtime: fix freebsd/arm instruction cache flush
    
    sysarch requires arguments to be passed on the stack, not in registers.
    
    Credit to Shenghou Ma (minux) for the fix.
    
    R=minux.ma, devon.odell
    CC=golang-dev
    https://golang.org/cl/7037043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/c2d2bfcc4908ca7ab94abf5479f28694b2d1efa8

元コミット内容

runtime: fix freebsd/arm instruction cache flush

sysarch requires arguments to be passed on the stack, not in registers.

Credit to Shenghou Ma (minux) for the fix.

R=minux.ma, devon.odell
CC=golang-dev
https://golang.org/cl/7037043

変更の背景

このコミットの背景には、FreeBSDオペレーティングシステムがARMアーキテクチャ上で提供するsysarchシステムコールの引数渡し規約に関する問題がありました。Goランタイムのcacheflush関数は、命令キャッシュをフラッシュするためにsysarchシステムコールを利用していました。しかし、FreeBSD/ARM環境では、sysarchシステムコールが引数をレジスタではなくスタック経由で受け取るという特定の規約を持っていました。

元の実装では、cacheflush関数が引数(キャッシュフラッシュの開始アドレスと終了アドレス)をARMのレジスタ(R1とR2)にロードしてsysarchを呼び出していました。このレジスタ渡しのアプローチは、FreeBSD/ARMのsysarchの期待する引数渡し規約と一致せず、結果として命令キャッシュが正しくフラッシュされないというバグを引き起こしていました。命令キャッシュの不適切なフラッシュは、特にJITコンパイルされたコードや動的に生成されたコードを実行する際に、古い命令が実行されてしまうなどの深刻な問題につながる可能性があります。

この問題は、Shenghou Ma (minux) によって特定され、修正が提案されました。このコミットは、その修正をGoランタイムに適用するものです。

前提知識の解説

ARMアーキテクチャにおけるレジスタとスタック

ARMプロセッサは、汎用レジスタ(R0-R15など)と特殊レジスタ(プログラムカウンタPC、スタックポインタSPなど)を持ちます。関数呼び出し規約(Calling Convention)は、関数間で引数をどのように渡し、戻り値をどのように返すかを定義します。一般的なARMのABI(Application Binary Interface)では、少数の引数はレジスタ(通常R0-R3)で渡され、それ以上の引数や複雑な構造体などはスタックにプッシュして渡されます。

システムコール (System Call)

システムコールは、ユーザー空間のプログラムがオペレーティングシステム(カーネル)のサービスを要求するためのメカニズムです。ファイルI/O、メモリ管理、プロセス制御など、特権的な操作を行うために使用されます。システムコールを呼び出す際には、引数をカーネルに渡す必要がありますが、その渡し方はOSやアーキテクチャによって異なります。

sysarchシステムコール

sysarchは、特定のアーキテクチャ固有の操作を行うための汎用システムコールです。FreeBSDでは、sysarchは様々なアーキテクチャ固有の機能を提供するために使用されます。例えば、CPUのキャッシュ制御、FPU(浮動小数点演算ユニット)の状態管理、デバッグ関連の操作などが含まれます。sysarchの具体的な動作は、渡されるコマンド引数によって決定されます。

命令キャッシュ (Instruction Cache)

現代のCPUは、メインメモリへのアクセス速度が遅いため、高速なキャッシュメモリを利用します。命令キャッシュは、CPUが次に実行する可能性のある命令のコピーを保持し、メモリからの命令フェッチを高速化します。

キャッシュフラッシュ (Cache Flush)

キャッシュフラッシュは、キャッシュメモリの内容を無効化したり、メインメモリに書き戻したりする操作です。命令キャッシュの場合、プログラムが実行中に新しいコードを動的に生成したり、既存のコードを書き換えたりした場合(例えば、JITコンパイラやデバッガがこれを行います)、キャッシュ内の古い命令が実行されないように、命令キャッシュをフラッシュして最新の命令をメモリから再ロードさせる必要があります。キャッシュがフラッシュされないと、CPUは古い(無効な)命令を実行し続け、プログラムの誤動作やクラッシュにつながる可能性があります。

技術的詳細

このコミットの技術的詳細の中心は、FreeBSD/ARMにおけるsysarchシステムコールの引数渡し規約への対応です。

ARMアーキテクチャでは、通常、関数呼び出しの最初の数個の引数はレジスタ(R0, R1, R2, R3)で渡されます。しかし、FreeBSDのsysarchシステムコールは、その実装において、引数をレジスタではなくスタックから読み取るように設計されていました。これは、システムコールハンドラが引数を処理する際に、特定のスタックフレームレイアウトを期待しているためと考えられます。

元のruntime·cacheflush関数は、命令キャッシュフラッシュに必要な開始アドレスと終了アドレスをそれぞれR1とR2レジスタにロードし、その後SWI $165sysarchシステムコールを呼び出すためのソフトウェア割り込み命令)を実行していました。

TEXT runtime·cacheflush(SB),7,$0
    MOVW $0, R0 // icacheflush
    MOVW 0(FP), R1 // start
    MOVW 4(FP), R2 // end
    SUB R1, R2 // R2 = length
    SWI $165 // sysarch
    RET

このコードでは、sysarchのコマンド(icacheflushを示す0)がR0に、開始アドレスがR1に、長さがR2に設定されています。しかし、FreeBSD/ARMのsysarchはこれらの値をスタックから期待するため、レジスタに設定された値は無視され、結果としてキャッシュフラッシュが正しく行われませんでした。

このコミットによる修正は、以下のステップでこの問題を解決します。

  1. スタックフレームの拡張: TEXT runtime·cacheflush(SB),7,$0TEXT runtime·cacheflush(SB),7,$8 に変更されています。これは、この関数のスタックフレームサイズを8バイト(2ワード)拡張することを意味します。この追加のスペースは、sysarchに渡す引数をスタックに配置するために使用されます。
  2. drain_writebufの追加:
    MOVW $1, R0 // drain_writebuf
    SWI $165 // sysarch
    
    この2行が追加されています。$1をR0にロードしてsysarchを呼び出すことで、drain_writebuf(ライトバッファのドレイン)操作を実行しています。これは、命令キャッシュをフラッシュする前に、CPUのライトバッファに保留されている書き込み操作を完了させるために重要です。これにより、メモリ上のコードが最新の状態であることを保証し、キャッシュフラッシュがその最新の状態に対して行われるようにします。
  3. 引数のスタックへの配置:
    MOVW 0(FP), R1 // start
    MOVW R1, 4(R13) // startをスタックにプッシュ (R13はスタックポインタ)
    MOVW 4(FP), R2 // end
    SUB R1, R2 // R2 = length
    MOVW R2, 8(R13) // lengthをスタックにプッシュ
    MOVW $4(R13), R1 // スタック上の引数へのポインタをR1に設定
    
    元のコードではstartendがレジスタR1とR2に直接ロードされていましたが、修正後では、これらの値はまず0(FP)4(FP)から読み込まれ、その後4(R13)8(R13)というスタック上のオフセットに書き込まれます。R13は通常、スタックポインタ(SP)として使用されます。これにより、startlengthがスタックに配置されます。 さらに、MOVW $4(R13), R1という命令で、スタックに配置された引数の先頭アドレス(4(R13))をR1レジスタにロードしています。これは、sysarchシステムコールが、引数へのポインタをレジスタで受け取ることを期待している場合があるためです。つまり、引数自体はスタックにあり、そのスタック上の場所へのポインタがレジスタで渡されるという二段階の渡し方をしている可能性があります。
  4. sysarchの再呼び出し: 最後に、SWI $165が再度呼び出され、今度はスタックに正しく配置された引数と、R1に設定された引数へのポインタを使用して、命令キャッシュフラッシュが実行されます。

この修正により、GoランタイムはFreeBSD/ARM環境で命令キャッシュを確実にフラッシュできるようになり、動的に生成されるコードの正確な実行が保証されます。

コアとなるコードの変更箇所

変更はsrc/pkg/runtime/sys_freebsd_arm.sファイルに集中しています。

--- a/src/pkg/runtime/sys_freebsd_arm.s
+++ b/src/pkg/runtime/sys_freebsd_arm.s
@@ -244,11 +244,16 @@ TEXT runtime·sigprocmask(SB),7,$0
 	MOVW.CS R9, (R9)
 	RET
 
-TEXT runtime·cacheflush(SB),7,$0
+TEXT runtime·cacheflush(SB),7,$8
+\tMOVW $1, R0 // drain_writebuf
+\tSWI $165 // sysarch
 	MOVW $0, R0 // icacheflush
 	MOVW 0(FP), R1 // start
+\tMOVW R1, 4(R13)
 	MOVW 4(FP), R2 // end
 	SUB R1, R2 // R2 = length
+\tMOVW R2, 8(R13)
+\tMOVW $4(R13), R1
 	SWI $165 // sysarch
 	RET

コアとなるコードの解説

TEXT runtime·cacheflush(SB),7,$8

  • TEXT runtime·cacheflush(SB): runtimeパッケージのcacheflush関数を定義しています。SBはStatic Baseで、グローバルシンボルであることを示します。
  • ,7: この関数の引数と戻り値の合計サイズが7バイトであることを示します。これはGoのアセンブリ規約の一部です。
  • $8: この関数のスタックフレームサイズが8バイトであることを示します。元の$0から$8に変更されたことで、関数内でローカル変数や引数をスタックに保存するための領域が確保されました。この8バイトは、startlengthの2つのワード(各4バイト)をスタックに格納するために使用されます。

MOVW $1, R0 // drain_writebuf

SWI $165 // sysarch

  • MOVW $1, R0: 即値1をレジスタR0に移動します。R0は通常、システムコールの第一引数またはコマンドコードとして使用されます。この1は、sysarchシステムコールに対して「ライトバッファをドレインする」というコマンドを意味します。
  • SWI $165: ソフトウェア割り込み命令です。$165はFreeBSDにおけるsysarchシステムコールの番号です。この命令により、カーネルのsysarchハンドラが呼び出され、ライトバッファのドレイン処理が実行されます。これは、命令キャッシュをフラッシュする前に、メモリ上のコードが完全に書き込まれていることを保証するために重要です。

MOVW $0, R0 // icacheflush

  • MOVW $0, R0: 即値0をレジスタR0に移動します。これは、次に呼び出すsysarchシステムコールに対して「命令キャッシュをフラッシュする」というコマンドを意味します。

MOVW 0(FP), R1 // start

MOVW R1, 4(R13)

  • MOVW 0(FP), R1: フレームポインタFPからのオフセット0にある値(cacheflush関数の第一引数であるstartアドレス)をレジスタR1にロードします。
  • MOVW R1, 4(R13): レジスタR1の値(startアドレス)を、スタックポインタR13からのオフセット4のメモリ位置にストアします。これにより、startアドレスがスタックにプッシュされます。

MOVW 4(FP), R2 // end

SUB R1, R2 // R2 = length

MOVW R2, 8(R13)

  • MOVW 4(FP), R2: フレームポインタFPからのオフセット4にある値(cacheflush関数の第二引数であるendアドレス)をレジスタR2にロードします。
  • SUB R1, R2: レジスタR2からレジスタR1の値を減算し、結果をR2に格納します。これにより、R2にはキャッシュフラッシュの対象となる領域の長さ(end - start)が計算されます。
  • MOVW R2, 8(R13): レジスタR2の値(計算された長さ)を、スタックポインタR13からのオフセット8のメモリ位置にストアします。これにより、lengthがスタックにプッシュされます。

MOVW $4(R13), R1

  • MOVW $4(R13), R1: スタックポインタR13からのオフセット4のメモリアドレス(つまり、スタックにプッシュされたstartアドレスの場所)をレジスタR1にロードします。これは、sysarchシステムコールが、引数自体ではなく、スタック上の引数へのポインタをレジスタで受け取ることを期待しているためです。

SWI $165 // sysarch

RET

  • SWI $165: 再びsysarchシステムコールを呼び出します。今回は、R0にはicacheflushコマンド(0)が、R1にはスタック上の引数へのポインタが設定されており、sysarchが期待する規約に従って引数が渡されます。
  • RET: 関数から戻ります。

この一連の変更により、FreeBSD/ARM環境でのsysarchシステムコールへの引数渡しが正しく行われるようになり、命令キャッシュフラッシュの機能が正常に動作するようになりました。

関連リンク

参考にした情報源リンク

このコミットは、GoランタイムにおけるFreeBSD/ARMアーキテクチャでの命令キャッシュフラッシュの不具合を修正するものです。具体的には、sysarchシステムコールが引数をレジスタではなくスタックで渡すことを要求するというFreeBSD/ARMの特性に対応し、runtime·cacheflush関数が正しく動作するように修正しています。

コミット

commit c2d2bfcc4908ca7ab94abf5479f28694b2d1efa8
Author: Dave Cheney <dave@cheney.net>
Date:   Tue Jan 1 21:47:42 2013 +1100

    runtime: fix freebsd/arm instruction cache flush
    
    sysarch requires arguments to be passed on the stack, not in registers.
    
    Credit to Shenghou Ma (minux) for the fix.
    
    R=minux.ma, devon.odell
    CC=golang-dev
    https://golang.org/cl/7037043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/c2d2bfcc4908ca7ab94abf5479f28694b2d1efa8

元コミット内容

runtime: fix freebsd/arm instruction cache flush

sysarch requires arguments to be passed on the stack, not in registers.

Credit to Shenghou Ma (minux) for the fix.

R=minux.ma, devon.odell
CC=golang-dev
https://golang.org/cl/7037043

変更の背景

このコミットの背景には、FreeBSDオペレーティングシステムがARMアーキテクチャ上で提供するsysarchシステムコールの引数渡し規約に関する問題がありました。Goランタイムのcacheflush関数は、命令キャッシュをフラッシュするためにsysarchシステムコールを利用していました。しかし、FreeBSD/ARM環境では、sysarchシステムコールが引数をレジスタではなくスタック経由で受け取るという特定の規約を持っていました。

元の実装では、cacheflush関数が引数(キャッシュフラッシュの開始アドレスと終了アドレス)をARMのレジスタ(R1とR2)にロードしてsysarchを呼び出していました。このレジスタ渡しのアプローチは、FreeBSD/ARMのsysarchの期待する引数渡し規約と一致せず、結果として命令キャッシュが正しくフラッシュされないというバグを引き起こしていました。命令キャッシュの不適切なフラッシュは、特にJITコンパイルされたコードや動的に生成されたコードを実行する際に、古い命令が実行されてしまうなどの深刻な問題につながる可能性があります。

この問題は、Shenghou Ma (minux) によって特定され、修正が提案されました。このコミットは、その修正をGoランタイムに適用するものです。

前提知識の解説

ARMアーキテクチャにおけるレジスタとスタック

ARMプロセッサは、汎用レジスタ(R0-R15など)と特殊レジスタ(プログラムカウンタPC、スタックポインタSPなど)を持ちます。関数呼び出し規約(Calling Convention)は、関数間で引数をどのように渡し、戻り値をどのように返すかを定義します。一般的なARMのABI(Application Binary Interface)では、少数の引数はレジスタ(通常R0-R3)で渡され、それ以上の引数や複雑な構造体などはスタックにプッシュして渡されます。

システムコール (System Call)

システムコールは、ユーザー空間のプログラムがオペレーティングシステム(カーネル)のサービスを要求するためのメカニズムです。ファイルI/O、メモリ管理、プロセス制御など、特権的な操作を行うために使用されます。システムコールを呼び出す際には、引数をカーネルに渡す必要がありますが、その渡し方はOSやアーキテクチャによって異なります。

sysarchシステムコール

sysarchは、特定のアーキテクチャ固有の操作を行うための汎用システムコールです。FreeBSDでは、sysarchは様々なアーキテクチャ固有の機能を提供するために使用されます。例えば、CPUのキャッシュ制御、FPU(浮動小数点演算ユニット)の状態管理、デバッグ関連の操作などが含まれます。sysarchの具体的な動作は、渡されるコマンド引数によって決定されます。

命令キャッシュ (Instruction Cache)

現代のCPUは、メインメモリへのアクセス速度が遅いため、高速なキャッシュメモリを利用します。命令キャッシュは、CPUが次に実行する可能性のある命令のコピーを保持し、メモリからの命令フェッチを高速化します。

キャッシュフラッシュ (Cache Flush)

キャッシュフラッシュは、キャッシュメモリの内容を無効化したり、メインメモリに書き戻したりする操作です。命令キャッシュの場合、プログラムが実行中に新しいコードを動的に生成したり、既存のコードを書き換えたりした場合(例えば、JITコンパイラやデバッガがこれを行います)、キャッシュ内の古い命令が実行されないように、命令キャッシュをフラッシュして最新の命令をメモリから再ロードさせる必要があります。キャッシュがフラッシュされないと、CPUは古い(無効な)命令を実行し続け、プログラムの誤動作やクラッシュにつながる可能性があります。

技術的詳細

このコミットの技術的詳細の中心は、FreeBSD/ARMにおけるsysarchシステムコールの引数渡し規約への対応です。

ARMアーキテクチャでは、通常、関数呼び出しの最初の数個の引数はレジスタ(R0, R1, R2, R3)で渡されます。しかし、FreeBSDのsysarchシステムコールは、その実装において、引数をレジスタではなくスタックから読み取るように設計されていました。これは、システムコールハンドラが引数を処理する際に、特定のスタックフレームレイアウトを期待しているためと考えられます。

元のruntime·cacheflush関数は、命令キャッシュフラッシュに必要な開始アドレスと終了アドレスをそれぞれR1とR2レジスタにロードし、その後SWI $165sysarchシステムコールを呼び出すためのソフトウェア割り込み命令)を実行していました。

TEXT runtime·cacheflush(SB),7,$0
    MOVW $0, R0 // icacheflush
    MOVW 0(FP), R1 // start
    MOVW 4(FP), R2 // end
    SUB R1, R2 // R2 = length
    SWI $165 // sysarch
    RET

このコードでは、sysarchのコマンド(icacheflushを示す0)がR0に、開始アドレスがR1に、長さがR2に設定されています。しかし、FreeBSD/ARMのsysarchはこれらの値をスタックから期待するため、レジスタに設定された値は無視され、結果としてキャッシュフラッシュが正しく行われませんでした。

このコミットによる修正は、以下のステップでこの問題を解決します。

  1. スタックフレームの拡張: TEXT runtime·cacheflush(SB),7,$0TEXT runtime·cacheflush(SB),7,$8 に変更されています。これは、この関数のスタックフレームサイズを8バイト(2ワード)拡張することを意味します。この追加のスペースは、sysarchに渡す引数をスタックに配置するために使用されます。
  2. drain_writebufの追加:
    MOVW $1, R0 // drain_writebuf
    SWI $165 // sysarch
    
    この2行が追加されています。$1をR0にロードしてsysarchを呼び出すことで、drain_writebuf(ライトバッファのドレイン)操作を実行しています。これは、命令キャッシュをフラッシュする前に、CPUのライトバッファに保留されている書き込み操作を完了させるために重要です。これにより、メモリ上のコードが最新の状態であることを保証し、キャッシュフラッシュがその最新の状態に対して行われるようにします。
  3. 引数のスタックへの配置:
    MOVW 0(FP), R1 // start
    MOVW R1, 4(R13) // startをスタックにプッシュ (R13はスタックポインタ)
    MOVW 4(FP), R2 // end
    SUB R1, R2 // R2 = length
    MOVW R2, 8(R13) // lengthをスタックにプッシュ
    MOVW $4(R13), R1 // スタック上の引数へのポインタをR1に設定
    
    元のコードではstartendがレジスタR1とR2に直接ロードされていましたが、修正後では、これらの値はまず0(FP)4(FP)から読み込まれ、その後4(R13)8(R13)というスタック上のオフセットに書き込まれます。R13は通常、スタックポインタ(SP)として使用されます。これにより、startlengthがスタックにプッシュされます。 さらに、MOVW $4(R13), R1という命令で、スタックに配置された引数の先頭アドレス(4(R13))をR1レジスタにロードしています。これは、sysarchシステムコールが、引数へのポインタをレジスタで受け取ることを期待している場合があるためです。つまり、引数自体はスタックにあり、そのスタック上の場所へのポインタがレジスタで渡されるという二段階の渡し方をしている可能性があります。
  4. sysarchの再呼び出し: 最後に、SWI $165が再度呼び出され、今度はスタックに正しく配置された引数と、R1に設定された引数へのポインタを使用して、命令キャッシュフラッシュが実行されます。

この修正により、GoランタイムはFreeBSD/ARM環境で命令キャッシュを確実にフラッシュできるようになり、動的に生成されるコードの正確な実行が保証されます。

コアとなるコードの変更箇所

変更はsrc/pkg/runtime/sys_freebsd_arm.sファイルに集中しています。

--- a/src/pkg/runtime/sys_freebsd_arm.s
+++ b/src/pkg/runtime/sys_freebsd_arm.s
@@ -244,11 +244,16 @@ TEXT runtime·sigprocmask(SB),7,$0
 	MOVW.CS R9, (R9)
 	RET
 
-TEXT runtime·cacheflush(SB),7,$0
+TEXT runtime·cacheflush(SB),7,$8
+\tMOVW $1, R0 // drain_writebuf
+\tSWI $165 // sysarch
 	MOVW $0, R0 // icacheflush
 	MOVW 0(FP), R1 // start
+\tMOVW R1, 4(R13)
 	MOVW 4(FP), R2 // end
 	SUB R1, R2 // R2 = length
+\tMOVW R2, 8(R13)
+\tMOVW $4(R13), R1
 	SWI $165 // sysarch
 	RET

コアとなるコードの解説

TEXT runtime·cacheflush(SB),7,$8

  • TEXT runtime·cacheflush(SB): runtimeパッケージのcacheflush関数を定義しています。SBはStatic Baseで、グローバルシンボルであることを示します。
  • ,7: この関数の引数と戻り値の合計サイズが7バイトであることを示します。これはGoのアセンブリ規約の一部です。
  • $8: この関数のスタックフレームサイズが8バイトであることを示します。元の$0から$8に変更されたことで、関数内でローカル変数や引数をスタックに保存するための領域が確保されました。この8バイトは、startlengthの2つのワード(各4バイト)をスタックに格納するために使用されます。

MOVW $1, R0 // drain_writebuf

SWI $165 // sysarch

  • MOVW $1, R0: 即値1をレジスタR0に移動します。R0は通常、システムコールの第一引数またはコマンドコードとして使用されます。この1は、sysarchシステムコールに対して「ライトバッファをドレインする」というコマンドを意味します。
  • SWI $165: ソフトウェア割り込み命令です。$165はFreeBSDにおけるsysarchシステムコールの番号です。この命令により、カーネルのsysarchハンドラが呼び出され、ライトバッファのドレイン処理が実行されます。これは、命令キャッシュをフラッシュする前に、メモリ上のコードが完全に書き込まれていることを保証するために重要です。

MOVW $0, R0 // icacheflush

  • MOVW $0, R0: 即値0をレジスタR0に移動します。これは、次に呼び出すsysarchシステムコールに対して「命令キャッシュをフラッシュする」というコマンドを意味します。

MOVW 0(FP), R1 // start

MOVW R1, 4(R13)

  • MOVW 0(FP), R1: フレームポインタFPからのオフセット0にある値(cacheflush関数の第一引数であるstartアドレス)をレジスタR1にロードします。
  • MOVW R1, 4(R13): レジスタR1の値(startアドレス)を、スタックポインタR13からのオフセット4のメモリ位置にストアします。これにより、startアドレスがスタックにプッシュされます。

MOVW 4(FP), R2 // end

SUB R1, R2 // R2 = length

MOVW R2, 8(R13)

  • MOVW 4(FP), R2: フレームポインタFPからのオフセット4にある値(cacheflush関数の第二引数であるendアドレス)をレジスタR2にロードします。
  • SUB R1, R2: レジスタR2からレジスタR1の値を減算し、結果をR2に格納します。これにより、R2にはキャッシュフラッシュの対象となる領域の長さ(end - start)が計算されます。
  • MOVW R2, 8(R13): レジスタR2の値(計算された長さ)を、スタックポインタR13からのオフセット8のメモリ位置にストアします。これにより、lengthがスタックにプッシュされます。

MOVW $4(R13), R1

  • MOVW $4(R13), R1: スタックポインタR13からのオフセット4のメモリアドレス(つまり、スタックにプッシュされたstartアドレスの場所)をレジスタR1にロードします。これは、sysarchシステムコールが、引数自体ではなく、スタック上の引数へのポインタをレジスタで受け取ることを期待しているためです。

SWI $165 // sysarch

RET

  • SWI $165: 再びsysarchシステムコールを呼び出します。今回は、R0にはicacheflushコマンド(0)が、R1にはスタック上の引数へのポインタが設定されており、sysarchが期待する規約に従って引数が渡されます。
  • RET: 関数から戻ります。

この一連の変更により、FreeBSD/ARM環境でのsysarchシステムコールへの引数渡しが正しく行われるようになり、命令キャッシュフラッシュの機能が正常に動作するようになりました。

関連リンク

参考にした情報源リンク