ARM で SPI LCD ディスプレイ用のフレームバッファを作成しています。それを完了する前に、メモリのみのドライバーを作成し、Ubuntu (Intel、Virtualbox) で試してみました。ドライバーは正常に動作します - kmalloc を使用してメモリのブロックを割り当て、ページを整列させ (実際にはページを整列させます)、フレームバッファー システムを使用して /dev/fb1 を作成しました。関連する場合は、独自の mmap 関数があります (deferred_io はそれを無視し、見た目によって独自のものを使用します)。
私は設定しました:
info->screen_base = (u8 __iomem *)kmemptr;
info->fix.smem_len = kmem_size;
テストプログラムで /dev/fb1 を開いて mmap すると、正しく動作します。fb1を「共有」するためにx11vncが何が起こっているかを見ることができます:
x11vnc -rawfb map:/dev/fb1@320x240x16
そして、vnc ビューアーで表示します。
gvncviewer strontium:0
mmapd バッファー全体に書き込むことで、オーバーフローがないことを確認しましたが、問題ないようです。
deferred_io を追加すると問題が発生します。テストとして、1 秒の遅延があり、呼び出された deferred_io 関数は pr_devel() の出力以外は何もしません。docsに従いました。
これで、テスト プログラムは /dev/fb1 を正常に開き、mmap は OK を返しますが、そのポインターに書き込むとすぐにカーネル パニックが発生します。次のダンプは実際には ARM マシンからのものですが、Ubuntu VM でもパニックになります。
root@duovero:~/testdrv# ./fbtest1 /dev/fb1
Device opened: /dev/fb3
Screen is: 320 x 240, 16 bpp
Screen size = 153600 bytes
mmap on device succeeded
Unable to handle kernel paging request at virtual address bf81e020
pgd = edbec000
[bf81e020] *pgd=00000000
Internal error: Oops: 5 [#1] SMP ARM
Modules linked in: hhlcd28a(O) sysimgblt sysfillrect syscopyarea fb_sys_fops bnep ipv6 mwifiex_sdio mwifiex btmrvl_sdio firmware_class btmrvl cfg80211 bluetooth rfkill
CPU: 0 Tainted: G O (3.6.0-hh04 #1)
PC is at fb_deferred_io_fault+0x34/0xb0
LR is at fb_deferred_io_fault+0x2c/0xb0
pc : [<c0271b7c>] lr : [<c0271b74>] psr: a0000113
sp : edbdfdb8 ip : 00000000 fp : edbeedb8
r10: edbeedb8 r9 : 00000029 r8 : edbeedb8
r7 : 00000029 r6 : bf81e020 r5 : eda99128 r4 : edbdfdd8
r3 : c081e000 r2 : f0000000 r1 : 00001000 r0 : bf81e020
Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 10c5387d Table: adbec04a DAC: 00000015
Process fbtest1 (pid: 485, stack limit = 0xedbde2f8)
Stack: (0xedbdfdb8 to 0xedbe0000)
[snipped out hexdump]
[<c0271b7c>] (fb_deferred_io_fault+0x34/0xb0) from [<c00db0c4>] (__do_fault+0xbc/0x470)
[<c00db0c4>] (__do_fault+0xbc/0x470) from [<c00dde0c>] (handle_pte_fault+0x2c4/0x790)
[<c00dde0c>] (handle_pte_fault+0x2c4/0x790) from [<c00de398>] (handle_mm_fault+0xc0/0xd4)
[<c00de398>] (handle_mm_fault+0xc0/0xd4) from [<c049a038>] (do_page_fault+0x140/0x37c)
[<c049a038>] (do_page_fault+0x140/0x37c) from [<c0008348>] (do_DataAbort+0x34/0x98)
[<c0008348>] (do_DataAbort+0x34/0x98) from [<c0498af4>] (__dabt_usr+0x34/0x40)
Exception stack(0xedbdffb0 to 0xedbdfff8)
ffa0: 00000280 0000ffff b6f5c900 00000000
ffc0: 00000003 00000000 00025800 b6f5c900 bea6dc1c 00011048 00000032 b6f5b000
ffe0: 00006450 bea6db70 00000000 000085d6 40000030 ffffffff
Code: 28bd8070 ebffff37 e2506000 0a00001b (e5963000)
---[ end trace 7e5ca57bebd433f5 ]---
Segmentation fault
root@duovero:~/testdrv#
私は完全に困惑しています - 他のドライバーは多かれ少なかれ私のものと同じように見えますが、私はそれらがうまくいくと思います. ほとんどの場合、実際には vmalloc を使用します。この目的で kmalloc と vmalloc に違いはありますか?