AIX Hardware Storage Keys 调试

作者:椒图实验室

转载请注明出处:http://blog.jowto.com

为了通杀所有 POWER AIX 系统,我的代码都是在最低平台和版本上进行编译的,如 POWER5 的 AIX 5300-00,为了向后兼容使用了解析内核镜像文件,动态获得函数及结构的方法,但这也带来了一些问题。比如 POWER6 后提供的 Hardware Storage Keys,在此平台编译使用没有任何问题,但拿到 POWER7 上则出现了崩溃现象,但将代码在 POWER7 上编译则没有任何问题,我查了编译选项没有使用任何优化参数,最终当我定位问题后不得不再次感叹,对这种硬件,OS,编译器都是自己的大型封闭系统真是没的治。

KDB(0)> dis @r0 – 4 10

.aix_kernel_get_diskdev+0002C4 bl <.new_hkeyset> –>调用new_hkeyset崩掉的,这是我写的包装函数。

.aix_kernel_get_diskdev+0002C8 ori r0,r0,0

.aix_kernel_get_diskdev+0002CC ld r3,90(stkp)

.aix_kernel_get_diskdev+0002D0 bl <.kputpath>

.aix_kernel_get_diskdev+0002D4 lwa r3,A8(stkp)

.aix_kernel_get_diskdev+0002D8 cmpwi cr0,r3,0

.aix_kernel_get_diskdev+0002DC beq cr0.eq,<.aix_kernel_get_diskdev+0002EC>

.aix_kernel_get_diskdev+0002E0 ld r3,108(stkp)

.aix_kernel_get_diskdev+0002E4 std r3,B8(stkp)

.aix_kernel_get_diskdev+0002E8 b <.aix_kernel_get_diskdev+0002F4>

KDB(0)> dis new_hkeyset 13

.new_hkeyset+000000 mflr r0

.new_hkeyset+000004 stdu stkp,FFFFFF90(stkp)

.new_hkeyset+000008 std r0,80(stkp) –>保存调用函数返回地址

.new_hkeyset+00000C std r3,A0(stkp) –>保存 hkeyset_t 映射值,即 amr 寄存器

.new_hkeyset+000010 ld r3,A0(stkp)

.new_hkeyset+000014 li r4,FFFFFFFF –>这里的 r4 寄存器为 HKEYSET_INVALID 无效值

.new_hkeyset+000018 cmpld cr0,r3,r4 r4=FFFFFFFFFFFFFFFF –>比较 hkeyset_t 有效性

.new_hkeyset+00001C beq cr0.eq,<.new_hkeyset+000024>

.new_hkeyset+000020 bla <.hkeyset_replace> –>如果有效应该调用这里替换 hkeyset_t 的值

.new_hkeyset+000024 ld r0,80(stkp) –>无效才会跳转到这里

.new_hkeyset+000028 mtlr r0

.new_hkeyset+00002C addi stkp,stkp,70

.new_hkeyset+000030 blr

KDB(0)> dr iar

iar : F1000000C06A9A6C

.new_hkeyset+000024 ld r0,80(stkp) r0=F1000000C06B6E0C –>iar 与 lr 的值一样,说明 hkeyset_t 值

有效是在调用系统提供的 hkeyset_replace 时崩掉的

,80(stkp)=F00000002FF47350

KDB(0)> dr lr

lr : F1000000C06A9A6C

.new_hkeyset+000024 ld r0,80(stkp) r0=F1000000C06B6E0C

,80(stkp)=F00000002FF47350

到现在为止自己写的代码没看出问题,为了跟踪并比较 hkeyset_replace() 完整流程,我找了台最新的 POWER7 AIX 7100-02 系统,并把断点下在了 hkeyset_replace+00000C

通过 intpri 寄存器与 prev 可以看到当前为“中断上下文”

KDB(2)> mst

Machine State Save Area

iar : 0000000000014C54 msr : 8000000000029032 cr : 88088287

lr : 0000000004152D64 ctr : 0000000004152D00 xer : 20000001

mq : 00000000 asr : FFFFFFFFFFFFFFFF amr : F3FC000000000000

r0 : 00000000001758A0 r1 : F10004158007F9D0 r2 : 000000000415D160

r3 : F30F000000000000 r4 : F10006C001438100 r5 : 0000000000001000

r6 : F10006C0013E08C0 r7 : 0000000080000000 r8 : 0000000010000000

r9 : 0000000010000000 r10 : 00000C62F0269E5E r11 : 000000000415D058

r12 : F3FC000000000000 r13 : F100060010095400 r14 : F100041580083D00

r15 : 0000000002088A80 r16 : F10004158007FD00 r17 : 000000000000000A

r18 : 000000000000000B r19 : 0000000000000003 r20 : 0000000002C26A88

r21 : 0000000810200000 r22 : 0000000000008000 r23 : 00000000007C6438

r24 : 0000000000000000 r25 : F10006C001420580 r26 : 0000000000000000

r27 : 0000000000000001 r28 : FFFFFFFFFFFFFFFF r29 : 0000000000000000

r30 : 0000000000000000 r31 : F100010014C70000

prev F100041580083D00 stackfix 0000000000000000 int_ticks 0000

cfar 0000000000000005

kjmpbuf 0000000000000000 excbranch 0000000000000000 no_pfault 00

intpri 03 backt 00 flags 00

hw_fru_id 02C41F70 hw_cpu_id 00000000

(2)> more (^C to quit) ?

反汇编调试 hkeyset_replace 存储键函数

KDB(2)> dis @iar – 10 8

.hkeyset_replace+000000 mfaccr r12 ->此条指令将 amr 寄存器值装入 r12 寄存器,即当前“存储键”

.hkeyset_replace+000004 cmpd cr0,r3,r12 ->与 r3 寄存器新的“存储键”值比较

.hkeyset_replace+000008 beqlr cr0.eq ->相等则直接返回调用者(lr 寄存器保存调用者地址)

.hkeyset_replace+00000C isync ->刷新“指令cache”

.hkeyset_replace+000010 mtaccr r3 ->不相等,则使用此条指令确保新的“存储键”装入 r3 寄存器

.hkeyset_replace+000014 isync ->两次刷新“指令cache”以达到“同步”目的

.hkeyset_replace+000018 mr r3,r12 ->替换新的“存储键” r3->r12 = amr

KDB(2)> s

.hkeyset_replace+000010 mtaccr r3 <F30F000000000000>

KDB(2)> dr r3

r3 : F30F000000000000 F30F000000000000 ->r3 = 新的“存储键”

KDB(2)> dr r12

r12 : F3FC000000000000 F3FC000000000000 ->r12 = 当前 “存储键”

KDB(2)> dr amr ->显示 amr 寄存器中的“内核存储键”与“硬件存储键”映射关系

amr : F3FC000000000000

hkey 2 RW PUBLIC

hkey 7 RW PROC INTR VMM LFS CRED LDR KER

KDB(2)> s

.hkeyset_replace+000014 isync

KDB(2)> s

.hkeyset_replace+000018 mr r3,r12 <F3FC000000000000> r3=

F30F000000000000,r12=F3FC000000000000

KDB(2)> s

.hkeyset_replace+00001C blr <04152D64> r3=F3FC0000

00000000

KDB(2)> dr amr ->替换后可以看到新“存储键” 值的范围

amr : F30F000000000000

hkey 2 RW PUBLIC

hkey 4 RW COMMO NETM IPSEC USB GRAPHICS

hkey 5 RW DMA PCI VDEV TRB IOMAP PRIVATE1 PRIVATE17 PRIVATE9 PRIVATE25 …

通过与上面正常流程比较,发现在 hkeyset_replace() 中对 hkeyset_t 设置时插入了一条用于符号扩展的汇编指令,从而影响了 r3 寄存器的值,导致访问违规。问题定位后调整了代码,改用指针传递,算是解决了 POWER6 与 POWER7 兼容问题。

 

Posted on 一月 19, 2015 at 下午1:24 by admin · Permalink
In: 未分类

友情链接