FreeBSD 15.0 ARM64 Display Freeze on Rockchip RK3568 - VOP2 Driver Issue

Mario Marietto <[email protected]> Thu, 12 Mar 2026 00:47:36 +0100
Newsgroups gmane.os.freebsd.devel.hackers,gmane.os.freebsd.devel.arm
Message-ID <CA+1FSijDOW3NaLTgxyrseH+CcbVp8PBi9HB=kB=kP1hCsF_j8g@mail.gmail.com>
Hello FreeBSD developers,

I need some help from you for the problem explained below,very thanks.

 ## Hardware & System

 - **Board**: Radxa Zero 3W (ARM64)
 - **SoC**: Rockchip RK3568

 - **GPU**: Mali-G52 (Panfrost driver)
 - **Display Controller**: VOP2 (Video Output Processor 2)
 - **OS**: FreeBSD 15.0-RELEASE-p3 (releng/15.0-n281008-5cf7232732d5)
 - **Kernel**: Custom RK356X-UNIFIED-KEYBOARD-FIX

 ## Problem Description

 ### Primary Issue
 Screen freezes permanently during VT (Virtual Terminal) driver switch from
`efifb` to `fb` (DRM framebuffer) at boot. Last visible
 message:
 rk_vop20: VOP2 version: 40158023

 ### System Behavior
 - ✓ System boots completely (confirmed via SSH access)
 - ✓ Keyboard input works (dmesg shows keypresses via SSH)
 - ✓ DRM modules load successfully (drm.ko, panfrost.ko, rockchipdrm.ko)
 - ✓ `/dev/dri/card1` (Panfrost GPU) and `/dev/dri/card2` (Rockchip
display) created
 - ✗ **Screen updates stop permanently** after "rk_vop20: VOP2 version"
message
 - ✗ No display refresh, VT console frozen

 ### Root Cause Analysis
 Issue introduced in **FreeBSD 15.0** VM subsystem changes:
 - Changed from `vm_page_lookup()` / `vm_page_insert()` to
`vm_radix_iter_lookup()` / `vm_page_iter_insert()`
 - Affects TTM (Translation Table Maps) buffer object page fault handling
 - **FreeBSD 14.2 works perfectly** with identical hardware/configuration
 - Cache coherency issues on ARM64 suspected due to VM changes

 ## Attempted Solutions (All Failed)

 ### 1. TTM Cache Flush Patch (kernel-v26)
 **File**: `sys/dev/drm2/ttm/ttm_bo_vm.c`
 **Approach**: Added full page cache flush (4KB) in `ttm_bo_vm_fault()`
