Kernel mode NEON

もともと、Linux Kernelのソースコードの一部なので、GPLv2扱いになる（はずの認識）。

> https://www.kernel.org/doc/html/latest/index.html
> 
> Licensing documentation
> 
> The following describes the license of the Linux kernel source code (GPLv2), how to properly mark the license of individual files in the source tree, as well as links to the full license text.
> 
> https://www.kernel.org/doc/html/latest/process/license-rules.html#kernel-licensing

# Kernel mode NEON

# TL;DR summary

> * Use only NEON instructions, or VFP instructions that don’t rely on support code
* Isolate your NEON code in a separate compilation unit, and compile it with ‘-march=armv7-a -mfpu=neon -mfloat-abi=softfp’
* Put kernel_neon_begin() and kernel_neon_end() calls around the calls into your NEON code
* Don’t sleep in your NEON code, and be aware that it will be executed with preemption disabled

* NEON命令、またはサポートコードに依存しないVFP命令だけを利用しなさい。
* NEONコードは、コンパイル単位から独立させて、`-march=armv7-a -mfpu=neon -mfloat-abi=softfp`を付けてコンパイルしなさい。
* NEON codeを呼び出す前後で、kernel_neon_begin()とkernel_neon_end()を呼び出しなさい。
* NEON code内でスリープに入ってはいけない。プリエンプションを無効化しておいてください。

# Introduction

> It is possible to use NEON instructions (and in some cases, VFP instructions) in code that runs in kernel mode. 

kernel mode内で動作するコードの中でも、NEON命令（また場合によってはVFP命令）を利用することができます。

> However, for performance reasons, the NEON/VFP register file is not preserved and restored at every context switch or taken exception like the normal register file is, so some manual intervention is required. 

しかし、パフォーマンス上の理由から、NEON/VFP register fileは、全てのコンテクストスイッチごとに保存および復元をされず、通常のレジスタファイルのように例外が発生するため、マニュアルでの介入が必要になります。

> Furthermore, special care is required for code that may sleep [i.e., may call schedule()], as NEON or VFP instructions will be executed in a non-preemptible section for reasons outlined below.

さらに、スリープに入る可能性のあるコードに対して（例えば、schedule()を呼び出す）、NEON や VFP命令は、下記理由からプリエンション不可能な中で使われように、特別な注意が必要になります。

# Lazy preserve and restore

> The NEON/VFP register file is managed using lazy preserve (on UP systems) and lazy restore (on both SMP and UP systems).

