Rockchip · AI & Linux Hub

Linux & boot

Rockchip Linux IOMMU V1/V2: Page Tables, DMA Mapping and Troubleshooting

Complete Chinese V1.2.0 baseline with V2 page tables, RK3588 dumps, DMA/DRM/system heap and all 18 FAQ sections.

· ArmSoM Editorial · Rockchip source documentation · 17 min read

ArmSoM applicability and source scope

Platform reference for adapting ArmSoM systems, based on CN V1.2.0 baseline; EN V1.0.1 comparison. No board, SDK/BSP, kernel or wiring combination has been hardware-validated here. The source scope below is not a claim that every ArmSoM board or kernel supports these features. Check the exact SoC, board schematic, SDK/BSP, kernel driver and pinmux. Commands, patches, logs and measurements are source examples, not ArmSoM test results.

By user approval, all languages follow Chinese V1.2.0, including V2 layouts, RK3588 page dumps, system-heap mapping and FAQ 5.9–5.18 missing from EN V1.0.1. Additions retain Chinese source-page comments. English/Russian use matching English originals for the four common figures; the two V2 figures use Chinese originals because no English equivalent was supplied. The older English formulas use && where Chinese uses &; the baseline uses Chinese literals, with both variants recorded in the notes.

Source SoC Source kernel scope
ROCKCHIP 4.4/4.19/5.10/6.1

IOMMU translates 32-bit virtual addresses to physical addresses, provides read/write permission bits and can raise page-fault and bus-exception interrupts.

Editorial notes · ArmSoM documentation · Rockchip Linux

1. IOMMU structure

A two-level page-table structure is used:

IOMMU two-level page-table structure — source EN PDF p.6

IOMMU two-level page-table structure — source EN PDF p.6.

32-bit IOMMU virtual address fields — source EN PDF p.6

32-bit IOMMU virtual address fields — source EN PDF p.6.

The 32-bit address contains a 10-bit first-level table offset, a 10-bit second-level table offset and a 12-bit offset within the page.

DTE structure:

IOMMU V1 DTE layout — source EN PDF p.6

IOMMU V1 DTE layout — source EN PDF p.6.

V2 DTE structure (Chinese V1.2.0 source):

IOMMU V2 DTE layout — source CN PDF p.4

IOMMU V2 DTE layout — source CN PDF p.4.

bit0: whether the next-level page table exists.

PTE structure:

IOMMU V1 PTE layout and permissions — source EN PDF p.7

IOMMU V1 PTE layout and permissions — source EN PDF p.7.

bit0: whether the physical page exists.

bit1: read permission.

bit2: write permission.

V2 PTE structure (Chinese V1.2.0 source):

IOMMU V2 PTE layout — source CN PDF p.5

IOMMU V2 PTE layout — source CN PDF p.5.

The preceding V1 text says bit1=read and bit2=write, but the V2 diagram labels bit2=read permission and bit1=write permission (bit0=page present). This version-specific discrepancy is preserved exactly as shown. Do not apply V1 permissions to V2 without checking the matching driver/TRM; no hardware validation was performed.

2. IOMMU driver

2.1 Driver file

Driver file location:

drivers/iommu/rockchip-iommu.c

2.2 DTS node configuration

Refer to Documentation/devicetree/bindings/iommu/rockchip,iommu.txt for DTS configuration. The main parameters are described below:

compatible = "rockchip,iommu";

compatible = "rockchip,iommu-v2"; — V2, from the Chinese V1.2.0 source.

The source states that the compatible value is shared by the IOMMUs of devices. It lists interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>; for exception interrupts such as page faults. Preserve this example and verify it against the actual DTS binding; the source has both V1 and V2 compatible strings above.

clocks = <&cru ACLK_VOP1>, <&cru HCLK_VOP1>;

clock-names = "aclk", "hclk"; — IOMMU and master share clocks; these entries allow the IOMMU driver to control the clocks independently.

power-domains = <&power RK3399_PD_VOPL>; — enables power-domain operations in the IOMMU driver.

iommu-cells = <0>; — the source requires 0; see iommu.txt. The missing # in this source spelling is retained and flagged in the editorial notes.

