Есть несколько частей к этому.
В ARMv7, который включает Zynq-7000, память обозначается как заданный тип атрибутами области памяти, настроенными с помощью дескрипторов таблицы преобразования. Существуют различные способы их настройки, и механизмы описаны в разделе B3.8 архитектуры ARM. Справочное руководство ARMv7-A. Также полезно Zynq техническое справочное руководство., менее полный в отношении ARM, но более простой в обработке.
В широком смысле интерес представляют биты B
(буферизуемый), бит C
(кэшируемый) и 3 бита TEX
(расширение типа). Они могут быть установлены напрямую или через перенаправление, когда установлен бит SCTLR.TRE
(что фактически позволяет пользовательское переназначение с использованием регистров PRRR
и NMRR
- может быть, это еще что-то, но я не могу сразу увидеть что).
Дескрипторы таблицы перевода настраиваются в Linux в подсистеме блока управления памятью (MMU). Это, очевидно, очень специфично для архитектуры, и соответствующие биты ARM находятся в arch. /рука/мм. Интересно полистать mmu.c чтобы увидеть, как разные атрибуты памяти настраиваются для разных типов.
То, что следует ниже, является немного более спекулятивным, но я думаю, что оно является точным.
Драйвер ядра UIO устанавливает соответствующую защиту памяти на физическом устройстве, вызывая pgprot_noncached()
. Теперь я думаю, что это делегировано конкретной реализации архитектуры, которая в случае ARMv7 является макросом, определенным в arch/arm/include/asm/pgtable.h и устанавливает флаг L_PTE_MT_UNCACHED
.
Константа L_PTE_MT_UNCACHED
, в свою очередь, устанавливается в arch/arm/include/asm/pgtable-2level.h. В этом файле есть хорошая документация, описывающая, что представляют собой различные константы. Значение для каждого типа переназначается на биты B
, C
и TEX
либо с помощью перенаправления TRE
, либо с помощью справочной таблицы, настроенной в arch/arm/mm/proc-macros.S. Регистры перенаправления TRE (PRRR
и NMRR
), я думаю, настроены в arch/arm/mm/proc-v7-2level.S. Если вы отследите их, вы получите те же значения, что и в справочной таблице (которая ссылается на константы, определенные в arch/arm/include/asm/pgtable-2level-hwdef.h — обратите внимание, что эти константы предназначены для небольшого дескриптора таблицы страниц. , отличные от используемых в mmu.c
)
Где это оставляет нас? Драйвер UIO, конфигурирующий часть памяти как pgprot_noncached()
, подразумевает, что это L_PTE_MT_UNCACHED
, что, в свою очередь, подразумевает TEX = 000
, B = 0
и C = 0
. Просматривая эти настройки в справочном руководстве, мы видим, что это соответствует небуферизованной, строго упорядоченной, совместно используемой области памяти (обозначается строго типизированной).
Очевидно, что для изменения устройства (возможно, чтобы разрешить буферизованную запись) нам нужно изменить конфигурацию драйвера памяти, чтобы использовать, например. pgprot_writecombine()
, который установит нормальный тип памяти, но с отключенным кешем. Существует также макрос pgprot_device()
, который также настраивает тип памяти устройства (буферизуемая) и отключает кэш, но с некоторыми дополнительными флагами, которые я еще не понял должным образом (думаю, они предназначены для настройки программной Linux-версии записи таблицы страниц для случай, когда аппаратное обеспечение не поддерживает это, поэтому не имеет значения, когда оно поддерживает).
person
Henry Gomersall
schedule
01.12.2020