如何在自编写的字符设备内核模块中处理页面域错误?

时间:2016-09-15 15:51:54

标签: linux module linux-kernel arm embedded-linux

Hej

我正在使用yocto和meta-atmel为Atmel的SAMA5D3x平台生成自己的嵌入式Linux。这包括一个自编写的内核模块。这是一个非常简单的字符设备(chrdev),它可以切换引脚来打开/关闭LED。

当我将其构建到内核4.1时,它工作正常。但是当迁移到内核4.4时,它会在写入函数中因“页面域错误”而崩溃。

直到崩溃的代码如下所示:

//! reads the commands from the i/o
static ssize_t dev_write(struct file *filp, const char *buff, size_t len, loff_t *off)
{
    char *  szDevice;
    int     deviceLen;
    char *  szPara;
    int     paraLen;
    char *  szValue;
    int     valueLen;
    size_t  remBytes;
    char *  szErrorStr;

    int devIndex, paraIndx;
    TBoardLed_State state;
    char tb[len+1];

    memcpy(tb, buff, len);
    tb[len] = 0;

    printk(KERN_INFO "%s: dev_write: %s (%i)\n", dSEK4Dev_indi, tb, (int) len);

错误打印是:

[  107.140000] Unhandled fault: page domain fault (0x01b) at 0x00101090
[  107.140000] pgd = d41a4000
[  107.140000] [00101090] *pgd=346e1831, *pte=3f5ba34f, *ppte=3f5ba83f
[  107.140000] Internal error: : 1b [#1] ARM
[  107.140000] Modules linked in: sek4matrixled(O) sek4comconfig(O) sek4boardled(O)
[  107.140000] CPU: 0 PID: 428 Comm: sh Tainted: G           O    4.4.19-linux4sam_5.4 #1
[  107.140000] Hardware name: Atmel SAMA5
[  107.140000] task: d45a0040 ti: d45b4000 task.ti: d45b4000
[  107.140000] PC is at memcpy+0x7c/0x330
[  107.140000] LR is at dev_write+0x2c/0x25c [sek4boardled]
[  107.140000] pc : [<c020effc>]    lr : [<bf0002f8>]    psr: 00020013
               sp : d45b5e74  ip : 0000000c  fp : d45b5efc
[  107.140000] r10: 00000000  r9 : d45b4000  r8 : c000f564
[  107.140000] r7 : d45b5f88  r6 : 00101090  r5 : 00000015  r4 : d45b5ea8
[  107.140000] r3 : 00000018  r2 : fffffff5  r1 : 00101090  r0 : d45b5ea8
[  107.140000] Flags: nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[  107.140000] Control: 10c53c7d  Table: 341a4059  DAC: 00000051
[  107.140000] Process sh (pid: 428, stack limit = 0xd45b4208)
[  107.140000] Stack: (0xd45b5e74 to 0xd45b6000)
[  107.140000] 5e60:                                              00000015 00101090 d45b5f88
[  107.140000] 5e80: c000f564 d45b5ea8 d45b5ea8 bf0002f8 00000000 00000000 d45b4000 00000068
[  107.140000] 5ea0: d45b5ed8 befff3f0 befff3f0 c0219c8c d46e07fc d45b5fb0 d45a0040 d4650540
[  107.140000] 5ec0: 00000817 0010209c d4650574 00000055 00000800 c001674c 00000006 d457e1c0
[  107.140000] 5ee0: bf0002cc 00101090 d45b5f88 c000f564 d45b4000 00000000 00000000 c00a2ae8
[  107.140000] 5f00: b6f627cc 00006950 00007958 c000928c 00001000 00000000 00000000 00000000
[  107.140000] 5f20: 57dabaed 258d097f 57dabaed 258d097f 57dabaed 258d097f 000005e5 00000000
[  107.140000] 5f40: befff3f0 b6f62d58 b6f62d58 d457e1c0 00000015 00101090 d45b5f88 c000f564
[  107.140000] 5f60: d45b4000 c00a32b0 00000000 0fa00000 d457e1c0 d457e1c0 00101090 00000015
[  107.140000] 5f80: c000f564 c00a3ac8 00000000 00000000 b6fd16d0 00000015 00101090 b6f62d58
[  107.140000] 5fa0: 00000004 c000f3a0 00000015 00101090 00000001 00101090 00000015 00000000
[  107.140000] 5fc0: 00000015 00101090 b6f62d58 00000004 00000015 000ed124 00000001 00000000
[  107.140000] 5fe0: 00000000 befff954 b6e8fe6c b6ee8f80 60020010 00000001 00000000 00000000
[  107.140000] [<c020effc>] (memcpy) from [<bf0002f8>] (dev_write+0x2c/0x25c [sek4boardled])
[  107.140000] [<bf0002f8>] (dev_write [sek4boardled]) from [<c00a2ae8>] (__vfs_write+0x1c/0xd8)
[  107.140000] [<c00a2ae8>] (__vfs_write) from [<c00a32b0>] (vfs_write+0x90/0x16c)
[  107.140000] [<c00a32b0>] (vfs_write) from [<c00a3ac8>] (SyS_write+0x44/0x9c)
[  107.140000] [<c00a3ac8>] (SyS_write) from [<c000f3a0>] (ret_fast_syscall+0x0/0x3c)
[  107.140000] Code: ea000011 e320f000 e4913004 e4914004 (e4915004)
[  107.140000] ---[ end trace 2c62698a45a8d21d ]---

对我而言,我的模块不允许从用户空间读取数据。但我不知道如何克服这个错误。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

正如Tsyvarev所提到的,输入缓冲区需要通过copy_from_user从用户空间复制到内核空间。在memcpy被copy_from_user替换后,模块可以正常工作。

答案 1 :(得分:1)

启用CONFIG_CPU_SW_DOMAIN_PAN时发生页面域错误CONFIG_CPU_SW_DOMAIN_PAN不允许副本从内核空间直接写入用户空间

解决方案::要么删除此驱动程序,要么修改您的代码。