3. Using IOMMU

The Rockchip IOMMU driver depends on the IOMMU framework:

drivers/iommu/iommu.c

It mainly implements callbacks in:

struct iommu_ops rk_iommu_ops

The master invokes the framework APIs to operate the IOMMU, as follows:

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

Create page tables and mappings between virtual and physical addresses. Enable the dbg output inside iommu_map during debugging to observe mapping.

4. iommu unmap

iommu_unmap -> rk_iommu_unmap

Remove virtual-to-physical mappings and free virtual address space. Enable dbg output inside iommu_unmap to observe unmapping.

5. domain alloc

iommu_domain_alloc -> rk_iommu_domain_alloc

Allocate the page-table base address used by attach/detach.

6. domain free

iommu_domain_free -> rk_iommu_domain_free

Free page-table space.

7. Dump IOMMU page tables. For RK3399 vopl_iommu and virtual address VA=0x00001000, use this sequence. a. Obtain the first-level table base DT:

io -4 0xff8f3f00

b. Calculate the first-level table offset:

index1 = VA >> 22

c. Calculate the physical address of the first-level entry DTE:

DTE = index1 * 4 + DT

d. Obtain the second-level table base PT:

PT = io -4 DTE

e. Calculate the second-level table offset:

index2 = VA & 0x3ff000

f. Calculate the physical address of the second-level entry PTE:

PTE = index2 * 4 + PT

g. Obtain the physical PAGE address, page:

page = io -4 PTE

h. Calculate the in-page offset, offset:

offset = page + (VA & 0xfff)

The source calls offset the physical address corresponding to virtual address 0x00001000; the master can inspect data there. For RK3588 vop_mmu with VA=0x00001000, the Chinese V1.2.0 source adds the following sequence. a. Obtain the first-level table base DT:

DT = io -4 0xfdd97e00
DT = ((DT & 0xf0) << 32) | ((DT & 0xf00) << 24) | (DT & 0xfffff000)

b. Calculate the first-level table offset:

index1 = VA >> 22

c. Calculate physical address DTE:

DTE = index1 * 4 + DT

d. Obtain second-level table base PT:

PT = io -4 DTE
PT = ((PT & 0xf0) << 32) | ((PT & 0xf00) << 24) | (PT & 0xfffff000)

e. Calculate the second-level table offset:

index2 = VA & 0x3ff000

f. Calculate physical address PTE:

PTE = index2 * 4 + PT

g. Obtain physical page address page:

page = io -4 PTE
page = ((page & 0xf0) << 32) | ((page & 0xf00) << 24) | (page & 0xfffff000)

h. Calculate offset:

offset = page + (VA & 0xfff)

The source calls offset the physical address corresponding to VA=0x00001000; the master can use it to inspect data. The formulas are reproduced literally and have not been validated on hardware.

8. dma-mapping. a. For a device without IOMMU:

ARM32: dev->dma_ops = arm_dma_ops;
ARM64: dev->dma_ops = arm64_swiotlb_dma_ops;

b. For an IOMMU device:

ARM32: dev->dma_ops = iommu_ops;
ARM64: dev->dma_ops = iommu_dma_ops;

Taking dma_alloc_attrs as an example:

1. For a non-IOMMU device, the alloc callback in the dma_ops from (a) allocates contiguous physical memory and a kernel virtual address.

2. For an IOMMU device, alloc in the dma_ops from (b) allocates physical memory and invokes iommu_map through the framework to create page tables and virtual-to-physical mappings. It returns the initial IOMMU virtual address and the kernel virtual address.

A minimal IOMMU usage sequence:

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 is a basic component that can be embedded in allocators such as ion/drm. In ARM64 DRM, a complete IOMMU buffer allocation and mapping sequence is:

rockchip_gem_alloc_buf ->
rockchip_gem_get_pages ->
rockchip_gem_iommu_map ->
iommu_map_sg ->
iommu_map

IOMMU mapping when passing an fd:

DRM path:

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 path:

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. Kernel configuration

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 frequently asked questions

5.1 Page-fault interrupt

