Включение комбинируемого доступа ввода-вывода в пользовательском пространстве
У меня есть устройство 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.