Vidage des données mises en cache pendant les opérations DMA
Sur certaines plateformes, le processeur et le contrôleur DMA système (ou les adaptateurs DMA master bus) présentent des anomalies de cohérence du cache. Les instructions suivantes permettent aux pilotes qui utilisent la version 1 ou 2 de l’interface des opérations DMA (voir DMA_OPERATIONS) de maintenir des états de cache cohérents dans toutes les architectures de processeur prises en charge, y compris les architectures qui ne contiennent pas de matériel pour appliquer automatiquement la cohérence du cache.
Note Les instructions de cette rubrique s’appliquent uniquement aux pilotes qui utilisent les versions 1 et 2 de l’interface des opérations DMA. Les pilotes qui utilisent la version 3 de cette interface doivent suivre un autre ensemble de instructions. Pour plus d’informations, consultez Version 3 de l’interface DMA Operations.
Pour maintenir l’intégrité des données pendant les opérations DMA, les pilotes de niveau le plus bas doivent suivre ces instructions
Appelez KeFlushIoBuffers avant de commencer une opération de transfert pour maintenir la cohérence entre les données qui peuvent être mises en cache dans le processeur et les données en mémoire.
Si un pilote appelle AllocateCommonBuffer avec le paramètre CacheEnabled défini sur TRUE, le pilote doit appeler KeFlushIoBuffers avant de commencer une opération de transfert vers/depuis sa mémoire tampon.
Appelez FlushAdapterBuffers à la fin de chaque opération de transfert d’appareil pour vous assurer que les octets restants dans les mémoires tampons du contrôleur DMA système ont été écrits dans la mémoire ou sur l’appareil subordonné.
Vous pouvez également appeler FlushAdapterBuffers à la fin de chaque opération de transfert pour un IRP donné pour vous assurer que toutes les données ont été lues dans la mémoire système ou écrites sur un appareil DMA master bus.
L’illustration suivante montre pourquoi il est important de vider le cache du processeur avant une opération de lecture ou d’écriture à l’aide de DMA si le processeur hôte et le contrôleur DMA ne gèrent pas automatiquement la cohérence du cache.
Une opération de lecture ou d’écriture DMA asynchrone accède aux données en mémoire, et non dans le cache du processeur. À moins que ce cache n’ait été vidé en appelant KeFlushIoBuffers juste avant une lecture, les données transférées dans la mémoire système par l’opération DMA peuvent être remplacées par des données obsolètes si le cache du processeur est vidé ultérieurement. À moins que le cache du processeur n’ait été vidé en appelant KeFlushIoBuffers juste avant une écriture, les données de ce cache peuvent être plus à jour que la copie en mémoire.
KeFlushIoBuffers ne fait rien si le processeur et le contrôleur DMA peuvent être utilisés pour maintenir la cohérence du cache. Par conséquent, les appels à cette routine de support n’ont presque pas de surcharge dans une telle plateforme.
Comme indiqué dans la figure précédente, les contrôleurs DMA, qui sont représentés par des objets d’adaptateur, peuvent avoir des mémoires tampons internes. Un tel contrôleur DMA peut transférer des données mises en cache dans des blocs de taille fixe, généralement huit octets ou plus à la fois. De plus, ces contrôleurs DMA peuvent attendre que leurs mémoires tampons internes soient complètes avant chaque opération de transfert.
Considérez le cas d’un pilote de niveau inférieur qui utilise DMA subordonné pour lire des données dans des segments de taille variable ou dans des segments de taille fixe qui ne sont pas un multiple intégral de la taille du cache d’un contrôleur DMA système. À moins que ce pilote n’appelle FlushAdapterBuffers à la fin de chaque transfert d’appareil, il ne peut pas être sûr que chaque octet demandé sera effectivement transféré.
Le pilote d’un périphérique DMA master bus doit également appeler FlushAdapterBuffers à la fin de chaque opération de transfert pour qu’un IRP s’assure que toutes les données ont été transférées dans la mémoire système ou vers l’appareil.
FlushAdapterBuffers retourne une valeur booléenne qui indique si l’opération de vidage demandée a réussi. Un pilote peut utiliser cette valeur pour déterminer comment définir le bloc d’E/S status lors de l’exécution d’une IRP pour une opération de lecture ou d’écriture DMA.