2014-04-23 18 views
9

Ho un dispositivo PCIe con un driver dello spazio utente. Sto scrivendo comandi al dispositivo tramite una BAR, i comandi sono sensibili alla latenza e la quantità di dati è piccola (~ 64-byte), quindi non voglio usare DMA.Abilitazione dell'accesso IO combina scrittura nello spazio utente

Se rimappare l'indirizzo fisico della BAR nel kernel utilizzando ioremap_wc e poi scrivere 64-byte al bar all'interno del kernel, posso vedere che i 64-byte vengono scritti come un unico TLP su PCIe. Se permetto al mio programma userspace di mmap l'area con il flag MAP_SHARED e poi scrivo 64-byte, vedo più TPL sul bus PCIe, piuttosto che una singola transazione.

Secondo il kernel PAT documentation dovrei essere in grado di esportare le pagine di scrittura-unito fino alla userspace:

driver che vogliono esportare alcune pagine allo userspace farlo utilizzando l'interfaccia mmap e una combinazione di

1) pgprot_noncached()

2) io_remap_pfn_range() o remap_pfn_range() o vm_insert_pfn()

Con il supporto PAT, è stata aggiunta una nuova API pgprot_writecombine. Così, piloti possono continuare a utilizzare la sequenza di cui sopra, sia con pgprot_noncached() o pgprot_writecombine() al punto 1, seguito da passo 2.

Sulla base di questa documentazione, il codice del kernel rilevanti dal mio gestore mmap assomiglia a questo :

vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); 

return io_remap_pfn_range(vma, 
          vma->vm_start, 
          info->mem[vma->vm_pgoff].addr >> PAGE_SHIFT, 
          vma->vm_end - vma->vm_start, 
          vma->vm_page_prot); 

il dispositivo PCIe presenta in lspci con le barre contrassegnati come prefetchable come previsto:

Latency: 0, Cache Line Size: 64 bytes 
    Interrupt: pin A routed to IRQ 11 
    Region 0: Memory at d8000000 (64-bit, prefetchable) [size=32M] 
    Region 2: Memory at d4000000 (64-bit, prefetchable) [size=64M] 

Quando chiamo mmap da userspace vedo un messaggio di log (dopo aver impostato debugpat parametro di avvio del kernel):

reserve_memtype aggiunto [mem 0xd4000000-0xd7ffffff], pista write-combining, req write-combining , ret scrittura che unisce

posso anche vedere in /sys/kernel/debug/x86/pat_memtype_list che una voce di PAT è corretto e non ci sono regioni che si sovrappongono:

write-combining @ 0xd4000000-0xd8000000 
uncached-minus @ 0xd8000000-0xda000000 

Ho anche verificato che non ci siano voci MTRR in conflitto con la configurazione PAT. Per quanto posso vedere, tutto è impostato correttamente affinché la combinazione di scrittura avvenga nello userspace, tuttavia utilizzando un analizzatore PCIe per osservare le transazioni sul bus PCIe, lo schema di accesso allo spazio utente è completamente diverso dalla stessa scrittura eseguita dal kernel dopo una chiamata ioremap_wc.

Perché la combinazione di scrittura non funziona come previsto dallo spazio utente?

Cosa posso fare per eseguire il debug ulteriormente?

Attualmente sono in esecuzione su un singolo socket 6-core i7-3930K.

+0

Qual è l'indirizzo visibile userspace per la gamma? Forse non è allineato correttamente? – wallyk

+0

@wallyk Buon suggerimento ma l'indirizzo visibile dello spazio utente sembra allineato. – Chiggs

risposta

1

Non so se questo sarà d'aiuto, ma è così che ho combinato la scrittura lavorando su PCIe. Certo, era nello spazio del kernel, ma questo è conforme alla documentazione di Intel. Vale la pena provare se sei bloccato.

Globalmente definito:

unsigned int __attribute__ ((aligned(0x20))) srcArr[ARR_SIZE]; 

Nella funzione:

int *pDestAddr 

for (i = 0; i < ARR_SIZE; i++) { 
    _mm_stream_si32(pDestAddr + i, pSrcAddr[i]); 
} 
+0

Grazie per la risposta, ma questo dà lo stesso schema di TLP: Kernel space un singolo TLP a 64 byte, userspace un flusso di singoli TLP. – Chiggs