linux - multiprocesadores - memoria cache
Gestión de coherencia de caché DMA (2)
Estoy realmente sorprendido de que nadie haya respondido esto, así que aquí vamos con una respuesta no específica de Linux (no tengo conocimiento suficiente del kernel de Linux para ser más específico) ...
La indagación de caché simplemente le dice al controlador DMA que envíe solicitudes de invalidación de caché a todas las CPU para la memoria DMA en la que se está. Obviamente, esto agrega carga al bus de coherencia de la memoria caché, y se amplía particularmente con procesadores adicionales, ya que no todas las CPU tendrán una conexión de salto único con el controlador DMA que emite el snoop. Por lo tanto, la respuesta simple a "cuando es seguro deshabilitar la indagación de la memoria caché" es cuando la memoria que se está guardando en DMA no existe en ninguna memoria caché de la CPU O si sus líneas de memoria caché están marcadas como no válidas. En otras palabras, cualquier intento de leer desde la región DMAed siempre resultará en una lectura desde la memoria principal.
Entonces, ¿cómo garantiza que las lecturas de una región DMAed siempre vayan a la memoria principal?
En la víspera, antes de que tuviéramos características sofisticadas como el espionaje de caché DMA, lo que solíamos hacer era canalizar la memoria DMA alimentándola a través de una serie de etapas divididas de la siguiente manera:
Etapa 1: agregue la región de memoria DMA "sucia" a la lista de memoria DMA "sucia y que necesita limpiarse".
Etapa 2: la próxima vez que el dispositivo interrumpa con datos nuevos de DMA, emita una invalidación de la memoria caché de la CPU local asíncrona para los segmentos de DMA en la lista "sucia y necesita limpieza" para todas las CPU que puedan acceder a esos bloques (a menudo cada CPU ejecuta su listas propias compuestas por bloques de memoria local). Mueva dichos segmentos a una lista "limpia".
Etapa 3: Próxima interrupción de DMA (que, por supuesto, está seguro de que no ocurrirá antes de que se complete la invalidación de la memoria caché anterior), tome una nueva región de la lista "limpia" e informe al dispositivo que su próxima DMA debe incluirse en esa. Recicle cualquier bloque sucio.
Etapa 4: Repetir.
Por más que esto sea más trabajo, tiene varias ventajas importantes. En primer lugar, puede fijar el manejo de DMA en una sola CPU (normalmente la CPU0 primaria) o en un solo nodo SMP, lo que significa que solo una CPU / nodo único debe preocuparse por la invalidación de la memoria caché. En segundo lugar, le da al subsistema de memoria muchas más oportunidades de ocultar las latencias de la memoria al espaciar las operaciones a lo largo del tiempo y distribuir la carga en el bus de coherencia de caché. La clave para el rendimiento generalmente es tratar de hacer que ocurra cualquier DMA en una CPU lo más cerca posible del controlador DMA relevante y en la memoria lo más cerca posible de esa CPU.
Si siempre transfiere el nuevo DMAed a la memoria al espacio del usuario y / u otras CPU, simplemente inyecte la memoria recién adquirida en la parte frontal de la tubería de validación de memoria caché asíncrona. Algunos sistemas operativos (no estoy seguro acerca de Linux) tienen una rutina optimizada para preordenar la memoria puesta a cero, por lo que el sistema operativo básicamente pone a cero la memoria en segundo plano y mantiene una memoria caché de satisfacción rápida. Le pagará mantener nuevas solicitudes de memoria por debajo de esa cantidad almacenada en caché porque la memoria de puesta a cero es extremadamente lento No tengo conocimiento de ninguna plataforma producida en los últimos diez años que utilice la puesta a cero de la memoria del hardware descargado, por lo que debe suponer que toda la memoria nueva puede contener líneas de caché válidas que deben invalidarse.
Agradezco que solo responda la mitad de tu pregunta, pero es mejor que nada. ¡Buena suerte!
Niall
Mi pregunta es la siguiente: ¿cómo puedo determinar cuándo es seguro deshabilitar la indagación de caché cuando estoy usando correctamente [pci_]dma_sync_single_for_{cpu,device}
en mi controlador de dispositivo?
Estoy trabajando en un controlador de dispositivo para un dispositivo que escribe directamente en la memoria RAM a través de PCI Express (DMA), y me preocupa la administración de la coherencia de la memoria caché. Hay un bit de control que puedo configurar al iniciar el DMA para habilitar o deshabilitar la indagación de caché durante la DMA, claramente para el rendimiento. Me gustaría dejar la indagación de la caché deshabilitada si es posible.
En la rutina de interrupción, llamo a pci_dma_sync_single_for_cpu()
y ..._for_device()
según corresponda, al cambiar los buffers DMA, pero en Linux 2.6.18 (RHEL 5) de 32 bits resulta que estos comandos son macros que se expanden a nada. .. lo que explica por qué mi dispositivo devuelve basura cuando la indagación de caché está deshabilitada en este núcleo.
He rastreado a través de la historia de las fuentes del kernel, y parece que hasta 2.6.25 solo x86 de 64 bits tenían ganchos para la sincronización DMA. Desde 2.6.26 parece haber un mecanismo genérico de direccionamiento unificado para la sincronización DMA (actualmente en include/asm-generic/dma-mapping-common.h
) a través de los campos sync_single_for_{cpu,device}
de dma_map_ops
, pero hasta ahora he No se pudo encontrar ninguna definición de estas operaciones.
Tal vez un poco atrasado, pero:
Si deshabilita la búsqueda de caché, el hardware ya no se hará cargo de la coherencia de la memoria caché. Por lo tanto, el núcleo necesita hacer esto por sí mismo. En los últimos días, he pasado un tiempo revisando las variantes de X86 de [pci_] dma_sync_single_for_ {cpu, device}. No he encontrado ninguna indicación de que realicen ningún esfuerzo para mantener la coherencia. Esto parece coherente con el hecho de que la indagación de caché está activada de forma predeterminada en la especificación PCI (e).
Por lo tanto, si está desactivando la indagación de caché, tendrá que mantener la coherencia en el controlador. Posiblemente llamando a clflush_cache_range () (X86) o similar?
Refs: