2413213_ja-JP

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

2413213_ja-JP

2413213_ja-JP

mlockall(MCL_FUTURE)を呼び出すプロセスでiMX8MP GPUを使用すると、カーネルBUG()

あるお客様がiMX8MPのGPU使用(EGLによる描画)に関する問題を報告しました。以前mlockall(MCL_FUTURE)と呼ばれていたGPU初期化プロセスが、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を駆動しています。

AIを活用した分析を実施した結果、問題が発生する理由として考えられる説明が明らかになりました。

galcoreドライバーのCMAアロケーターには.mmap()が含まれていません。フック。_CMAFSLMapUser() の実行中に、mmap() を呼び出して vma を取得し、それを使用して find_vma() を使用して CMA 領域を特定します。mmap() の呼び出し方法により、カーネルは要求を満たすために SHM 領域を遅延的に割り当てることになります。通常の場合、CMAが見つかって再マッピングされると、この割り当てはすぐに破棄されます。

しかし、MCL_FUTUREがアクティブなとカーネルはもはやSHM領域を怠惰に割り当てることができなくなり、mmap()が戻る前にエリア全体を埋め尽くします。この場合、このアドレスには有効なページがあり、後のremap_pfn_range()への呼び出しはメモリ管理のハウスキーピング情報を静かに破棄することになり、これはまさにBUG()が防いでいることです。

CODESYSを実行せずに問題を再現できるプログラムのソースコードを含むzipファイルを添付します。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チームに確認させてください。

よろしくお願いします、
志明

タグ(1)
評価なし
バージョン履歴
最終更新日:
火曜日
更新者: