浅析armlinux-__arch_clear_user内存拷贝函数之3
文章来源:http://gliethttp.cublog.cn
它还有两个姊妹篇《浅析armlinux-__arch_copy_to_user内存拷贝函数之1》和 《浅析armlinux-__arch_copy_from_user内存拷贝函数之2》[http://gliethttp.cublog.cn]
//int __arch_clear_user(void *addr, size_t sz) //addr - 需要清0的用户内存空间起始地址 //sz - 需要清0字节数 //返回值为没有清0字节数[gliethttp] //include/asm-arm/proc-armv/Assembler.h //搜索异常处理程序代码文件arch/arm/mm/Extable.c: //#define USER(x...)\//异常文件 //9999:x;\//将x...内容就放在当前.text这儿 //.section __ex_table,"a";\//转入自定义段.section,该段的内容被链接到__ex_table段专用地址空间中 //'a' 可重定位的段 //'w' 可写段 //'x' 可执行段 //'W' 可合并的段 //'s' 共享段 //.align 3;\//8字节对齐 //.long 9999b,9001f;\//上面9999b出自身x的标号处虚拟地址和下面的9001标号处虚拟地址 //0991f处为该x代码部分异常处理函数地址值,与其说是处理,不如说是一个跳板 //.previous//.previous作用就是恢复进入.section之前的.text作为当前段
ENTRY(__arch_clear_user) stmfd {r1, lr} mov r2, #0//r2为清0使用寄存器 cmp r1, #4 blt 2f//如果r1<4,调到下面的标号2: ands ip, r0, #3//检测用户地址空间是否4字节对齐 beq 1f//对齐跳转到下面的标号1: cmp ip, #2 USER( strbt r2, [r0], #1)//至少有1字节数据需要拷贝,可能触发缺页异常 USER( strlebt r2, [r0], #1)//如果ip<=2,说明至少有2个,可能触发缺页异常 USER( strltbt r2, [r0], #1)//如果ip<2,说明有3个,可能触发缺页异常[gliethttp] rsb ip, ip, #4//计算未对齐字节数ip=4-ip sub r1, r1, ip//从总数中剔除已经清0的ip个未对齐字节数 //执行至此表明用户内存地址已经4字节对齐,以下采取尽量快的存储方式 1: subs r1, r1, #8 USER( strplt r2, [r0], #4)//如果r1>=8,即还有至少8字节空闲空间,4字节清0,可能触发缺页异常 USER( strplt r2, [r0], #4)//如果r1>=8,即还有至少8字节空闲空间,4字节清0,可能触发缺页异常 bpl 1b//如果剩余用户内存数据空间r1>=8,继续 //1.ip = ip-16 //对于ip-16有这样一个规律[gliethttp 2007-07-28 唐山] // -32, -31, -30,..., -23, -22, -21, -20, -19, -18, -17, -16->1递增 //0000,0001,0010,...,1001,1010,1011,1100,1101,1110,1111,0000->1递增 // 0, 1, 2,..., 9, a, b, c, d, e, f,16+0->1递增
// -16, -15, -14,..., -7, -6, -5, -4, -3, -2, -1, 0->1递增 //0000,0001,0010,...,1001,1010,1011,1100,1101,1110,1111,0000->1递增 //16+0,16+1,16+2,...,16+9,16+a,16+b,16+c,16+d,16+e,16+f, 0->1递增[gliethttp 2007-07-28 唐山]
//从上面的规律可以看出,ip=ip-16,-16<=ip<=0,那么ip的bit3~bit0值就是ip-16之前非负时的ip值 //因此,以16为循环体%16,余取16,扩展为32字节数据处理时,先要判断16字节的组数,如: //因为-32<=ip<=-1,所以 //cmn ip, #16//判断一共有多少个16字节组 //如果ip>=-16,那么表示有有两组16字节组
//2.ip = ip - 4 //对于ip-8有这样一个规律[gliethttp 2007-07-28 唐山] // -8, -7, -6, -5, -4->1递增 // 00, 01, 10, 11, 00->1递增 // 0, 1, 2, 3, 0->1递增
// -4, -3, -2, -1, -0->1递增 // 00, 01, 10, 11, 00->1递增 //4+0,4+1,4+2,4+3, 0->1递增[gliethttp 2007-07-28 唐山]
//从上面的规律可以看出,ip=ip-4,-4<=ip<=0,[-4和0可以合并]那么ip的bit1~bit0值就是ip-4之前非负值时的ip值 //因此,以4为循环体%4,余取4,扩展为8字节数据处理时,先要判断4字节的组数,如: //因为-8<=ip<=-1,所以 //adds r1,r1,#4和cmn r1,#4如出一辙[gliethttp] //检查是否多余4字节数据 adds r1, r1, #4//r1=r1+4,-4<=r1<=3[gliethttp 唐山] USER( strplt r2, [r0], #4)//如果此时r1>=0,说明至少还有4字节未被清0,所以4字节清0,可能触发缺页异常 //因为-4和0可以合并在一起,所以 //-3<=r1<=3 //又因为-3<=r1<=0时bit1,bit0,说明剩余字节数<4,所以bit1,bit0刚好是剩余字节数 //而0<=r1<=3,时,bit1,bit0,值就是-4后字节数,即执行strplt r2, [r0], #4之后剩余字节数 2: tst r1, #2 USER( strnebt r2, [r0], #1)//bit1置位,表明至少还有2字节,对于<0,ip=3,对于>0,ip=6或7 USER( strnebt r2, [r0], #1) tst r1, #1//bit0置位,表示至少还有1个,对于<0,ip=2或3,对于>0,ip=5或7 USER( strnebt r2, [r0], #1) mov r0, #0 LOADREGS(fd, {r1, pc}) //include/asm-arm/proc-armv/Assembler.h //#define LOADREGS(cond, base, reglist...)\ // ldm/**/cond base,reglist //所以展开就是ldmfd sp!,{r0, pc}[gliethttp] .section .fixup,"ax" .align 0 9001: LOADREGS(fd, {r0, pc}) .previous
|