2017-02-17 12 views
3

私は、Raspberry PIを含む組み込みシステムでRedisが正常に動作するように一連の作業を行っています。アライメントの合っていないメモリアクセスが実行されるRedisの特定のコードパスを修正するために(私はRedis 3.2で導入された変更のために)PIがアライメントされていないメモリアクセスでメッセージを記録するようにするか、これが起こる。このようにして、私は、非境界整列のアクセスが違反である場合、Redisがうまく動作し、代わりにそのようなアクセスを実行することができますが、遅いプラットフォームではより高速に動作することを確認できます。 ARM v6の、PI v1のに使用されるものは、明らかに非整列メモリに対処することが可能である私は、Linuxを設定するには、次のコマンドを使用しますので、もし、アクセスするために、非整列アクセスを実行するプロセスにシグナルを送っしますラズベリーPIバージョン1でアライメントされていないアクセスが検出されない

echo 4 > /proc/cpu/alignment 
をその後、

そして、次のプログラムを実行します。私は/proc/cpu/alignmentインクリメントの処理で受信した信号、またはカウンタを見ることができない

#include <stdio.h> 
#include <stdint.h> 

int main(int argc, char **argv) { 
    char *buf = "foobareklsjdfklsjdfslkjfskdljfskdfjdslkjfdslkjfsd"; 
    uint32_t *l = (uint32_t*) (buf+1); 
    printf("%p\n", l); 
    printf("%d\n", (int)*l); 
    return 0; 
} 

を。

これは、指定されたCPU構成フラグが設定されていると、アライメントされていないアドレスを自動的に処理するためのARM v6の能力によるものです。私の疑問は、私の仮説は正しいのですか?もしそうなら、/ proc/cpu/alignmentに従って、Linuxカーネルがそれをトラップしてシグナルを送信したり、アクセスを記録したりすることができるように、PIバージョン1に実際にアライメントの合っていないアクセスが発生した場合に例外を発生させる設定?

EDIT:ARMv6でもすべての命令がアラインされていないアクセスを実行できるわけではありません。たとえば、STMDB、STMFD、LDMDB、LDMEAなどの複数ワード命令は、実際には例外を発生させ、Linuxカーネルにトラップされます。私は最終的に私の答えを見つけたと思う

答えて

4

  1. はい、私はワード・サイズのARM v6の(またはそれ以上)まで、正しいんだが静かにそう何のトラップが生成されていないアクセスして、完全に透明な非整列を扱うことができますLinuxカーネルの場合何もログに記録されず、/proc/cpu/alignmentのトラップカウンタもインクリメントされません。
  2. AFAIKカーネルにワードサイズのアラインされていないアクセスをトラップさせる方法はありません。なぜなら、そうするためには、CPUはすべての場合にアライメントされていないアドレスをトラップするために設定する必要があるからです。そのAFAIKはおそらくカーネル内部に安全でないコードが整列しているためです。 1が見ることができる実際にLinuxカーネルのソースコードを確認する:

    if (cpu_is_v6_unaligned()) { 
         set_cr(__clear_cr(CR_A)); 
         ai_usermode = safe_usermode(ai_usermode, false); 
    } 
    

    これが何を意味するのかは、SCTLR.Aビットは常にクリアされているので、整列していないが、V6が処理できるARMにアクセスするために何のトラップ が生成されないということです。

  3. マルチストア/ロード命令、ダブル値のロードと格納など、アラインされていないアドレスでもトラップが生成されることがあります。

  4. しかし、正しく、/proc/cpu/alignmentがに設定されている場合でも、生成SIGBUSをもたらすことのLinuxカーネルによって処理されていないGCC(デフォルトラズベリーのLinuxディストリビューションに同梱版)が喜んを生成します命令がありますアクセスを修正してください。

だから、ポイント数4は、基本的にはARMで実行するプログラムを修正するために、良いアイデアではありませんV6だけ非整列アドレスのパフォーマンスに影響がある場合でも、Linuxカーネルは、私たちのための非整列アドレスを処理せ、ということを意味問題ではありません。すべての命令が処理されるわけではないので、プログラムはまだクラッシュする可能性があります。

残念なことに、そうでなければ素晴らしいvalgrindプログラムは、この機能を実装したことがないので、プログラム内のすべてのアライメントされていないアクセスを確実に見つける方法は未解決です。過去に私はSparcをエミュレートするQEMUを使用しなければなりませんでしたが、これは非常に遅いプロセスです。 Valgrindはそれを行うための些細な方法でしょう。

+1

ARMv4とv5でも境界整列されていないアクセスが許可されていますが、一部のアームコアではデフォルトで有効になっています。どちらの場合でも有効または無効にすることができます。アライメントのとれていないアクセスの古いコアの動作は、期待通りのものとは異なる/奇妙でした。次のアドレスに落ちるのではなく、ワード内のバイトを回転させます。それはバイトアクセス(またはハーフワード)のためのゼロバイトレーン上の正しいバイトを得る方法であり、その猫をスキンするための複数の方法です。 –

+1

ARMの場合ではなく、ソフトウェアで一般的に整列していないアクセスを検出したい場合は、x86環境でLinux上の整列していないアクセスをトラップすることができます。 – EOF

+0

EOFはい私はあなたがACレジスタを参照していることを発見しました。しかし、gdb setコマンドでなければ、私のプログラムでそれを有効にする信頼できる方法を見つけられませんでした。 – antirez

関連する問題