Применимость к ArmSoM и область исходника
Справочный материал для адаптации ArmSoM на основе CN V1.2.0 baseline; EN V1.0.1 comparison. Сочетания платы, SDK/BSP, ядра и соединений аппаратно не проверялись. Область исходника ниже не означает поддержку каждой платой ArmSoM либо каждым ядром. Проверьте SoC, схему, SDK/BSP, драйвер и pinmux. Команды, патчи, журналы и измерения взяты из исходника и не являются тестами ArmSoM.
По подтверждению пользователя все языки следуют китайскому V1.2.0: добавлены отсутствующие в EN V1.0.1 структуры V2, дамп RK3588, system heap и FAQ 5.9–5.18 с китайскими страницами источника. Для четырёх общих рисунков английская и русская версии используют английские оригиналы; два рисунка V2 взяты из китайского, поскольку английских нет. Старый английский текст использует && вместо китайского &; применён китайский вариант, оба зафиксированы в примечаниях.
| SoC исходника | Ядра по исходнику |
|---|---|
| ROCKCHIP | 4.4/4.19/5.10/6.1 |
IOMMU преобразует 32-битные виртуальные адреса в физические, содержит биты разрешения чтения/записи и формирует исключения отсутствия страницы и ошибки шины.
Редакционные примечания · ArmSoM documentation · Rockchip Linux
1. Структура IOMMU
Используется двухуровневая таблица страниц:

Двухуровневая таблица IOMMU — источник EN PDF p.6.

Поля 32-битного адреса IOMMU — источник EN PDF p.6.
32-битный адрес содержит 10-битное смещение в таблице первого уровня, 10-битное смещение второго уровня и 12-битное смещение внутри страницы.
Структура DTE:

Структура DTE IOMMU V1 — источник EN PDF p.6.
Структура DTE V2 (китайский исходник V1.2.0):

Структура DTE IOMMU V2 — источник CN PDF p.4.
bit0: наличие таблицы страниц следующего уровня.
Структура PTE:

Структура и права PTE IOMMU V1 — источник EN PDF p.7.
bit0: наличие физической страницы.
bit1: разрешение чтения.
bit2: разрешение записи.
Структура PTE V2 (китайский исходник V1.2.0):

