探索kernel3.18设备树读取过程以及driver的match过程2
(由于个人原因没按时发布,flag很危险呐)
上一篇探索到了match的过程,1形成了自己的打印函数思路,2知道了dump_stack()函数,3缩小了of读取函数的范围。
本篇则通过dump_stack()函数打印出来的函数一个一个找下去,看会不会找到哪个地方读取of
[ 4.664679] <6>-(4)[1:swapper/0][<ffffffc00008becc>] dump_backtrace+0x0/0x190
[ 4.664688] <6>-(4)[1:swapper/0][<ffffffc00008c180>] show_stack+0x14/0x1c
[ 4.664697] <6>-(4)[1:swapper/0][<ffffffc000d173e4>] dump_stack+0xbc/0xf8
[ 4.664706] <6>-(4)[1:swapper/0][<ffffffc000a621d0>] __of_match_node+0xa8/0xe8
[ 4.664714] <6>-(4)[1:swapper/0][<ffffffc000a631c0>] of_match_node+0x38/0x5c
[ 4.664721] <6>-(4)[1:swapper/0][<ffffffc000a64d50>] of_match_device+0x18/0x28
[ 4.664731] <6>-(4)[1:swapper/0][<ffffffc0003d3e8c>] platform_match+0x4c/0xb8
[ 4.664739] <6>-(4)[1:swapper/0][<ffffffc0003d2224>] __driver_attach+0x3c/0xb8
[ 4.664747] <6>-(4)[1:swapper/0][<ffffffc0003d0228>] bus_for_each_dev+0x58/0x98
[ 4.664754] <6>-(4)[1:swapper/0][<ffffffc0003d239c>] driver_attach+0x30/0x38
[ 4.664761] <6>-(4)[1:swapper/0][<ffffffc0003d0a54>] bus_add_driver+0x128/0x23c
[ 4.664769] <6>-(4)[1:swapper/0][<ffffffc0003d2eec>] driver_register+0x74/0x138
[ 4.664777] <6>-(4)[1:swapper/0][<ffffffc0003d495c>] __platform_driver_register+0x60/0x68
[ 4.664785] <6>-(4)[1:swapper/0][<ffffffc001441adc>] mtkfb_init+0x8c/0x168
[ 4.664792] <6>-(4)[1:swapper/0][<ffffffc001407d18>] do_one_initcall+0xec/0x238
[ 4.664800] <6>-(4)[1:swapper/0][<ffffffc001407fb0>] kernel_init_freeable+0x14c/0x218
[ 4.664809] <6>-(4)[1:swapper/0][<ffffffc000d106f8>] kernel_init+0x14/0x194
[ 4.664814] <6>-(4)[1:swapper/0]fuhua-checkcode-score = 1073741823
现在是从a5a_cn_import/kernel3.18/driver/base/dd.c中的__driver_attach中打印出了device->of_node->properties->value,所以应该从bus_for_each_dev往上追溯dev的值。
但如果没有drv的限制,会不会出现value又为空而kernel又处理不了的情况呢?
所以现在急需知道如何让kernel跳过处理"Unable to handle kernel NULL pointer dereference at virtual address 00000020"
现在就绕不过上一篇的mark了
我们可以先探索一下c语言的try catch机制(c语言的异常处理机制),然后看这个办法是否可行(在尝试异常处理机制之前,尝试过用ISR_ERR函数,但是并没有太多的用处)
猜想异常处理机制和堆栈的关系,只能返回堆栈里面的异常?不然就崩溃?goto语句
发现setjmp这个函数根本不能使用,所以只能继续往上看了~
追溯到bus_for_each_dev
这段代码,发现里面的dev都是从klist_iter_init_node函数里面读取出来的,所以需要查清楚该函数做了什么
通过查找资料,klist只是kernel三大链表里面的一个,list_head,hlist,klist。所以推断这个函数只是单纯操作klist的,对of没有太多涉及。
网上找到一篇和我想做同样事情的blog,不过是基于3.14的,通过一些验证发现说的一些函数并没有调用到,难道是已经做了修改?
经过一些波折,还是打印除了populate函数的log,处理方式是重新生成obj文件(暂时是不知道原因的,可能和make文件有关系)
现在是将child打印出来看看
PS: 这个populate函数是根据网上查到的,由于之前验证没有打出log,所以之前以为是假的,但是通过log看到populate这个函数的确是被调用了,而且整个代码里面就只有两处,所以验证到了是因为out的obj问题。
现在由于没有打印出来mtkfb这个关键字,所以还在继续寻找如何打印出来子节点什么的,刚刚因为搜索soc关键字所以又走了岔路,所以我们现在回来继续看看tree的节点是怎么构建的。
根据log和populate这个函数里面的逻辑,总算是打印出来了似乎是读取的log,在of_platform_bus_create()
的for_each_child_of_node(bus, child)
下面,打印出child->properties->value
另外of_platform_bus_create
居然还是递归调用~~~好久没看到这种了
首先,这个函数不是在bus match mtkfb_driver的时候出现的,是在之前出现的,然后由于在log当中也发现了之前打印的log,所以这个函数可能走的是上一篇文章探索的主要函数之前的流程, 我们先探索一下log,看具体的调用顺序,然后再结合上一篇形成一个总体的概述。
那么先解决第一个疑问,到底有没有真正找到创建device_node的地方呢,我们可以在log之前打印一次child->properties->value
如果为null就可以证明之前是没有创建这个节点的,如果有则证明还在前面;当然根据经验,基本上就是这个地方了,后面再去验证吧。如果继续深挖下去就是哪里将设备树加载进来的,以及通过怎样的代码读取的,是否在这些个函数里面呢?这里先mark一下,以后有时间有兴趣有需求再探索
第二个点就是of_platform_bus_create()
函数的调用顺序以及该函数和mtkfb_match关系或者调用顺序(关系我只能想到前后关系,前置条件等关系)
那么of_platform_bus_create()
的函数调用顺序是怎样的呢?我们通过log可以看到有打印出'mediatek,mtk'
之前有dump_stack
的影子,log如下:
[ 1.935095] <7>-(7)[1:swapper/0]CPU: 7 PID: 1 Comm: swapper/0 Not tainted 3.18.35+ #12
[ 1.936079] <7>-(7)[1:swapper/0]Hardware name: MT6738 (DT)
[ 1.936763] <7>-(7)[1:swapper/0][name:traps&]Call trace:
[ 1.937435] <7>-(7)[1:swapper/0][<ffffffc00008becc>] dump_backtrace+0x0/0x190
[ 1.938324] <7>-(7)[1:swapper/0][<ffffffc00008c180>] show_stack+0x14/0x1c
[ 1.939172] <7>-(7)[1:swapper/0][<ffffffc000d173f0>] dump_stack+0xbc/0xf8
[ 1.940019] <7>-(7)[1:swapper/0][<ffffffc000a621f0>] __of_match_node+0x90/0xb4
[ 1.940918] <7>-(7)[1:swapper/0][<ffffffc000a631c4>] of_match_node+0x38/0x5c
[ 1.941796] <7>-(7)[1:swapper/0][<ffffffc000a64d54>] of_match_device+0x18/0x28
[ 1.942698] <7>-(7)[1:swapper/0][<ffffffc0003d3e8c>] platform_match+0x4c/0xb8
[ 1.943586] <7>-(7)[1:swapper/0][<ffffffc0003d1f14>] __device_attach+0x2c/0xb4
[ 1.944486] <7>-(7)[1:swapper/0][<ffffffc0003d0478>] bus_for_each_drv+0x54/0x94
[ 1.945397] <7>-(7)[1:swapper/0][<ffffffc0003d2350>] device_attach+0xb0/0xcc
[ 1.946275] <7>-(7)[1:swapper/0][<ffffffc0003d0780>] bus_probe_device+0x94/0xb8
[ 1.947188] <7>-(7)[1:swapper/0][<ffffffc0003cdd10>] device_add+0x438/0x518
[ 1.948055] <7>-(7)[1:swapper/0][<ffffffc000a64dfc>] of_device_add+0x50/0x88
[ 1.948934] <7>-(7)[1:swapper/0][<ffffffc000a65830>] of_platform_device_create_pdata+0x78/0xc8
[ 1.950007] <7>-(7)[1:swapper/0][<ffffffc000a6595c>] of_platform_bus_create+0xdc/0x490
[ 1.950993] <7>-(7)[1:swapper/0][<ffffffc000a65ce0>] of_platform_bus_create+0x460/0x490
[ 1.951992] <7>-(7)[1:swapper/0][<ffffffc000a65e8c>] of_platform_populate+0x48/0xb0
[ 1.952949] <7>-(7)[1:swapper/0][<ffffffc00140a364>] arm64_device_init+0x20/0x2c
[ 1.953869] <7>-(7)[1:swapper/0][<ffffffc001407d18>] do_one_initcall+0xec/0x238
[ 1.954780] <7>-(7)[1:swapper/0][<ffffffc001407fb0>] kernel_init_freeable+0x14c/0x218
[ 1.955758] <7>-(7)[1:swapper/0][<ffffffc000d10704>] kernel_init+0x14/0x194
[ 1.956622] <7>-(7)[1:swapper/0]fuhua-checkcode-score = 1073741823
[ 1.957538] <5>-(5)[1:swapper/0]CPU: 5 PID: 1 Comm: swapper/0 Not tainted 3.18.35+ #12
[ 1.958523] <5>-(5)[1:swapper/0]Hardware name: MT6738 (DT)
[ 1.959206] <5>-(5)[1:swapper/0][name:traps&]Call trace:
[ 1.959873] <5>-(5)[1:swapper/0][<ffffffc00008becc>] dump_backtrace+0x0/0x190
[ 1.960763] <5>-(5)[1:swapper/0][<ffffffc00008c180>] show_stack+0x14/0x1c
[ 1.961609] <5>-(5)[1:swapper/0][<ffffffc000d173f0>] dump_stack+0xbc/0xf8
[ 1.962454] <5>-(5)[1:swapper/0][<ffffffc0003d3ee4>] platform_match+0xa4/0xb8
[ 1.963343] <5>-(5)[1:swapper/0][<ffffffc0003d1f14>] __device_attach+0x2c/0xb4
[ 1.964243] <5>-(5)[1:swapper/0][<ffffffc0003d0478>] bus_for_each_drv+0x54/0x94
[ 1.965155] <5>-(5)[1:swapper/0][<ffffffc0003d2350>] device_attach+0xb0/0xcc
[ 1.966033] <5>-(5)[1:swapper/0][<ffffffc0003d0780>] bus_probe_device+0x94/0xb8
[ 1.966945] <5>-(5)[1:swapper/0][<ffffffc0003cdd10>] device_add+0x438/0x518
[ 1.967813] <5>-(5)[1:swapper/0][<ffffffc000a64dfc>] of_device_add+0x50/0x88
[ 1.968691] <5>-(5)[1:swapper/0][<ffffffc000a65830>] of_platform_device_create_pdata+0x78/0xc8
[ 1.969765] <5>-(5)[1:swapper/0][<ffffffc000a6595c>] of_platform_bus_create+0xdc/0x490
[ 1.970752] <5>-(5)[1:swapper/0][<ffffffc000a65ce0>] of_platform_bus_create+0x460/0x490
[ 1.971750] <5>-(5)[1:swapper/0][<ffffffc000a65e8c>] of_platform_populate+0x48/0xb0
[ 1.972705] <5>-(5)[1:swapper/0][<ffffffc00140a364>] arm64_device_init+0x20/0x2c
[ 1.973626] <5>-(5)[1:swapper/0][<ffffffc001407d18>] do_one_initcall+0xec/0x238
[ 1.974537] <5>-(5)[1:swapper/0][<ffffffc001407fb0>] kernel_init_freeable+0x14c/0x218
[ 1.975514] <5>-(5)[1:swapper/0][<ffffffc000d10704>] kernel_init+0x14/0x194
接下来需要查证两个问题,一个是dump_stack()
是在哪里调用的,二是of_platform_bus_create
的调用顺序。
一:首先我们搜索一下dump_stack的调用,第一个是drivers/base/platform.c里的platform_match()
里面调用了一次 另一个看log应该y也是,当屏蔽了之后发现drivers/of/base.c在前调用,drivers/base/platform.c在后面调用。结合log,发现有一个value是
'mediatek,dispsys'```,所以猜想是匹配到了调用的吧,那么就可以看出来这一条线也是有点奇怪的,可能也是在交叉的
也就是说中间有一条没走fuhua-checkcode-device_attcch_else
这条线,这条线前后打出来的child是'mediatek,mdp_color'
,'mediatek,dispsys'
那么现在引申出另一个问题,能进入match的compitable又是哪一个呢?(这一个问题在完成第二点之后再验证)
二: 在加载了'mediatek,mtkfb'
的地方打印dump_stack()
log如下:
[ 1.723465] <6>-(6)[1:swapper/0][<ffffffc000d18408>] dump_stack+0xbc/0xf8
[ 1.724313] <6>-(6)[1:swapper/0][<ffffffc000a65d0c>] of_platform_bus_create+0x498/0x4b4
[ 1.725311] <6>-(6)[1:swapper/0][<ffffffc000a65ea4>] of_platform_populate+0x48/0xb0
[ 1.726268] <6>-(6)[1:swapper/0][<ffffffc00140b364>] arm64_device_init+0x20/0x2c
[ 1.727189] <6>-(6)[1:swapper/0][<ffffffc001408d18>] do_one_initcall+0xec/0x238
[ 1.728100] <6>-(6)[1:swapper/0][<ffffffc001408fb0>] kernel_init_freeable+0x14c/0x218
[ 1.729079] <6>-(6)[1:swapper/0][<ffffffc000d1171c>] kernel_init+0x14/0x194
从log看,调用的顺序是kernel_init
->kernel_init_freeable
->arm64_device_init
->of_platform_populate
->of_platform_bus_create
结合上一篇我们可以发现都有do_one_initcall
这个函数,所以可以看一下是否有先后顺序,发现这个函数的调用也比较特别,在for循环里面调用的fn,所以通过打印的时间来看是of_platform_populate
在mtkfb_init(void)
之前调用的。
至此,读取设备树的流程基本清楚了,现在可以针对of_platform_populate()
这个函数进行进一步的解读,解读完成之后基本能回答第一篇的问题3了。