Vaciado de datos almacenados en caché durante las operaciones de DMA
En algunas plataformas, el procesador y el controlador DMA del sistema (o adaptadores DMA maestros de bus) exhiben anomalías de la coherencia de caché. Las instrucciones siguientes permiten a los controladores que usan la versión 1 o 2 de la interfaz de operaciones DMA (consulte DMA_OPERATIONS) mantener estados de caché coherentes en todas las arquitecturas de procesador compatibles, incluidas las arquitecturas que no contienen hardware para aplicar automáticamente la coherencia de caché.
Nota Las directrices de este tema solo se aplican a los controladores que usan las versiones 1 y 2 de la interfaz de operaciones DMA. Los controladores que usan la versión 3 de esta interfaz deben seguir un conjunto diferente de directrices. Para obtener más información, vea La versión 3 de la interfaz de operaciones de DMA.
Para mantener la integridad de los datos durante las operaciones de DMA, los controladores de nivel más bajo deben seguir estas directrices.
Llame a KeFlushIoBuffers antes de comenzar una operación de transferencia para mantener la coherencia entre los datos que podrían almacenarse en caché en el procesador y los datos en memoria.
Si un controlador llama a AllocateCommonBuffer con el parámetro CacheEnabled establecido en TRUE, el controlador debe llamar a KeFlushIoBuffers antes de iniciar una operación de transferencia hacia y desde su búfer.
Llame a FlushAdapterBuffers al final de cada operación de transferencia de dispositivos para asegurarse de que los bytes restantes del búfer del controlador DMA del sistema se han escrito en la memoria o en el dispositivo subordinado.
O bien, llame a FlushAdapterBuffers al final de cada operación de transferencia para un IRP determinado para asegurarse de que todos los datos se han leído en la memoria del sistema o se han escrito en un dispositivo DMA maestro de bus.
En la ilustración siguiente se muestra por qué es importante vaciar la memoria caché del procesador antes de una operación de lectura o escritura mediante DMA si el procesador host y el controlador DMA no mantienen automáticamente la coherencia de caché.
Una operación asincrónica de lectura o escritura de DMA accede a los datos en memoria, no en la memoria caché del procesador. A menos que esta caché se haya vaciado llamando a KeFlushIoBuffers justo antes de una lectura, los datos transferidos a la memoria del sistema por la operación DMA se podrían sobrescribir con datos obsoletos si la memoria caché del procesador se vacía más adelante. A menos que la memoria caché del procesador se haya vaciado llamando a KeFlushIoBuffers justo antes de una escritura, los datos de esta memoria caché podrían estar más actualizados que la copia en memoria.
KeFlushIoBuffers no hace nada si se puede confiar en el procesador y el controlador DMA para mantener la coherencia de caché, por lo que las llamadas a esta rutina de soporte técnico no tienen casi ninguna sobrecarga en esta plataforma.
Como también se muestra en la ilustración anterior, los controladores DMA, representados por objetos de adaptador, pueden tener búferes internos. Este tipo de controlador DMA puede transferir datos almacenados en caché en fragmentos de tamaño fijo, normalmente ocho o más bytes a la vez. Además, estos controladores DMA pueden esperar hasta que sus búferes internos estén llenos antes de cada operación de transferencia.
Considere el caso de un controlador de nivel inferior que usa DMA subordinado para leer datos en fragmentos de tamaño variable o en fragmentos de tamaño fijo que no son un múltiplo entero de un tamaño de caché del controlador DMA del sistema. A menos que este controlador llame a FlushAdapterBuffers al final de cada transferencia de dispositivo, no puede estar seguro de cuándo se transferirán realmente todos los bytes solicitados.
El controlador de un dispositivo DMA maestro de bus también debe llamar a FlushAdapterBuffers al final de cada operación de transferencia para un IRP para asegurarse de que todos los datos se han transferido a la memoria del sistema o fuera del dispositivo.
FlushAdapterBuffers devuelve un valor booleano, que indica si la operación de vaciado solicitada se realizó correctamente. Un controlador puede usar este valor para determinar cómo establecer el bloque de estado de E/S al completar un IRP para una operación de lectura o escritura de DMA.