当前位置: 技术问答>linux和unix
一个很怪的现象:同样的驱动代码,ko模块方式加载工作正常,直接编入内核却导致kernel panic崩溃
来源: 互联网 发布时间:2016-08-26
本文导语: 大家好,当前我正在进行基于AU1200(mips32)处理器的嵌入式Linux驱动开发,因为刚刚换了块新的2G,所以现在正在做nand驱动。由于内核版本是2.6.11,不支持 nand_oob_128 的新Nand,所以从最新版本的2.6.33内核中复制了 sta...
大家好,当前我正在进行基于AU1200(mips32)处理器的嵌入式Linux驱动开发,因为刚刚换了块新的2G,所以现在正在做nand驱动。由于内核版本是2.6.11,不支持 nand_oob_128 的新Nand,所以从最新版本的2.6.33内核中复制了
static struct nand_oobinfo nand_oob_128 = {
.useecc = MTD_NANDECC_AUTOPLACE,
.eccbytes = 48,
.eccpos = {
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127},
.oobfree = { {2, 78} }
};
到nand_base.c中,并且将2.6.11内核中结构体 nand_oobinfo中eccpos大小根据最新版本内核的情况,从32修改为64,如下
struct nand_oobinfo {
uint32_t useecc;
uint32_t eccbytes;
uint32_t oobfree[8][2];
//uint32_t eccpos[32];
uint32_t eccpos[64];
};
编译能够通过,并且系统启动过程中也能够识别新的2G Nandflash(ID、型号等信息均显示正确),但是非常奇怪的现象是,同样的驱动代码,我如果在menuconfig中将 driver -> mtd -> Nand 下的NandDevice Support和Au1550/1200 Nand Support 选为 M,通过insmod *.ko(包括nand_ecc.ko、nand_ids.ko、nand.ko和au1550nd.ko)的方式加载驱动,一切工作正常,按照我驱动程序中的分区方式正常分区,Nand也可以正常读写使用。
但是如果我将nand驱动直接编入内核,系统启动识别Nand之后,在对其进行分区操作的时候却出现了如下的错误,导致内核崩溃:
NAND device: Manufacturer ID: 0xec, Chip ID: 0xd5
NAND device: Manufacturer ID: 0xec, Chip ID: 0xd5 (Samsung NAND 2GiB 3,3V 8-bit) ──这里能够正常识别Nand信息
Scanning device for bad blocks
Creating 3 MTD partitions on "NAND 2GiB 3,3V 8-bit":
0x00000000-0x10000000 : "NAND FS 0" ──这里在创建第一个Nand分区
Unhandled kernel unaligned access in arch/mips/kernel/unaligned.c::emulate_load_store_insn, line 475[#1]:
Cpu 0
$ 0 : 00000000 1000fc00 00000014 85fd9390
$ 4 : ffffffff 000000d0 85fc98e0 000000d0
$ 8 : 00000000 00000000 804e0000 00000000
$12 : 85f6243e fffffff9 ffffffff 0000000a
$16 : 1000fc01 85f62450 00000415 804e0000
$20 : 803b2090 85fc98e0 804e0000 000000d0
$24 : 00000002 810f3d4b
$28 : 810f2000 810f3d80 85fd9380 803283ac
Hi : 0000000f
Lo : 8f8f8f9f
epc : 80157634 kmem_cache_alloc+0x28/0x98 Not tainted
ra : 803283ac alloc_skb+0x34/0xf4
Status: 1000fc02 KERNEL EXL
Cause : 00800010
BadVA : ffffffff
PrId : 04030202
Modules linked in:
Process swapper (pid: 1, threadinfo=810f2000, task=810e4ba8)
Stack : 804fa000 80194410 00000000 80192d64 000000d0 803283ac 00000000 810f3e20
80410000 ffffffff 8044aa40 85f62450 00000015 85fd9380 8024e350 363d7f80
0000000a ffffffff ffffffff 00000000 8044aa40 85f62450 85fc98e0 85f62434
8044aa94 85fd382c 8044aa40 85f62450 85fc98e0 85f62434 8044aa94 85fd382c
803b2090 85f62400 8024e820 8024e7cc 801252b0 810e4ba8 000002c4 00000000
...
Call Trace:
[] alloc_inode+0x120/0x150
[] d_alloc+0x34/0x1e4
[] alloc_skb+0x34/0xf4
[] send_uevent+0x70/0x1d0
[] kobject_hotplug+0x24c/0x2e8
[] kobject_hotplug+0x1f8/0x2e8
[] __wake_up+0x40/0x7c
[] kobject_add+0x180/0x1b4
[] register_disk+0x54/0x118
[] register_disk+0x2c/0x118
[] exact_match+0x0/0x8
[] exact_lock+0x0/0x28
[] add_disk+0x58/0x6c
[] snprintf+0x14/0x20
[] release_console_sem+0x104/0x330
[] exact_lock+0x0/0x28
[] add_mtd_blktrans_dev+0x294/0x354
[] mtdblock_add_mtd+0x2c/0xcc
[] blktrans_notify_add+0x50/0x7c
[] blktrans_notify_add+0x50/0x7c
[] add_mtd_device+0x15c/0x210
[] printk+0x1c/0x28
[] nand_scan+0xa28/0xc30
[] add_mtd_partitions+0x4e4/0x608
[] add_mtd_partitions+0x68/0x608
[] au1xxx_nand_init+0x214/0x240
[] cfi_amdstd_init+0x20/0x30
[] net_dev_init+0xc4/0x234
[] init+0xa4/0x244
[] kernel_thread_helper+0x10/0x18
[] kernel_thread_helper+0x0/0x18
Code: 00020040 00020040 00020040 8cc30000 2467ffff 00071080 10600013 00c24021
Kernel panic - not syncing: Attempted to kill init!
麻烦大家帮我看看这到底是怎么回事情啊?对于这种错误信息我真的一筹莫展了,在网上也搜不到合理的解释。难道模块加载方式和直接编入内核方式有什么本质的不同吗?谢谢大家了
static struct nand_oobinfo nand_oob_128 = {
.useecc = MTD_NANDECC_AUTOPLACE,
.eccbytes = 48,
.eccpos = {
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127},
.oobfree = { {2, 78} }
};
到nand_base.c中,并且将2.6.11内核中结构体 nand_oobinfo中eccpos大小根据最新版本内核的情况,从32修改为64,如下
struct nand_oobinfo {
uint32_t useecc;
uint32_t eccbytes;
uint32_t oobfree[8][2];
//uint32_t eccpos[32];
uint32_t eccpos[64];
};
编译能够通过,并且系统启动过程中也能够识别新的2G Nandflash(ID、型号等信息均显示正确),但是非常奇怪的现象是,同样的驱动代码,我如果在menuconfig中将 driver -> mtd -> Nand 下的NandDevice Support和Au1550/1200 Nand Support 选为 M,通过insmod *.ko(包括nand_ecc.ko、nand_ids.ko、nand.ko和au1550nd.ko)的方式加载驱动,一切工作正常,按照我驱动程序中的分区方式正常分区,Nand也可以正常读写使用。
但是如果我将nand驱动直接编入内核,系统启动识别Nand之后,在对其进行分区操作的时候却出现了如下的错误,导致内核崩溃:
NAND device: Manufacturer ID: 0xec, Chip ID: 0xd5
NAND device: Manufacturer ID: 0xec, Chip ID: 0xd5 (Samsung NAND 2GiB 3,3V 8-bit) ──这里能够正常识别Nand信息
Scanning device for bad blocks
Creating 3 MTD partitions on "NAND 2GiB 3,3V 8-bit":
0x00000000-0x10000000 : "NAND FS 0" ──这里在创建第一个Nand分区
Unhandled kernel unaligned access in arch/mips/kernel/unaligned.c::emulate_load_store_insn, line 475[#1]:
Cpu 0
$ 0 : 00000000 1000fc00 00000014 85fd9390
$ 4 : ffffffff 000000d0 85fc98e0 000000d0
$ 8 : 00000000 00000000 804e0000 00000000
$12 : 85f6243e fffffff9 ffffffff 0000000a
$16 : 1000fc01 85f62450 00000415 804e0000
$20 : 803b2090 85fc98e0 804e0000 000000d0
$24 : 00000002 810f3d4b
$28 : 810f2000 810f3d80 85fd9380 803283ac
Hi : 0000000f
Lo : 8f8f8f9f
epc : 80157634 kmem_cache_alloc+0x28/0x98 Not tainted
ra : 803283ac alloc_skb+0x34/0xf4
Status: 1000fc02 KERNEL EXL
Cause : 00800010
BadVA : ffffffff
PrId : 04030202
Modules linked in:
Process swapper (pid: 1, threadinfo=810f2000, task=810e4ba8)
Stack : 804fa000 80194410 00000000 80192d64 000000d0 803283ac 00000000 810f3e20
80410000 ffffffff 8044aa40 85f62450 00000015 85fd9380 8024e350 363d7f80
0000000a ffffffff ffffffff 00000000 8044aa40 85f62450 85fc98e0 85f62434
8044aa94 85fd382c 8044aa40 85f62450 85fc98e0 85f62434 8044aa94 85fd382c
803b2090 85f62400 8024e820 8024e7cc 801252b0 810e4ba8 000002c4 00000000
...
Call Trace:
[] alloc_inode+0x120/0x150
[] d_alloc+0x34/0x1e4
[] alloc_skb+0x34/0xf4
[] send_uevent+0x70/0x1d0
[] kobject_hotplug+0x24c/0x2e8
[] kobject_hotplug+0x1f8/0x2e8
[] __wake_up+0x40/0x7c
[] kobject_add+0x180/0x1b4
[] register_disk+0x54/0x118
[] register_disk+0x2c/0x118
[] exact_match+0x0/0x8
[] exact_lock+0x0/0x28
[] add_disk+0x58/0x6c
[] snprintf+0x14/0x20
[] release_console_sem+0x104/0x330
[] exact_lock+0x0/0x28
[] add_mtd_blktrans_dev+0x294/0x354
[] mtdblock_add_mtd+0x2c/0xcc
[] blktrans_notify_add+0x50/0x7c
[] blktrans_notify_add+0x50/0x7c
[] add_mtd_device+0x15c/0x210
[] printk+0x1c/0x28
[] nand_scan+0xa28/0xc30
[] add_mtd_partitions+0x4e4/0x608
[] add_mtd_partitions+0x68/0x608
[] au1xxx_nand_init+0x214/0x240
[] cfi_amdstd_init+0x20/0x30
[] net_dev_init+0xc4/0x234
[] init+0xa4/0x244
[] kernel_thread_helper+0x10/0x18
[] kernel_thread_helper+0x0/0x18
Code: 00020040 00020040 00020040 8cc30000 2467ffff 00071080 10600013 00c24021
Kernel panic - not syncing: Attempted to kill init!
麻烦大家帮我看看这到底是怎么回事情啊?对于这种错误信息我真的一筹莫展了,在网上也搜不到合理的解释。难道模块加载方式和直接编入内核方式有什么本质的不同吗?谢谢大家了
|
在 kobject_uevent.c 的函数:
void kobject_hotplug(struct kobject *kobj, enum kobject_action action)
找到 send_uevent(action_string, kobj_path, envp, GFP_KERNEL);
把上面的调试信息 :
pr_debug ("%s: %s %s seq=%llu %s %s %s %s %sn",
__FUNCTION__, argv[0], argv[1], (unsigned long long)seq,
envp[0], envp[1], envp[2], envp[3], envp[4]);
改成 printk... 看看是什么情况,再处理。
void kobject_hotplug(struct kobject *kobj, enum kobject_action action)
找到 send_uevent(action_string, kobj_path, envp, GFP_KERNEL);
把上面的调试信息 :
pr_debug ("%s: %s %s seq=%llu %s %s %s %s %sn",
__FUNCTION__, argv[0], argv[1], (unsigned long long)seq,
envp[0], envp[1], envp[2], envp[3], envp[4]);
改成 printk... 看看是什么情况,再处理。
|
DEVPATH=/block/mtdblock3
mtdblock3 就是块设备咯。。
你 判断一下 envp[3] 中是否有 mtdblock ,就知道这个设备是不是 flash 分区了,
用这段代码试试。
mtdblock3 就是块设备咯。。
你 判断一下 envp[3] 中是否有 mtdblock ,就知道这个设备是不是 flash 分区了,
if(NULL == strstr(envp[3], "mtdblock"))
goto exit;
send_uevent(action_string, kobj_path, envp, GFP_KERNEL);
if (!hotplug_path[0])
goto exit;
用这段代码试试。