Rockchip · AI & Linux Hub

Linux и загрузка

Rockchip Linux IOMMU V1/V2: таблицы страниц, DMA и диагностика

Полный китайский V1.2.0: таблицы V2, дамп RK3588, DMA/DRM/system heap и 18 разделов диагностики.

· ArmSoM Editorial · Rockchip source documentation · 16 мин чтения

Применимость к 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

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

Поля 32-битного адреса IOMMU — источник EN PDF p.6

Поля 32-битного адреса IOMMU — источник EN PDF p.6.

32-битный адрес содержит 10-битное смещение в таблице первого уровня, 10-битное смещение второго уровня и 12-битное смещение внутри страницы.

Структура DTE:

Структура DTE IOMMU V1 — источник EN PDF p.6

Структура DTE IOMMU V1 — источник EN PDF p.6.

Структура DTE V2 (китайский исходник V1.2.0):

Структура DTE IOMMU V2 — источник CN PDF p.4

Структура DTE IOMMU V2 — источник CN PDF p.4.

bit0: наличие таблицы страниц следующего уровня.

Структура PTE:

Структура и права PTE IOMMU V1 — источник EN PDF p.7

Структура и права PTE IOMMU V1 — источник EN PDF p.7.

bit0: наличие физической страницы.

bit1: разрешение чтения.

bit2: разрешение записи.

Структура PTE V2 (китайский исходник V1.2.0):

Структура PTE IOMMU V2 — источник CN PDF p.5

Структура 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.

Управление 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

Порядок переключения:

  1. Убедитесь, что все часы включены.
  2. Убедитесь, что все PD включены.
  3. Выключите все IOMMU.
  4. Переключите GRF.
  5. Включите текущую IOMMU.

5.18 Ошибки одновременной работы VPU и HEVC RK3368

VPU и HEVC RK3368 используют общую IOMMU TLB. Операции TLB и отображения должны быть сериализованы, иначе возможны сбои.

Другие статьи по теме → · Учебные маршруты →