2011-08-20 17 views
19

La mia domanda è questa: come posso determinare quando è possibile disabilitare lo snooping della cache quando sto usando correttamente [pci_]dma_sync_single_for_{cpu,device} nel mio driver di periferica?Gestione della coerenza della cache DMA

Sto lavorando a un driver di periferica per un dispositivo che scrive direttamente su RAM su PCI Express (DMA) e sono preoccupato per la gestione della coerenza della cache. C'è un bit di controllo che posso impostare quando si avvia DMA per abilitare o disabilitare il snooping della cache durante il DMA, chiaramente per le prestazioni vorrei lasciare il snooping della cache disabilitato se possibile.

Nella routine di interrupt chiamo pci_dma_sync_single_for_cpu() e ..._for_device() come appropriato, quando si passano i buffer DMA, ma su Linux a 32 bit 2.6.18 (RHEL 5) si scopre che questi comandi sono macro che si espandono a nulla ... quale spiega perché il mio dispositivo restituisce garbage quando lo snooping della cache è disabilitato su questo kernel!

Ho esplorato la cronologia dei sorgenti del kernel e sembra che fino alla 2.6.25 solo x86 a 64 bit disponesse di hook per la sincronizzazione DMA. Dal 2.6.26 sembra esserci un meccanismo generico unificato di riferimento indiretto per la sincronizzazione DMA (attualmente in include/asm-generic/dma-mapping-common.h) tramite i campi sync_single_for_{cpu,device} di dma_map_ops, ma finora non sono riuscito a trovare alcuna definizione di queste operazioni.

+0

Ci sono stati alcuni articoli LWN su DMA e la coerenza della cache si potrebbe voler guardare in giro su lwn.net – Spudd86

+1

Hai misurato le prestazioni guadagno che si ottiene disattivando la cache snooping , non solo sul trasferimento stesso ma sull'applicazione in generale? La coerenza di DMA è così conveniente e rende molto più semplice pensare all'interazione con l'hardware che vorrei misurare con attenzione prima di spegnerlo. –

risposta

15

Sono davvero sorpreso nessuno ha risposto a questa, così qui andiamo su una risposta specifica non-Linux (ho insufficiente conoscenza del kernel di Linux per essere più precisi) ...

snooping Cache indica semplicemente al controller DMA di inviare richieste di invalidazione della cache a tutte le CPU per la memoria in cui viene inserito DMA. Ciò ovviamente aggiunge carico al bus di coerenza della cache, e si adatta in modo particolarmente grave con processori aggiuntivi, poiché non tutte le CPU avranno una connessione hop singolo con il controller DMA che emette lo snoop. Pertanto, la semplice risposta a "quando è sicuro disabilitare lo snooping della cache" è quando la memoria che si trova in DMA non esiste in alcuna cache della CPU O le sue linee della cache sono contrassegnate come non valide. In altre parole, qualsiasi tentativo di leggere dalla regione DMAed sarà sempre risultato in una lettura dalla memoria principale.

Quindi, come assicurate che le letture da un'area DMAed andranno sempre alla memoria principale?

Indietro nel giorno prima abbiamo avuto caratteristiche di fantasia come la DMA di cache snooping, quello che abbiamo usato per fare era di gasdotto di memoria DMA alimentando attraverso una serie di fasi interrotte come segue:

Fase 1: Aggiungi " dirty "DMA memory region alla lista di memoria DMA" dirty and needs to be clean ".

Fase 2: la prossima volta che il dispositivo si interrompe con nuovi dati DMA, emette una cache locale asincrona della cache invalida per i segmenti DMA nell'elenco "sporchi e deve essere pulito" per tutte le CPU che potrebbero accedere a tali blocchi (spesso ogni CPU esegue le proprie liste composte da blocchi di memoria locali). Sposta i suddetti segmenti in una lista "pulita".

Fase 3: Prossimo interrupt DMA (che naturalmente non si verificherà prima che la cache precedente sia stata annullata), prelevare una nuova regione dall'elenco "pulito" e comunicare al dispositivo che il prossimo DMA dovrebbe andare in quello Ricicla eventuali blocchi sporchi.

Fase 4: ripetizione.

Tanto più che questo è più lavoro, presenta diversi importanti vantaggi. Innanzitutto, è possibile collegare la gestione DMA a una singola CPU (in genere la CPU primaria0) oa un singolo nodo SMP, il che significa che solo una singola CPU/nodo deve preoccuparsi dell'invalidazione della cache.In secondo luogo, si offre al sottosistema di memoria molte più possibilità di nascondere le latenze della memoria per voi distanziando le operazioni nel tempo e distribuendo il carico sul bus di coerenza della cache. La chiave per le prestazioni è in genere quella di provare a eseguire qualsiasi DMA su una CPU il più vicino possibile al controller DMA pertinente e in memoria il più vicino possibile a quella CPU.

Se si sempre consegnare nuovamente DMA in memoria nello spazio utente e/o in altre CPU, è sufficiente iniettare memoria appena acquisita nella parte anteriore della pipeline invalidante della cache asincrona. Alcuni sistemi operativi (non sono sicuro di Linux) hanno una routine ottimizzata per il preordinamento della memoria azzerata, quindi il sistema operativo zera la memoria in background e mantiene una cache di soddisfazione rapida - ti pagherà per mantenere nuove richieste di memoria al di sotto di quella cache perché azzeramento della memoria è estremamente lento. Non sono a conoscenza di alcuna piattaforma prodotta negli ultimi dieci anni che utilizza l'azzeramento della memoria dell'hardware scaricato, quindi è necessario presumere che tutta la nuova memoria possa contenere linee di cache valide che devono essere invalidate.

Apprezzo che questo risponda solo a metà della tua domanda, ma è meglio di niente. In bocca al lupo!

Niall

4

Forse un po 'in ritardo, ma:

Se si disattiva la cache snooping, hardware sarà più prendere cura di coerenza della cache. Quindi, il kernel ha bisogno di farlo da solo. Negli ultimi giorni, ho passato qualche tempo a rivedere le varianti X86 di [pci_] dma_sync_single_for_ {cpu, device}. Non ho trovato alcuna indicazione che compiano sforzi per mantenere la coerenza. Ciò sembra coerente con il fatto che lo snooping della cache è attivato di default nelle specifiche PCI (e).

Quindi, se si spegne lo snooping della cache, si dovrà mantenere la coerenza da soli, nel driver. Forse chiamando clflush_cache_range() (X86) o simili?

Refs:

Problemi correlati