Структура PTE IOMMU V2 — источник CN PDF p.5.
Предыдущий текст V1 указывает bit1=чтение и bit2=запись, но рисунок V2 подписывает bit2=read permission и bit1=write permission (bit0=page present). Расхождение версий сохранено по исходнику. Не переносите права V1 на V2 без проверки соответствующего драйвера/TRM; аппаратная проверка не проводилась.
2. Драйвер IOMMU
2.1 Файл драйвера
Расположение файла драйвера:
drivers/iommu/rockchip-iommu.c
2.2 Настройка узла DTS
Описание настройки DTS находится в Documentation/devicetree/bindings/iommu/rockchip,iommu.txt. Основные параметры:
compatible = "rockchip,iommu";
compatible = "rockchip,iommu-v2"; — V2, из китайского исходника V1.2.0.
Исходник указывает общее значение compatible для IOMMU устройств и приводит interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>; для исключений, например page fault. Пример сохранён; проверьте его по binding конкретного DTS, учитывая два compatible для V1/V2 выше.
clocks = <&cru ACLK_VOP1>, <&cru HCLK_VOP1>;
clock-names = "aclk", "hclk"; — IOMMU и master используют общие часы; записи позволяют драйверу IOMMU отдельно управлять ими.
power-domains = <&power RK3399_PD_VOPL>; — позволяет драйверу IOMMU управлять доменом питания.
iommu-cells = <0>; — исходник требует 0, см. iommu.txt. Написание без # сохранено как сомнительное место исходника.
3. Использование IOMMU
Драйвер Rockchip IOMMU зависит от инфраструктуры IOMMU:
drivers/iommu/iommu.c
В основном он реализует обратные вызовы в:
struct iommu_ops rk_iommu_ops
Master управляет IOMMU через API инфраструктуры:
1. iommu attach
iommu_attach_device -> rk_iommu_attach_device /* enable iommu */
2. iommu detach
iommu_detach_device -> rk_iommu_detach_device /* disable iommu */
3. iommu map
iommu_map -> rk_iommu_map
Создаёт таблицы страниц и соответствие виртуальных и физических адресов. Для отладки включите dbg-вывод внутри iommu_map и наблюдайте отображение.
4. iommu unmap
iommu_unmap -> rk_iommu_unmap
Удаляет отображения виртуальных адресов на физические и освобождает виртуальное пространство. Включите dbg внутри iommu_unmap для наблюдения.
5. domain alloc
iommu_domain_alloc -> rk_iommu_domain_alloc
Выделяет базовый адрес таблицы страниц для attach/detach.
6. domain free
iommu_domain_free -> rk_iommu_domain_free
Освобождает пространство таблиц страниц.
7. Дамп таблиц IOMMU. Для RK3399 vopl_iommu и виртуального адреса VA=0x00001000 выполните следующую последовательность. a. Получите базу первого уровня DT:
io -4 0xff8f3f00
b. Вычислите смещение первого уровня:
index1 = VA >> 22
c. Вычислите физический адрес записи первого уровня DTE:
DTE = index1 * 4 + DT
d. Получите базу второго уровня PT:
PT = io -4 DTE
e. Вычислите смещение второго уровня:
index2 = VA & 0x3ff000
f. Вычислите физический адрес записи второго уровня PTE:
PTE = index2 * 4 + PT
g. Получите физический адрес страницы page:
page = io -4 PTE
h. Вычислите адрес с внутристpаничным смещением offset:
offset = page + (VA & 0xfff)
Исходник называет offset физическим адресом, соответствующим 0x00001000; master может проверить данные по нему. Китайский V1.2.0 добавляет следующую последовательность для RK3588 vop_mmu с VA=0x00001000. a. Получите базу первого уровня DT:
DT = io -4 0xfdd97e00
DT = ((DT & 0xf0) << 32) | ((DT & 0xf00) << 24) | (DT & 0xfffff000)
b. Вычислите смещение первого уровня:
index1 = VA >> 22
c. Вычислите физический адрес DTE:
DTE = index1 * 4 + DT
d. Получите базу таблицы второго уровня PT:
PT = io -4 DTE
PT = ((PT & 0xf0) << 32) | ((PT & 0xf00) << 24) | (PT & 0xfffff000)
e. Вычислите смещение второго уровня:
index2 = VA & 0x3ff000
f. Вычислите физический адрес PTE:
PTE = index2 * 4 + PT
g. Получите физический адрес страницы page:
page = io -4 PTE
page = ((page & 0xf0) << 32) | ((page & 0xf00) << 24) | (page & 0xfffff000)
h. Вычислите offset:
offset = page + (VA & 0xfff)
Исходник называет offset физическим адресом, соответствующим VA=0x00001000; master может проверить данные. Формулы воспроизведены буквально и не проверялись на оборудовании.
8. dma-mapping. a. Для устройства без IOMMU:
ARM32: dev->dma_ops = arm_dma_ops;
ARM64: dev->dma_ops = arm64_swiotlb_dma_ops;
b. Для устройства с IOMMU:
ARM32: dev->dma_ops = iommu_ops;
ARM64: dev->dma_ops = iommu_dma_ops;
На примере dma_alloc_attrs:
1. Для устройства без IOMMU alloc из dma_ops пункта (a) выделяет непрерывную физическую память и виртуальный адрес ядра.
2. Для устройства с IOMMU alloc из dma_ops пункта (b) выделяет физическую память и через инфраструктуру вызывает iommu_map для создания таблиц и отображений. Возвращаются начальный виртуальный адрес IOMMU и виртуальный адрес ядра.
Минимальная последовательность использования IOMMU:
1. domain = iommu_domain_alloc(&platform_bus_type);
2. iommu_map(domain, iova, paddr, size, prot);
3. iommu_attach_device(domain, dev);
4. master启动访问iommu
IOMMU — базовый компонент, который встраивается в распределители памяти, например ion/drm. Полная последовательность выделения и отображения буфера в ARM64 DRM:
rockchip_gem_alloc_buf ->
rockchip_gem_get_pages ->
rockchip_gem_iommu_map ->
iommu_map_sg ->
iommu_map
Отображение IOMMU при передаче fd:
Путь DRM:
1. struct dma_buf *dmabuf = dma_buf_get(fd) ->
dma_buf_attach -> dma_buf_map_attachment ->
map_dma_buf -> drm_gem_map_dma_buf ->
dma_map_sg_attrs -> map_sg ->
__iommu_map_sg_attrs ->
iommu_dma_map_sg ->
iommu_map_sg ->
iommu_map
Путь SYSTEM HEAP:
2. struct dma_buf *dmabuf = dma_buf_get(fd) ->
dma_buf_attach -> dma_buf_map_attachment ->
map_dma_buf -> system_heap_map_dma_buf ->
dma_map_sgtable -> __dma_map_sg_attrs ->
map_sg -> iommu_dma_map_sg ->
iommu_map_sg_atomic ->
__iommu_map_sg ->
__iommu_map
4. Конфигурация ядра
Symbol: ROCKCHIP_IOMMU [=y]
Type : boolean
Prompt: Rockchip IOMMU Support
Location:
-> Device Drivers
-> IOMMU Hardware Support (IOMMU_SUPPORT [=y])
Defined at drivers/iommu/Kconfig:211
Depends on: IOMMU_SUPPORT [=y] && (ARM || ARM64 [=y]) && (ARCH_ROCKCHIP [=y] ||
COMPILE_TEST [=n])
Selects: IOMMU_API [=y] && ARM_DMA_USE_IOMMU
5. Частые вопросы по IOMMU
5.1 Прерывание page fault
Page fault означает отсутствие отображения для текущего виртуального адреса. В master встречались три причины: доступ к уже unmapped-адресу, выход за границы и начало доступа до map.
5.2 Ошибка iommu enable stall
Возможно, IOMMU уже выдала page fault, но master продолжает доступ без обработки ошибки; проверьте журнал.
Другая причина — неверное управление CLK. Для проверки временно оставьте PD и CLK включёнными.
5.3 Недоступны регистры IOMMU
Master может неправильно использовать pm_runtime_get_sync/pm_runtime_put_sync и обращаться к регистрам до включения домена питания IOMMU.
5.4 Непрерывные прерывания IOMMU
В DTS может быть указан неверный номер прерывания.
Master может непрерывно обращаться к неотображённой IOVA; это часто наблюдается при сбоях дисплея.
5.5 Мерцание при загрузке
Включение IOMMU во время вывода VOP может нарушить выборку данных. На SoC без применения по границе кадра включайте IOMMU, когда VOP не выполняет выборку.
5.6 Неверные значения регистров IOMMU
Причиной может быть выход master за границы регистров IOMMU.
Сброс всего IP master также сбрасывает IOMMU, встроенную в этот IP.
После сброса master восстановите настройки регистров IOMMU.
5.7 Интеграция IOMMU с device link
Управление PD передаётся master; правильно используйте pm_runtime_get/pm_runtime_put.
Вызов pm_runtime_get в master включает IOMMU.
Вызов pm_runtime_put в master выключает IOMMU.
5.8 Обслуживание таблиц страниц
В ARM32 master, совместно использующие IOMMU, например vepu и vdpu, должны иметь отдельные таблицы и выполнять attach перед каждым доступом. В ARM64 таблицы общие, повторный attach не нужен.
5.9 Сброс при высокой тактовой частоте
При стресс-тесте перезагрузки RK3288 возможен VOP page fault. При разгоне VOP операция force reset IOMMU может завершиться некорректно. Исходный workaround — пропустить force reset при attach VOP IOMMU.
5.10 Нельзя читать VOP IOMMU RK3128/RK3126
Регистры VOP IOMMU этих SoC нельзя читать. Добавьте в DTS следующий workaround:
rockchip,skip-mmu-read
Драйвер пропускает соответствующие чтения; флаг — iommu->skip_read.
5.11 Операция reset
После сброса ISP IOMMU регистр состояния может не подтверждать завершение, хотя сброс выполнен. Добавьте workaround в узел DTS ISP IOMMU:
rockchip,disable-mmu-reset
Это отключает reset ISP IOMMU; флаг драйвера — iommu->reset_disabled.
5.12 Выполнение команд записи
Исходник указывает, что rkvenc IOMMU RK1126 и RV1109 может терять команды записи; рекомендуется повторять запись несколько раз. Написание RK1126 сохранено и требует проверки.
5.13 Отключение автоматического attach VOP IOMMU
Начиная с ядра 4.19 VOP сама выполняет attach IOMMU вместо автоматического attach при регистрации узла, чтобы избежать ошибок вывода при переходе от U-Boot к ядру.
5.14 Потеря производительности при очистке IOMMU TLB
Отображение требует очистки TLB. Фрагментированный буфер вызывает множество очисток и снижает производительность; флаг позволяет выполнить очистку только один раз.
5.15 Отображение один-к-одному для VOP IOMMU
Отображение один-к-одному позволяет избежать ошибок при ожидании применения кадра во время перехода U-Boot/ядро. Например, в RK356X master больше, чем IOMMU, и ожидание применения кадра недоступно; тождественное отображение обходит проблему.
5.16 Один master и две IOMMU
Если нет особых требований, настройте драйвер master так, чтобы обе IOMMU использовали одну таблицу страниц.
Описанный в исходнике новый драйвер автоматически использует общую таблицу для нескольких IOMMU одного master; вмешательство драйвера master не требуется.
5.17 Переключение H.264/H.265 на PX30
Порядок переключения:
- Убедитесь, что все часы включены.
- Убедитесь, что все PD включены.
- Выключите все IOMMU.
- Переключите GRF.
- Включите текущую IOMMU.
5.18 Ошибки одновременной работы VPU и HEVC RK3368
VPU и HEVC RK3368 используют общую IOMMU TLB. Операции TLB и отображения должны быть сериализованы, иначе возможны сбои.
