2413213_zh-CN

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

2413213_zh-CN

2413213_zh-CN

在调用 mlockall(MCL_FUTURE) 的进程中使用 iMX8MP GPU 会导致内核 BUG()

一位客户报告了一个与使用 iMX8MP GPU(使用 EGL 绘图)相关的问题。当初始化 GPU 的进程先前调用 mlockall(MCL_FUTURE) 时,一旦 CMA 区域被映射到用户空间,内核就会报告以下 BUG():

Kernel BUG at remap_pfn_range_internal+0x23c/0x2c8
Internal error: Oops - BUG: 00000000f2000800 [#1] PREEMPT SMP
CPU: 0 PID: 3197 Comm: galcore_window_ Tainted: G
 O
 6.6.142-7.7.0-devel #1-Torizon
Hardware name: Toradex Verdin iMX8M Plus WB on Verdin Development Board (DT)
pc : remap_pfn_range_internal+0x23c/0x2c8
x27: 00000000a2100000
x20: 0068000000000fcb
 x19: 0000007f90000000
^^^^^^^^^^^^^^^^^^^^^^ the PTE already present
Call trace:
remap_pfn_range_internal+0x23c/0x2c8
remap_pfn_range+0x24/0x58
dma_direct_mmap+0xf4/0x150
dma_mmap_attrs+0x18/0x3c
_CMAFSLMapUser+0x9c/0x150
 [galcore]
gckOS_LockPages+0xe4/0x148
 [galcore]
gckKERNEL_MapVideoMemory+0x90/0x1dc [galcore]
gckVIDMEM_NODE_LockCPU+0x1b4/0x250 [galcore]
_LockVideoMemory.isra.0+0x1f4/0x28c [galcore]
gckKERNEL_Dispatch+0x210/0x1730 [galcore]
gckDEVICE_Dispatch+0xcc/0x220
 [galcore]
drv_ioctl+0x340/0x444
 [galcore]
__arm64_sys_ioctl+0xac/0xf0
Kernel panic - not syncing: Oops - BUG: Fatal exception

mlockall(MCL_FUTURE) 通常用于实时应用程序,而报告此问题的客户正在使用 CODESYS 来驱动其 HMI。

我们利用人工智能辅助分析了该问题,并找到了该问题触发原因的合理解释:

galcore 驱动程序中的 CMA 分配器不包含 .mmap() 方法。钩。在 _CMAFSLMapUser() 执行期间,它调用 mmap() 获取 vma,然后使用该 vma 通过 find_vma() 定位 CMA 区域。mmap() 的调用方式导致内核延迟分配 SHM 区域以满足请求。正常情况下,当找到 CMA 区域并重新映射时,此分配会在片刻后被丢弃。

但是,当 MCL_FUTURE 处于活动状态时,内核不能再延迟分配 SHM 区域,因此它会在 mmap() 返回之前填充整个区域。在这种情况下,该地址上有有效的页面,而稍后对 remap_pfn_range() 的调用最终会默默地丢弃内存管理维护信息,这正是 BUG() 所阻止的。

我将附上一个 zip 文件,其中包含一个程序的源代码,该程序可以稳定地重现该问题,而无需运行 CODESYS。AI代理建议使用以下补丁来修复此问题:

diff -uNr a/hal/kernel/inc/gc_hal_options.h b/hal/kernel/inc/gc_hal_options.h
--- a/hal/kernel/inc/gc_hal_options.h   2026-09-04 13:00:44.596621860 +0000
+++ b/hal/kernel/inc/gc_hal_options.h   2026-09-04 13:01:15.643862002 +0000
@@ -1471,9 +1471,17 @@
  *       Enable this macro can replace the /dev/zero by anon_inode:
  *       [galcore] in /proc//maps.
  *       Without the macro, run 'cat /proc//maps' will print "/dev/zero".
+ *
+ *       It is also what gives the allocators an ->mmap handler, which is
+ *       required so that the reservation made by vm_mmap() is created as a
+ *       device mapping (VM_IO | VM_PFNMAP) rather than as ordinary anonymous
+ *       memory. Without it, a process that has called mlockall(MCL_FUTURE)
+ *       gets the range pre-faulted inside vm_mmap(), and the subsequent
+ *       remap_pfn_range() then hits BUG_ON(!pte_none()) in remap_pte_range().
+ *       See tmp_mmap() in gc_hal_kernel_allocator.c.
  */
 #ifndef gcdANON_FILE_FOR_ALLOCATOR
-#    define gcdANON_FILE_FOR_ALLOCATOR              0
+#    define gcdANON_FILE_FOR_ALLOCATOR              1
 #endif

 /*
diff -uNr a/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c b/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c
--- a/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c     2026-09-04 13:00:44.605314869 +0000
+++ b/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c     2026-09-04 13:01:15.644216883 +0000
@@ -400,7 +400,13 @@
     gcmkHEADER_ARG("Allocator=%p Mdl=%p Cacheable=%d", Allocator, Mdl, Cacheable);

 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+#if gcdANON_FILE_FOR_ALLOCATOR
+    /* Same as the gfp, dma and reserved_mem allocators: go through the
+     * allocator's anon file so that its ->mmap handler runs. */
+    userLogical = (gctPOINTER)vm_mmap(Allocator->anon_file,
+#    else
     userLogical = (gctPOINTER)vm_mmap(gcvNULL,
+#    endif
                     0L,
                     Mdl->numPages * PAGE_SIZE,
                     PROT_READ | PROT_WRITE,
diff -uNr a/hal/os/linux/kernel/gc_hal_kernel_allocator.c b/hal/os/linux/kernel/gc_hal_kernel_allocator.c
--- a/hal/os/linux/kernel/gc_hal_kernel_allocator.c     2026-09-04 13:00:44.603242857 +0000
+++ b/hal/os/linux/kernel/gc_hal_kernel_allocator.c     2026-09-04 13:01:15.644041018 +0000
@@ -104,6 +104,36 @@
 static int
 tmp_mmap(struct file *fp, struct vm_area_struct *vma)
 {
+    /*
+     * Declare the reservation as a device mapping with raw PFNs, before
+     * mmap() returns it to the caller. remap_pfn_range() sets both flags
+     * anyway; setting them here only makes them effective from the moment
+     * the VMA is created, and that is what matters:
+     *
+     *  - the kernel treats VM_IO | VM_PFNMAP as VM_SPECIAL, documented in
+     *    include/linux/mm.h as "Special vmas that are non-mergable,
+     *    non-mlock()able". mmap_region() therefore clears VM_LOCKED from
+     *    this VMA and leaves mm->locked_vm alone, and __mm_populate()
+     *    skips it outright ("if (vma->vm_flags & (VM_IO | VM_PFNMAP))
+     *    continue;" in mm/gup.c).
+     *
+     *  - so a process that has called mlockall(MCL_FUTURE) no longer has
+     *    this range pre-faulted inside vm_mmap(). Every other mapping in
+     *    that process keeps being locked and pre-faulted as before; only
+     *    device memory, which is neither pageable nor swappable and gains
+     *    nothing from being pre-faulted, is left out.
+     *
+     *  - and the allocator's own remap_pfn_range(), a few microseconds
+     *    later, therefore finds an empty range instead of one the kernel
+     *    has just populated, so it no longer trips
+     *    BUG_ON(!pte_none(ptep_get(pte))) in remap_pte_range().
+     */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
+    vm_flags_set(vma, VM_IO | VM_PFNMAP);
+#else
+    vma->vm_flags |= VM_IO | VM_PFNMAP;
+#endif
+
     return 0;
 }

上游驱动程序使用了一种不同的机制来绕过这个问题。其他 galcore 分配器使用相同的模式(调用 vm_mmap 获取 vma),因此很可能容易受到相同的 BUG() 的影响。


请您调查并修复 galcore 驱动程序?这个问题导致实际应用场景无法正常运行,直接影响到我们的客户。


谢谢!

拉斐尔

Re: Using iMX8MP GPU on a process that call mlockall(MCL_FUTURE) causes kernel BUG()

嗨@rbeims

让我先运行一下测试,然后再和GPU团队确认。

此致,
志明

Re: Using iMX8MP GPU on a process that call mlockall(MCL_FUTURE) causes kernel BUG()

@Zhiming_Liu ,你好,请问你成功复现了这个bug吗?如果可以,请问预计何时能在BSP中实现该修复?谢谢。

Re: Using iMX8MP GPU on a process that call mlockall(MCL_FUTURE) causes kernel BUG()

您好@Zhiming_Liu ,感谢您提供的清晰报告。完全理解,我们也预料到这种情况会发生。一切都好。

请继续推进这项工作,如有任何进展,请与我们联系。

谢谢你,
阿尔瓦罗。

Re: Using iMX8MP GPU on a process that call mlockall(MCL_FUTURE) causes kernel BUG()

嗨@alvaro_tx

我们的内部团队测试了这个补丁。虽然它直接解决了客户遇到的问题,但在其他应用程序的测试过程中却造成了问题。我们仍在调查此事,尚未得出最终结论。

此致,
志明

Tags (1)
No ratings
Version history
Last update:
2 weeks ago
Updated by: