2011-10-26 17 views
6

Tengo hardware que quiero emular; Me pregunto si puedo hacerlo a un nivel bajo como este. El hardware tiene muchos registros, que yo arregle en una estructura:Cómo emular E/S mapeadas en 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; 

Por lo tanto, quiero apoyar la siguiente sintaxis para el acceso al hardware en Windows y Linux:

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

Cuando la última línea de código se ejecuta, quiero que el emulador de hardware se "despierte" y haga algunas cosas. ¿Puedo implementar esto en Windows y/o Linux? Pensé en detectar de alguna manera la señal de "falla de segmentación", pero no estoy seguro de si esto puede hacerse en Windows, o en absoluto.

Miré la página de manual de mmap; parece que puede ayudar, pero no pude entender cómo puedo usarlo.

Por supuesto, podría resumir el acceso al hardware definiendo funciones como WriteToMyDevice, y todo sería fácil (tal vez), pero quiero entender si puedo organizar el acceso a mi hardware de esta manera exacta.

+0

Su "nivel bajo" es demasiado alto ... Tanto en Windows como en Linux, el acceso al hardware se realiza desde el modo kernel. Debe pensar en más detalles de implementación: cómo hablar con el hardware. Por ejemplo, puede escribir emulación real de controlador y controlador. –

+0

Entonces, ¿es imposible usar direcciones de memoria predefinidas en el modo de usuario? – anatolyg

+0

No se puede hablar directamente con el dispositivo de hardware desde el modo de usuario Windows/Linux utilizando el acceso directo a la memoria. Esto es posible solo en el modo kernel. Es por eso que le sugiero que piense primero sobre los detalles de implementación. Sin ellos, en realidad no sabes qué emular. –

Respuesta

2

En principio, podría codificar (unportably) un controlador para SIGSEGV que atraparía y manejaría el acceso a páginas no deseadas, y que podría verificar el acceso a una dirección específica.

Para hacer eso en Linux, deberá usar la llamada al sistema sigaction con SA_SIGINFO y usar el tercer argumento ucontext_t* de su manejador de señal.

Esto es extremadamente poco práctico: tendrá que codificar de manera diferente para diferentes Unixes (quizás incluso el número de versión de su kernel de Linux podría importar) y al cambiar procesadores.

Y he oído que los kernels de Linux no son muy rápidos en este tipo de manejo.

Otros núcleos mejores (Hurd, Plan9) ofrecen paginación a nivel de usuario, lo que debería ayudar.

1

En realidad, su emulador es (bastante crudamente) posible en Linux con código de espacio de usuario puro.

Para construir el emulador, sólo tiene que tener un segundo hilo o proceso (se utiliza la memoria compartida, o tal vez un archivo mmap'd y inotify) viendo la memoria que está emulando el dispositivo de memoria mapeada

Para el conductor hardware real , necesitará un poquito de código kernel, pero eso simplemente podría ser algo que mapee las direcciones de hardware reales en el espacio del usuario con los permisos apropiados. En efecto, esto hace retroceder un entorno operativo multiusuario moderno hasta actuar como un viejo dos box o un simple microcontrolador; no es una buena práctica, pero al menos funciona cuando la seguridad no es una preocupación.

Otra cosa que podría considerar sería ejecutar el código en una máquina virtual.

Si el código que va a ejercer es el suyo, probablemente sea mejor escribirlo de manera portátil para comenzar, abstrayendo el acceso de hardware en funciones que puede volver a escribir para cada plataforma (es decir, SO, versión de hardware o física/emulada). Estas técnicas son más útiles si se trata de un código existente de otra persona para el que se necesita crear un entorno. Otra cosa que puede considerar (si el original no está muy bien integrado) es utilizar la intercepción de nivel dinámico de biblioteca de funciones específicas, por ejemplo con LD_PRELOAD en Linux o un contenedor dll en Windows. O para el caso, parchear el binario.

1

Incomprendo su pregunta inicialmente. Tiene una pieza de hardware mapeado en memoria y desea que su emulación sea binaria. En Windows podría asignar la memoria para la estructura usando VirtualAlloc y convertirla en una página de guardia y capturar cualquier acceso a ella usando SEH.