2011-10-26 9 views
6

私はエミュレートしたいハードウェアをいくつか持っています。私はこのような低レベルでそれをやり遂げることができるのだろうかと思う。ハードウェアは、私が構造体にアレンジ多くのレジスタ、持っている:メモリマップされたI/Oをエミュレートする方法

MyDevice->data_reg_1 = 42; 
MyDevice->data_reg_2 = 100; 
MyDevice->control_reg_1 = 1; 

コードの最後の行を:だから

#include <stdint.h> 
struct MyControlStruct 
{ 
    uint32_t data_reg_1; 
    uint32_t data_reg_2; 
    uint32_t dummy[2]; // to make the following registers have certain addresses 
    uint32_t control_reg_1; 
    uint32_t control_reg_2; 
}; 
volatile struct MyControlStruct* MyDevice = (struct MyControlStruct*)0xDeadF00; 

を、私は、WindowsおよびLinux上のハードウェアにアクセスするための次の構文をサポートしたいですハードウェアエミュレータが "起きて"何かをやりたいと思っています。 WindowsやLinuxでこれを実装できますか?私は何とか "セグメンテーションフォールト"シグナルをキャッチすることを考えましたが、これがWindows上で実行できるか、まったく実行できないかはわかりません。

マニュアルページmmapを見ました。それは助けることができるようだが、私はそれをどのように使うことができるのか理解できませんでした。

もちろん、私はWriteToMyDeviceのような関数を定義することでハードウェアへのアクセスを抽象化することができますが、すべてが簡単です(おそらく)、私はこの正確な方法で私のハードウェアへのアクセスを手配することができます。

+0

"低レベル"が高すぎます... WindowsとLinuxの両方でハードウェアアクセスはカーネルモードから実行されます。ハードウェアとの対話の仕方、実装の詳細について考える必要があります。たとえば、実際のドライバとドライバエミュレーションを書き込むことができます。 –

+0

したがって、ユーザモードで事前に定義されたメモリアドレスを使用することは不可能ですか? – anatolyg

+0

直接メモリアクセスを使用してWindows/Linuxのユーザモードからハードウェアデバイスと直接通信することはできません。これはカーネルモードでのみ可能です。このため、実装の詳細について最初に考えることをお勧めします。それらがなければ、あなたは実際に何をエミュレートするかを知らない。 –

答えて

2

原則として、望ましくないページへのアクセスをトラップして処理し、指定されたアドレスがアクセスされているかどうかをチェックするSIGSEGVのハンドラをコード化できます。

Linuxでこれを行うには、SA_SIGINFOsigactionシステムコールを使用し、ucontext_t*シグナルハンドラの第3引数を使用する必要があります。

これは非常に移植性が悪い:異なるUnix(多分あなたのLinuxカーネルのバージョン番号でさえ問題があるかもしれない)とプロセッサーを変更するときに違うコードをしなければならないだろう。

そして、私は、Linuxカーネルがこのような処理にはあまり迅速ではないと聞いています。

その他の優れたカーネル(Hurd、Plan9)では、ユーザーレベルのページネーションが用意されています。

1

あなたのエミュレータは、純粋なユーザスペースコードを使ってLinux上で(かなり粗く)可能です。

エミュレータを構築するには、単純に(共有メモリ、またはおそらくmmap'dファイルを使用してはinotify)は、第2のスレッドまたはプロセスを有する実際のハードウェアのドライバのためにメモリマップされたデバイス

をエミュレートしているメモリを見ごくわずかな量のカーネルコードが必要になりますが、実際のハードウェアアドレスを適切なパーミッションでユーザー空間にマップすることができます。実際には、これは、現代のマルチユーザ環境を、古いDOSボックスや単純なマイクロコントローラのように振る舞うことに回帰させます。偉大な習慣ではありませんが、少なくともセキュリティは重要ではありません。

もう1つのことは、仮想マシンでコードを実行することです。

あなたが演習するコードが自分のものであれば、ハードウェアアクセスを抽象化して各プラットフォーム(OS、ハードウェアバージョンまたは物理/エミュレートされたバージョン)。これらの手法は、環境を作成するために必要な既存のコードであれば、より便利です。あなたが考えることができるもう一つの事柄(オリジナルがあまりにも緊密に統合されていない場合)は、例えばLinux上のLD_PRELOADやウィンドウ上のラッパーDLLのような特定の関数の動的ライブラリレベル傍受を使用しています。あるいは、バイナリにパッチを当てることです。

1

私は最初あなたの質問を誤解しています。メモリにマップされたハードウェアがあり、エミュレーションをバイナリ互換にする必要があります。 Windowsでは、VirtualAllocを使って構造体のメモリを割り当てて、それをガードページにして、SEHを使ってアクセスすることができます。

関連する問題