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.