after page mapping
 ```c
 #ifdef __aarch64__
 {
     vm_paddr_t pa = VM_PAGE_TO_PHYS(m);
     vm_offset_t va = PHYS_TO_DMAP(pa);
     vm_offset_t va_end = va + PAGE_SIZE;
     vm_offset_t addr;
     for (addr = va; addr < va_end; addr += 64) {
         __asm __volatile("dc civac, %0" : : "r" (addr) : "memory");
     }
     __asm __volatile("dsb sy" : : : "memory");
 }
 #endif
 Result: ✗ No effect. Screen still frozen.
 Reason: Page faults only happen during initial mapping, not during
rendering.

 2. VT Layer Cache Flush (kernel-v27)

 File: sys/dev/vt/hw/fb/vt_fb.c
 Approach: Added cache flush helper in VT framebuffer layer, called after
every rendering operation
 #ifdef __aarch64__
 static inline void
 vt_fb_cache_flush_region(struct fb_info *info, unsigned int x, unsigned int
y,
     unsigned int width, unsigned int height)
 {
     unsigned int bpp, yi;
     vm_offset_t line_start, line_end, addr;
     bpp = FBTYPE_GET_BYTESPP(info);
     for (yi = 0; yi < height; yi++) {
         line_start = (vm_offset_t)info->fb_vbase +
             ((y + yi) * info->fb_stride) + (x * bpp);
         line_end = line_start + (width * bpp);
         line_start &= ~63UL;
         line_end = (line_end + 63) & ~63UL;
         for (addr = line_start; addr < line_end; addr += 64) {
             __asm __volatile("dc civac, %0" : : "r" (addr) : "memory");
         }
     }
     __asm __volatile("dsb sy" : : : "memory");
 }
 #endif
 Added to: vt_fb_bitblt_bitmap(), vt_fb_bitblt_argb(), vt_fb_setpixel(),
vt_fb_blank()
 Result: ✗ No effect. Screen still frozen.

 3. Debug Printf Attempt (kernel-v28)

 Approach: Added printf() debug inside cache flush to verify execution
 Result: ✗ CATASTROPHIC - Infinite loop, hard freeze at boot
 Reason: printf() writes to screen → calls cache flush → calls printf() →
recursion

 4. Uncached Framebuffer (kernel-v29)

 File: sys/dev/drm2/ttm/ttm_bo_vm.c
 Approach: Force VM_MEMATTR_UNCACHEABLE for all TTM mappings on ARM64
 #ifdef __aarch64__
 pmap_page_set_memattr(m, VM_MEMATTR_UNCACHEABLE);
 #else
 pmap_page_set_memattr(m, ttm_io_prot(bo->mem.placement));
 #endif
 Result: ✗ No effect. Screen still frozen.

 5. Early DRM Load (loader.conf)

 Approach: Load DRM modules in /boot/loader.conf before efifb
initialization
 Result: ✗ Kernel panic - vm_fault_failed during Panfrost initialization
 panic: vm_fault_failed: 0xfffff00000146404 error 1

 Working Workaround (Limitation: Software Rendering Only)

 Boot Sequence

 1. Boot with efifb (EFI framebuffer)
 2. Start X11/Xorg BEFORE loading DRM modules
 3. X uses scfb (Simple Framebuffer) driver
 4. Load DRM modules AFTER X is running
 5. X continues working (no VT switch, no freeze)

 Configuration

 /usr/local/etc/X11/xorg.conf.d/10-scfb.conf:
 Section "Device"
     Identifier "EFI Framebuffer"
     Driver "scfb"
 EndSection

 Workaround Limitations

 - ✓ System fully functional, X11 desktop works
 - ✓ Keyboard/mouse work correctly
 - ✗ No GPU acceleration - Mesa uses llvmpipe (software rendering)
 - ✗ scfb driver does not support DRI2/DRI3
 - ✗ glxinfo shows: OpenGL renderer: llvmpipe (LLVM 19.1.7, 128 bits)
 - ✗ Cannot switch to modesetting driver at runtime (would require X
restart → freeze)

 Technical Analysis

 Why Workaround Works

 - Avoids VT driver hot-swap (efifb → fb)
 - No rk_vop20 initialization during active console
 - DRM loads after display system stabilized

 Why GPU Acceleration Fails in Workaround

 MESA-LOADER: screen 0 does not appear to be DRI2 capable
 MESA-LOADER: dlopen(/usr/local/lib/dri/swrast_dri.so)
 - X bound to scfb framebuffer for GLX rendering
 - scfb is non-accelerated, no DRI2/DRI3 support
 - Mesa fallback to software rendering (swrast/llvmpipe)
 - Even with DRM loaded, X cannot use hardware acceleration without restart

 Confirmed Working Components

 - ✓ Panfrost driver loads (panfrost_dri.so exists, renderD128 created)
 - ✓ Mesa compiled with Panfrost support (pkg info mesa-dri shows panfrost:
on)
 - ✓ DRM devices created correctly (/dev/dri/card1, card2, renderD128)
 - ✓ X detects multiple providers: modesetting (display) + NVIDIA-G0
(GPU/Panfrost)
 - ✗ Cannot use providers due to scfb limitation

 Suggested Next Steps

 Option A: Fix rk_vop20 Driver (Recommended)

 Problem is in the VOP2 driver itself, not just cache coherency.

 Investigation needed:
 1. Review rk_vop20 initialization sequence
 2. Compare FreeBSD 14.2 vs 15.0 VOP2 code paths
 3. Check VOP2 interrupt handling and display pipeline setup
 4. Add delays/barriers during VOP2 initialization
 5. Investigate VOP2 register access patterns with new VM radix tree

 Files to examine:
 find /usr/src -name "*vop2*" -o -name "*rk_vop*"
 # Likely: sys/dev/drm/rockchip/rk_vop2.c or similar

 Option B: Alternative Display Path

 Try Wayland instead of X11 - May not trigger same VT switch issue:
 - Weston compositor on FreeBSD
 - Direct KMS/DRM without VT layer
 - Could bypass VOP2 freeze scenario

 Option C: Hybrid Approach

 Load DRM earlier in boot, before efifb:
 - Use custom kernel with DRM compiled-in (not module)
 - Initialize VOP2 before EFI framebuffer handler
 - May avoid VT switch entirely

 Option D: Community Help

 Post to:
 - FreeBSD ARM mailing list
 - FreeBSD graphics/DRM mailing list
 - Rockchip/Radxa community forums

 Attach:
 - Full dmesg output (working vs frozen)
 - Xorg logs (/var/log/Xorg.0.log)
 - Kernel config (RK356X-UNIFIED-KEYBOARD-FIX)
 - VOP2 register dumps (if accessible via SSH)

 Questions for FreeBSD Developers

 1. VM radix tree changes: Do ARM64 cache maintenance operations need
updates for the new radix tree iterator API?
 2. TTM on ARM64: Are there known issues with TTM buffer object management
on FreeBSD 15 ARM64?
 3. VOP2 driver: Has anyone tested Rockchip VOP2 display controller on
FreeBSD 15 ARM64?
 4. DRI3 on ARM64: Is DRI3 fully supported for ARM64 Mali/Panfrost on
FreeBSD 15?
 5. VT hot-swap: Are there known ARM64-specific issues with VT driver
switching in FreeBSD 15?

 Additional Information

 DRM Module: Custom unified module combining:
 - DRM core framework
 - Rockchip VOP2 + HDMI display driver
 - Panfrost Mali GPU driver
 - Module name: drm_panfrost_unified.ko

 Dependencies: linuxkpi.ko, powerdom.ko, rk_pmdomain.ko, rk_iommu.ko

 Reproducibility: 100% reproducible on FreeBSD 15.0. FreeBSD 14.2 works
perfectly with an identical setup.

 ---
 Goal: Enable full GPU-accelerated X11/Wayland desktop on FreeBSD 15 ARM64
with Rockchip RK3568 without VOP2 freeze.

-- 
Mario.