Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15531670
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2007-07-29 13:32:22

浅析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

阅读(2311) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~