A page-fault interrupt means that the virtual address currently accessed has no corresponding mapping. Three cases have occurred in masters: accessing an unmapped address, accessing out of bounds, or starting access before mapping.

5.2 IOMMU enable-stall failure

An IOMMU page fault may already have occurred and the master continues accessing without handling it; inspect the log.

Incorrect clock handling is another possibility. Temporarily keep PD and CLK enabled to rule out those causes.

5.3 Inaccessible IOMMU registers

The master’s power-domain handling may use pm_runtime_get_sync/pm_runtime_put_sync incorrectly, accessing IOMMU registers before enabling the IOMMU power domain.

5.4 Continuous IOMMU interrupts

The interrupt number in DTS may be wrong.

The master may continuously access unmapped IOVA; this often accompanies display failures.

5.5 Boot-time display flicker

Enabling IOMMU while VOP is displaying may disrupt data fetching. On chips without frame-effective switching, wait until VOP is not fetching before enabling IOMMU.

5.6 Abnormal IOMMU registers

Out-of-bounds master accesses to IOMMU registers can cause this problem.

Resetting the entire master IP also resets IOMMU, because IOMMU is integrated inside that IP.

After a master reset, restore the IOMMU register configuration.

Power-domain control is handed to the master; ensure correct use of pm_runtime_get/pm_runtime_put.

Calling pm_runtime_get in the master enables IOMMU.

Calling pm_runtime_put in the master disables IOMMU.

5.8 Page-table maintenance

In ARM32, masters sharing IOMMU, such as vepu and vdpu, need separate page tables and must attach the appropriate table before every access. ARM64 shares page tables, so repeated attach is unnecessary.

5.9 Reset failure at high clock frequency

RK3288 reboot stress tests can trigger VOP page faults. If VOP is overclocked, force reset of VOP IOMMU may fail. The source workaround is to skip force reset when attaching VOP IOMMU.

5.10 Unreadable VOP IOMMU on RK3128/RK3126

These chips’ VOP IOMMU registers cannot be read. Add this workaround to the VOP IOMMU DTS configuration:

rockchip,skip-mmu-read

The driver skips the relevant reads; its flag is iommu->skip_read.

5.11 Reset operation

After resetting ISP IOMMU, its status register may not confirm completion even though reset succeeded. Add this workaround to the ISP IOMMU DTS node:

rockchip,disable-mmu-reset

This skips ISP IOMMU reset; the driver flag is iommu->reset_disabled.

5.12 Ensuring write commands take effect

The source names RK1126 and RV1109 rkvenc IOMMU as possibly losing write commands; repeat writes several times to avoid this. RK1126 is preserved as written and requires verification.

5.13 Disable automatic VOP IOMMU attach

From the 4.19 kernel onward, VOP explicitly attaches IOMMU rather than attaching automatically when the device node is registered, preventing display problems at the U-Boot-to-kernel handover.

5.14 Performance loss from IOMMU TLB flushing

Mapping requires TLB flushes. Fragmented buffers can cause many flushes and reduce performance; add a flag so the TLB is flushed only once.

5.15 One-to-one mapping for VOP IOMMU

One-to-one mapping avoids display faults caused by waiting for frame-effective updates at the U-Boot/kernel transition. For example, RK356X has more masters than IOMMUs, so waiting for frame-effective updates is unavailable; identity mapping avoids that problem.

5.16 One master with two IOMMUs

Unless special requirements apply, optimize the master driver so both IOMMUs use the same page table.

The source’s newer IOMMU driver automatically shares the same page table across multiple IOMMUs of one master; no master-driver intervention is needed.

5.17 PX30 H.264/H.265 switching

Use this switching order:

  1. Ensure all clocks are enabled.
  2. Ensure all power domains are enabled.
  3. Disable all IOMMUs.
  4. Switch GRF.
  5. Enable the current IOMMU.

5.18 RK3368 VPU and HEVC simultaneous-operation failures

RK3368 VPU and HEVC share an IOMMU TLB. Serialize TLB operations, and therefore mapping operations, to prevent failures.

Explore this topic → · Learning paths →