2011-10-26 14 views
6

Ho un hardware che voglio emulare; Mi chiedo se posso farlo a un livello basso come questo. L'hardware ha molti registri, che organizzo in una struttura:Come emulare l'I/O mappato in memoria

#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; 

Quindi, voglio sostenere la seguente sintassi per l'accesso hardware su Windows e Linux:

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

Quando l'ultima riga di codice viene eseguito, voglio che l'emulatore hardware si "svegli" e faccia qualcosa. Posso implementarlo su Windows e/o Linux? Ho pensato di prendere in qualche modo il segnale di "segmentation fault", ma non sono sicuro se questo può essere fatto su Windows, o del tutto.

Ho guardato la pagina di manuale di mmap; sembra che possa aiutare, ma non ho potuto capire come posso usarlo.

Ovviamente, potrei astrarre l'accesso all'hardware definendo funzioni come WriteToMyDevice e tutto sarebbe facile (forse), ma voglio capire se riesco ad organizzare l'accesso al mio hardware in questo modo esatto.

+0

Il tuo "livello basso" è troppo alto ... Sia in Windows che in Linux l'accesso all'hardware avviene dalla modalità kernel. Devi pensare a più dettagli di implementazione - come parlare con l'hardware. Ad esempio, è possibile scrivere l'effettiva emulazione di driver e driver. –

+0

Quindi, utilizzare gli indirizzi di memoria predefiniti in modalità utente è impossibile? – anatolyg

+0

Non è possibile parlare direttamente con il dispositivo hardware dalla modalità utente Windows/Linux utilizzando l'accesso diretto alla memoria. Questo è possibile solo nella modalità kernel. Questo è il motivo per cui ti suggerisco di pensare prima ai dettagli di implementazione. Senza di loro in realtà non sai cosa emulare. –

risposta

2

In linea di principio, è possibile codificare (unportably) un gestore per SIGSEGV che avrebbe intercettare e gestire l'accesso alle pagine indesiderate, e che potrebbe verificare che un indirizzo specificato si accede.

Per farlo in Linux, è necessario utilizzare la chiamata di sistema sigaction con SA_SIGINFO e utilizzare il terzo argomento ucontext_t* del gestore di segnale.

Questo è estremamente non esportabile: dovrete codificare in modo diverso per diversi Unix (forse anche il numero di versione del kernel di Linux potrebbe essere importante) e quando si cambiano i processori.

E ho sentito dire che i kernel di Linux non sono molto veloci su questo tipo di gestione.

Altri kernel migliori (Hurd, Plan9) offrono l'impaginazione a livello di utente, che dovrebbe aiutare.

1

In realtà il tuo emulatore è (piuttosto rozzamente) possibile su Linux con puro codice di spazio utente.

Per costruire l'emulatore, semplicemente una seconda filettatura o processo (utilizzando memoria condivisa, o forse un file mmap'd e inotify) monitorando la memoria che emula il dispositivo di memoria mappata

Per il driver hardware reale , avrete bisogno di un po 'di codice del kernel, ma quello potrebbe essere semplicemente qualcosa che mappa gli indirizzi hardware reali nello spazio utente con le autorizzazioni appropriate. In effetti, questo regredisce un moderno ambiente operativo multiutente fino a comportarsi come una vecchia scatola dos o un semplice microcontrollore - non una grande pratica, ma funzionante almeno laddove la sicurezza non è un problema.

Un'altra cosa che si potrebbe considerare sarebbe eseguire il codice in una macchina virtuale.

Se il codice che si sta esercitando è il proprio, è probabilmente meglio scrivere in un modo portatile per cominciare, estrapolando l'accesso all'hardware in funzioni che è possibile riscrivere per ogni piattaforma (ad esempio, OS, versione hardware o fisica/emulata). Queste tecniche sono più utili se si tratta del codice esistente di qualcun altro per il quale è necessario creare un ambiente. Un'altra cosa che puoi considerare (se l'originale non è troppo strettamente integrato) usa l'intercettazione a livello di libreria dinamica di funzioni specifiche, per esempio con LD_PRELOAD su linux o una dll wrapper su windows. O del resto, aggiustando il binario.

1

Inizialmente non capisco la tua domanda. Hai un pezzo di hardware mappato in memoria e vuoi che la tua emulazione sia compatibile con i binari. Su Windows è possibile allocare la memoria per la struttura utilizzando VirtualAlloc e trasformarlo in una pagina di guardia e catturare qualsiasi accesso ad esso utilizzando SEH.