Включение комбинируемого доступа ввода-вывода в пользовательском пространстве

У меня есть устройство PCIe с драйвером пользовательского пространства. Я пишу команды на устройство через BAR, команды чувствительны к задержке и объем данных невелик (~ 64 байта), поэтому я не хочу использовать DMA.

Если я переназначить физический адрес BAR в ядре, используяioremap_wc а затем записать 64 байта в барвнутри ядраЯ вижу, что 64 байта записаны как один TLP через PCIe. Если я позволю моей программе пользователяmmap регион сMAP_SHARED флаг и затем записать 64 байта я вижу несколько TPL на шине PCIe, а не одну транзакцию.

По словам ядраPAT документация Я должен быть в состоянии экспортировать комбинированные записи записи через пользовательское пространство:

Драйверы, желающие экспортировать некоторые страницы в пользовательское пространство, делают это с помощью интерфейса mmap и комбинации

1)pgprot_noncached()

2)io_remap_pfn_range() или жеremap_pfn_range() или жеvm_insert_pfn()

С поддержкой PAT новый APIpgprot_writecombine добавляется. Таким образом, драйверы могут продолжать использовать вышеуказанную последовательность, либоpgprot_noncached() или жеpgprot_writecombine() на шаге 1, затем шаг 2.

Основываясь на этой документации, соответствующий код ядра из моего обработчика mmap выглядит так:

 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);

Мое устройство PCIe отображается в lspci с BAR, помеченными как предварительно выбранные, как и ожидалось:

    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]

Когда я звонюmmap из пространства пользователя я вижу сообщение журнала (установив параметр загрузки ядра debugpat):

добавлен Reserve_memtype [mem 0xd4000000-0xd7ffffff], объединение записи трека, объединение записи req, объединение повторной записи

Я также могу видеть в/sys/kernel/debug/x86/pat_memtype_list что запись PAT выглядит правильно и нет перекрывающихся областей:

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

Я также проверил, что нет записей MTRR, которые будут конфликтовать с конфигурацией PAT. Насколько я вижу, все настроено правильно для объединения записи в пользовательском пространстве, однако при использовании анализатора PCIe для наблюдения за транзакциями на шине PCIe шаблон доступа в пользовательском пространстве полностью отличается от той же записи, выполняемой из ядра послеioremap_wc вызов.

Почему объединение записей не работает так, как ожидается от пользовательского пространства?

Что я могу сделать для дальнейшей отладки?

В настоящее время я работаю на одном сокете 6-ядерный i7-3930K.

Ответы на вопрос(1)

Ваш ответ на вопрос