NEON/VFP register fileは、遅延保存(UPシステムの場合）および、遅延復元（SMPとUPシステムの両方）で管理されます。

> This means that the register file is kept ‘live’, and is only preserved and restored when multiple tasks are contending for the NEON/VFP unit (or, in the SMP case, when a task migrates to another core). 

これは、register fileは`live`が保持され、複数のタスクでNEON/VFP unitが競合している場合（あるいは、SMPの場合で、タスクが別のコアに移行する場合）にだけ、保存と復元が行われます。

> Lazy restore is implemented by disabling the NEON/VFP unit after every context switch, resulting in a trap when subsequently a NEON/VFP instruction is issued, allowing the kernel to step in and perform the restore if necessary.

遅延復元は、コンテクストスイッチ毎に、NEON/VFPユニットが無効されることで実現されます。その後に、NEON/VFP命令によってトラップが発生し、必要に応じて復元が実行されます。
.

> Any use of the NEON/VFP unit in kernel mode should not interfere with this, so it is required to do an ‘eager’ preserve of the NEON/VFP register file, and enable the NEON/VFP unit explicitly so no exceptions are generated on first subsequent use. 

カーネルモードにおけるNEON/VFP unitの利用は、これに干渉しないはずなので、NEON/VFP register fileを積極的に保持し、NEON/VFP unitを明示的に有効にして、最初の継続利用後において例外が発生しないようにする必要があります。

> This is handled by the function kernel_neon_begin(), which should be called before any kernel mode NEON or VFP instructions are issued. 

これは、`kernel_neon_begin()`によって処理されます。カーネルモードのNEON/VFP命令が発行される目に、呼び出す必要があります。

> Likewise, the NEON/VFP unit should be disabled again after use to make sure user mode will hit the lazy restore trap upon next use. This is handled by the function kernel_neon_end().

同様に、NEON/VFP unitを使用後に再び無効化し、ユーザーモードで次回の使用時に遅延復元trapにヒットさせる必要があります。これは関数 `kernel_neon_end()`によって処理されます。

# Interruptions in kernel mode

> For reasons of performance and simplicity, it was decided that there shall be no preserve/restore mechanism for the kernel mode NEON/VFP register contents. 

パフォーマンスと単純化の理由から、NEON/VFP register contentsのカーネルモードでの保存/復元メカニズムは存在しないように決定された。

> This implies that interruptions of a kernel mode NEON section can only be allowed if they are guaranteed not to touch the NEON/VFP registers. 

これは、カーネルモードにおける割り込みセクションで、それがNEON/VFP registerに関与しないことが保証された場合にのみ許可されることを意味します。

> For this reason, the following rules and restrictions apply in the kernel: 

この理由から、カーネルにおいては下記のルーツと原則が適用されます。

> * NEON/VFP code is not allowed in interrupt context; 
> * NEON/VFP code is not allowed to sleep; 
> * NEON/VFP code is executed with preemption disabled.

* NEON/VFP コードは、割り込みコンテクスト内では使用しない。
* NEON/VFP コードはスリープを許可しない。
* NEON/VFP コードはプリエンプション無効化時に実行される。

.

> If latency is a concern, it is possible to put back to back calls to kernel_neon_end() and kernel_neon_begin() in places in your code where none of the NEON registers are live. 

遅延が問題になる場合、NEONレジスタが存在しないコード内の場所で、kernel_neon_end()とkernel_neon_begin()を連続して呼び出すことができます。

> (Additional calls to kernel_neon_begin() should be reasonably cheap if no context switch occurred in the meantime)

(kernel_neon_begin()の追加呼び出しは、その間にコンテクストスイッチが行われなかった場合には、非常に低コストになることでしょう）

# VFP and support code

> Earlier versions of VFP (prior to version 3) rely on software support for things like IEEE-754 compliant underflow handling etc. 

従来バージョンのVFP(バージョン3以前）では、IEEE-754準拠のアンダーフロー処理などのソフトウェア実装に依存をしていました。

> When the VFP unit needs such software assistance, it signals the kernel by raising an undefined instruction exception. 

VFP unitがソフトウェアでの支援を必要としていた時、kernelに未定義な命令に対する例外として通知がされます。

> The kernel responds by inspecting the VFP control registers and the current instruction and arguments, and emulates the instruction in software.

カーネルは、VFP制御レジスタと現在の命令、引数を勘案し、ソフトウェア命令をエミュレーションします。

.

Such software assistance is currently not implemented for VFP instructions executed in kernel mode. If such a condition is encountered, the kernel will fail and generate an OOPS.

そのようなソフトウェア支援は、カーネルモードでのVFP命令実行が実装されていません。そのような状況に陥った場合、カーネルは失敗し、OOPSを発行します。

# Separating NEON code from ordinary code

> The compiler is not aware of the special significance of kernel_neon_begin() and kernel_neon_end(), i.e., that it is only allowed to issue NEON/VFP instructions between calls to these respective functions. 

コンパイラは、kernel_neon_begin()とkernel_neon_end()の特別な識別子に基づいて特殊なことは行いません。これらの関連関数の呼び出す間でだけ、NEON/VFP命令を発酵する事が許可されます。

> Furthermore, GCC may generate NEON instructions of its own at -O3 level if -mfpu=neon is selected, and even if the kernel is currently compiled at -O2, future changes may result in NEON/VFP instructions appearing in unexpected places if no special care is taken.

>さらに、-mfpu = neonが選択されている場合、GCCは独自のNEON命令を-O3レベルで生成する可能性があります。特別な注意が払われていなければ、カーネルが現在-O2でコンパイルされている場合でも、将来の変更によりNEON / VFP命令が予期しない場所に出現する可能性があります。 

.

> Therefore, the recommended and only supported way of using NEON/VFP in the kernel is by adhering to the following rules:

したがって、カーネルでNEON/VFPを使用する場合の推奨される唯一のサポートされている手順は、以下の通りとなります。

> * isolate the NEON code in a separate compilation unit and compile it with ‘-march=armv7-a -mfpu=neon -mfloat-abi=softfp’;
* issue the calls to kernel_neon_begin(), kernel_neon_end() as well as the calls into the unit containing the NEON code from a compilation unit which is not built with the GCC flag ‘-mfpu=neon’ set.


* NEONコードを別のコンパイル単位に分離し、「-march = armv7-a -mfpu = neon -mfloat-abi = softfp」を使用してコンパイルする。
* kernel_neon_begin()とkernel_neon_end()が呼び出し、および、コンパイル単位からのNEONコードを含むユニットへの呼び出しを行う。これには、GCC flag ‘-mfpu=neon’ を設定されてビルドされていません。

> As the kernel is compiled with ‘-msoft-float’, the above will guarantee that both NEON and VFP instructions will only ever appear in designated compilation units at any optimization level.

カーネルは`msoft-float`を使用してコンパイルされるため、上記により、NEON命令とVFP命令の両方が、最適化レベルで指定されたコンパイル単位にのみ出現するようになりまsう。

# NEON assembler

> NEON assembler is supported with no additional caveats as long as the rules above are followed.

NEONアセンブラは、上記のルールが守られている限り、追加の警告なしでサポートされます。

# NEON code generated by GCC

> The GCC option -ftree-vectorize (implied by -O3) tries to exploit implicit parallelism, and generates NEON code from ordinary C source code. 

GCCオプション-ftree-vectorize（-O3によって暗黙指定）は、暗黙的な並列処理を利用しようとし、通常のCソースコードからNEONコードを生成します。

This is fully supported as long as the rules above are followed.

上記のルールが守られていれば、これは完全にサポートされます。

# NEON intrinsics

> NEON intrinsics are also supported. 

NEON組み込み関数もサポートしています。

> However, as code using NEON intrinsics relies on the GCC header <arm_neon.h>, (which #includes <stdint.h>), you should observe the following in addition to the rules above:

ただし、NEON組み込み関数を使用するコードはGCC header<arm_neon.h>（#include <stdint.h>を含む）に依存しているため、上記のルールに加えて、次の点に注意する必要があります。

> * Compile the unit containing the NEON intrinsics with ‘-ffreestanding’ so GCC uses its builtin version of <stdint.h> (this is a C99 header which the kernel does not supply);
* Include <arm_neon.h> last, or at least after <linux/types.h>

* NEON組み込みを含むユニットを「-ffreestanding」でコンパイルして、GCCが組み込みバージョンの<stdint.h>を使用するようにします（これはカーネルが提供しないC99ヘッダーです）。
* 　`<arn_neon.h>`を、一番最後、もしくは少なくとも `<linux/types.h>`の後に追加します。