Freigeben über


Leeren zwischengespeicherter Daten während DMA-Vorgängen

Auf einigen Plattformen weisen der Prozessor- und System-DMA-Controller (oder Bus-master-DMA-Adapter) Cachekohärenzanomalien auf. Die folgenden Richtlinien ermöglichen Es Treibern, die Version 1 oder 2 der DMA-Betriebsschnittstelle verwenden (siehe DMA_OPERATIONS), kohärente Cachezustände für alle unterstützten Prozessorarchitekturen aufrechtzuerhalten, einschließlich Architekturen, die keine Hardware zur automatischen Erzwingung der Cachekohärenz enthalten.

Hinweis Die Richtlinien in diesem Thema gelten nur für Treiber, die die Versionen 1 und 2 der DMA-Betriebsschnittstelle verwenden. Treiber, die Version 3 dieser Schnittstelle verwenden, müssen anderen Richtlinien folgen. Weitere Informationen finden Sie unter Version 3 der DMA-Betriebsschnittstelle.

Um die Datenintegrität während DMA-Vorgängen aufrechtzuerhalten, müssen Treiber der niedrigsten Ebene diese Richtlinien befolgen.

  1. Rufen Sie KeFlushIoBuffers auf, bevor Sie mit einem Übertragungsvorgang beginnen, um die Konsistenz zwischen Daten, die möglicherweise im Prozessor zwischengespeichert werden, und den Daten im Arbeitsspeicher zu gewährleisten.

    Wenn ein Treiber AllocateCommonBuffer aufruft, wobei der CacheEnabled-Parameter auf TRUE festgelegt ist, muss der Treiber KeFlushIoBuffers aufrufen, bevor er mit einem Übertragungsvorgang zu/aus dem Puffer beginnt.

  2. Rufen Sie FlushAdapterBuffers am Ende jedes Geräteübertragungsvorgangs auf, um sicherzustellen, dass alle verbleibenden Bytes in den Puffern des DMA-Systems in den Arbeitsspeicher oder auf das untergeordnete Gerät geschrieben wurden.

    Oder rufen Sie FlushAdapterBuffers am Ende jedes Übertragungsvorgangs für einen bestimmten IRP auf, um sicherzustellen, dass alle Daten in den Systemspeicher eingelesen oder auf ein Bus-master DMA-Gerät geschrieben wurden.

Die folgende Abbildung zeigt, warum es wichtig ist, den Prozessorcache vor einem Lese- oder Schreibvorgang mithilfe von DMA zu leeren, wenn der Hostprozessor und der DMA-Controller die Cachekohärenz nicht automatisch aufrechterhalten.

Diagramm zur Veranschaulichung von Lese- und Schreibvorgängen mithilfe von dma.

Ein asynchroner DMA-Lese- oder Schreibvorgang greift auf Daten im Arbeitsspeicher und nicht im Prozessorcache zu. Sofern dieser Cache nicht durch Aufrufen von KeFlushIoBuffers kurz vor einem Lesevorgang geleert wurde, können die vom DMA-Vorgang in den Systemspeicher übertragenen Daten mit veralteten Daten überschrieben werden, wenn der Prozessorcache später geleert wird. Sofern der Prozessorcache nicht durch Aufrufen von KeFlushIoBuffers kurz vor einem Schreibvorgang geleert wurde, sind die Daten in diesem Cache möglicherweise aktueller als die Kopie im Arbeitsspeicher.

KeFlushIoBuffers macht nichts, wenn der Prozessor und der DMA-Controller verwendet werden können, um die Cachekohärenz aufrechtzuerhalten, sodass Aufrufe dieser Supportroutine in einer solchen Plattform fast keinen Mehraufwand haben.

Wie auch in der vorherigen Abbildung gezeigt, können DMA-Controller, die durch Adapterobjekte dargestellt werden, über interne Puffer verfügen. Ein solcher DMA-Controller kann zwischengespeicherte Daten in Blöcken mit fester Größe übertragen, in der Regel acht oder mehr Bytes gleichzeitig. Darüber hinaus können diese DMA-Controller vor jedem Übertragungsvorgang warten, bis ihre internen Puffer voll sind.

Betrachten Sie den Fall eines Treibers der niedrigsten Ebene, der untergeordneten DMA verwendet, um Daten in Blöcken variabler Größe oder in Blöcken mit fester Größe zu lesen, die kein integrales Vielfaches der Cachegröße eines System-DMA-Controllers sind. Wenn dieser Treiber am Ende jeder Geräteübertragung FlushAdapterBuffers aufruft , kann er nicht sicher sein, wann jedes byte, das der Treiber tatsächlich angefordert hat, übertragen wird.

Der Treiber eines Bus-master DMA-Geräts sollte auch FlushAdapterBuffers am Ende jedes Übertragungsvorgangs für ein IRP aufrufen, um sicherzustellen, dass alle Daten in den Systemspeicher oder auf das Gerät übertragen wurden.

FlushAdapterBuffers gibt einen booleschen Wert zurück, der angibt, ob der angeforderte Leerungsvorgang erfolgreich war. Ein Treiber kann diesen Wert verwenden, um zu bestimmen, wie der E/A-status-Block festgelegt wird, wenn ein IRP für einen DMA-Lese- oder Schreibvorgang abgeschlossen wird.