2012-06-28 14 views
6

Estoy intentando escribir un controlador con la función personalizada mmap() para la barra PCIe, con el objetivo de hacer que esta BAR sea almacenable en el caché del procesador. Soy consciente de que esta no es la mejor manera de lograr el mayor ancho de banda y que el orden de las escrituras es impredecible (como tampoco lo son los problemas en este caso).cómo hacer mmap para almacenar en caché la barra PCIe

Esto es similar a lo que se describe en How would one prevent MMAP from caching values?

El procesador es de arena i7 Puente, dispositivo PCIe es Altera Stratix IV dev. tablero.

Primero, traté de hacerlo en CentOS 5 (2.6.18). Cambié las configuraciones de MTRR para asegurarme de que la BAR no esté dentro de un MTRR que no se puede descartar y que usó io_remap_pfn_range() con _PAGE_PCD y _PAGE_PWT bits borrados. Read trabajó como se esperaba: lee los valores correctos devueltos y la segunda lectura para la misma dirección no necesariamente hace que la lectura vaya a PCIe (el contador de lectura se activó en FPGA). Sin embargo, las escrituras causaron que el sistema se congele y luego se reinicie sin ningún mensaje en los registros o en la pantalla.

En segundo lugar, traté de hacerlo en CentOS 6 (2.6.32), que tiene compatibilidad con PAT. El resultado es el mismo: las lecturas funcionan correctamente, las escrituras causan la congelación del sistema y se reinician. Curiosamente, las escrituras en línea de caché completa (AVX/SSE) no temporales/que combinan escritura funcionan como se esperaba, es decir, siempre van a FPGA y FPGA observa las escrituras completas de la línea de caché, lee los valores de retorno correctos después. Sin embargo, las escrituras simples de 64 bits todavía causan el congelamiento/reinicio del sistema.

También intenté ioremap_cache() y luego iowrite32() dentro del código del controlador. El resultado es el mismo.

Creo que es un problema de hardware pero agradecería que alguien pueda compartir cualquier idea sobre lo que está pasando.

EDITAR: Pude capturar el mensaje MCE en CentOS 6: Excepción de comprobación de la máquina: 5 Banco 5: be2000000003110a.

También probé el mismo código en Sandy Bridge de 2 sockets (Romley): las lecturas y el comportamiento de escritura no temporal son las mismas, las escrituras simples no causan MCE/crash pero no tienen efecto en el estado del sistema, es decir, la memoria no cambia

Además, probé el mismo código en el antiguo sistema Nehalem de 2 sockets: las escrituras simples también causan MCE, aunque los códigos son diferentes.

Respuesta

6

No conozco ningún hardware x86 que admita el tipo de memoria WriteBack (WB) para las direcciones MMIO, y es casi seguro que vea el resultado de esa incompatibilidad. me han publicado una discusión sobre este tema en mi blog en http://blogs.utexas.edu/jdm4372/2013/05/29/ y http://blogs.utexas.edu/jdm4372/2013/05/30/

En esas publicaciones, discuto un método que funciona en algunos procesadores - mapa del MMIO surtido de dos veces - una vez para las operaciones de almacén desde el procesador hasta el FPGA que usa el tipo de memoria Write-Combining (WC) y una vez para las lecturas del procesador al FPGA utilizando los tipos Write Protect (WP) o Write Through (WT). Tendrá que mantener la coherencia de forma manual mediante el uso de CLFLUSH en las líneas de caché en la región de "solo lectura" cuando escribe en el alias de esa línea en la región de "solo escritura". También deberá mantener la coherencia de forma manual con respecto a los cambios en los valores en la memoria FPGA, ya que los dispositivos IO no pueden generar transacciones de invalidación de caché para direcciones MMIO.

Mi equipo hizo esto hace unos años cuando estaba en AMD, y ahora estoy tratando de encontrar la manera de hacerlo con los núcleos Linux más nuevos y con los procesadores Intel. Linux no admite directamente tipos de memoria WP o WT con sus funciones de mapeo predefinidas, por lo que se requiere algo de hackeo ...Es bastante fácil anular el MTRR para una región, pero estoy teniendo más problemas para encontrar los lugares correctos en los descendientes de la función remap_pfn_range() que necesito cambiar para obtener el atributo WP o WT establecido en las entradas PAT para el rango.

Este método es probablemente más adecuado para FPGA que para otros tipos (predefinidos) de dispositivos IO, ya que la programabilidad del FPGA permite la flexibilidad para definir las barras PCI para operar en este modo de doble asignación y cooperar con el controlador del lado del procesador para mantener la coherencia del caché.

Cuestiones relacionadas