积分规则 网站地图 帮助中心    
嵌入式软件 单 片 机 DSP 存储器 传感控制 光电显示
嵌入式硬件 CPLD/FPGA SOPC AD/DA 接口电路 模拟设计
I C设计 通信产品 汽车电子 电源产品 消费电子 数控系统
工业控制 军工/航天 安防产品 医疗电子 计算机外设 测试测量
供应 I C
求购 公司库

  IC 求购 销售 公司 论文 DATASHEET 参考设计 论坛
当前位置: 电子技术 >> 嵌入式硬件 >> MIPS
  相关分类: 相关文章 | ARM | 新产品 | 下载 | MIPS | X86 |
MIPS-Linux Kernel分析(3)
 
作者:陈怀临翻译   来源:嵌入式技术网    点击数:1128   更新时间:2007-1-26
您可以添加到网摘 让更多人关注此文章:

    
好了,说了一通系统调用,无非是想让大家明白内核中寄存器的保存恢复过程,以及
   为了少做些无用功所做的努力.下面看为什么要save_static_function:为了避免
   s0寄存器的破坏.
     如果我们使用
        sys_rt_sigsuspend()
        {   ..
           save_static;
           ...
        }
    会有什么问题呢,请看,
 
    Nasty degree - 3 days of tracking.
 
    The symptom was pthread cannot be created.  In the end the caller will 
    get a BUS error.
 
    What exactly happened has to do with how registers are saved.  Below
    attached is the beginning part of sys_sigsuspend() function.  It is easy
    to see that s0 is saved into stack frame AFTER its modified.  Next time
    when process returns to userland, the s0 reg will be wrong!
 
    So the bug is either
 
    1) that we need to save s0 register in SAVE_SOME and not save it in
    save_static; or that
 
    2) we fix compiler so that it does not use s0 register in that case (it
            does the same thing for sys_rt_sigsuspend)
 
    I am sure Ralf will have something to say about it.  :-)  In any case, I
    attached a patch for 1) fix.
 
sys_sigsuspend(struct pt_regs regs)
{
        8008e280:   27bdffc0        addiu   $sp,$sp,-64
        8008e284:   afb00030        sw      $s0,48($sp)
                   sigset_t *uset, saveset, newset;
 
                    save_static(&regs);
        8008e288:   27b00040        addiu   $s0,$sp,64   /* save_static
                                                            s0已经破坏*/
        8008e28c:   afbf003c        sw      $ra,60($sp)
        8008e290:   afb20038        sw      $s2,56($sp)
        8008e294:   afb10034        sw      $s1,52($sp)
        8008e298:   afa40040        sw      $a0,64($sp)
        8008e29c:   afa50044        sw      $a1,68($sp)
        8008e2a0:   afa60048        sw      $a2,72($sp)
        8008e2a4:   afa7004c        sw      $a3,76($sp)
        8008e2a8:   ae100058        sw      $s0,88($s0)
        8008e2ac:   ae11005c        sw      $s1,92($s0)
 
#ifdef CONFIG_SMP
#  define GET_SAVED_SP                                   \
                mfc0    k0, CP0_CONTEXT;                 \
                lui     k1, %hi(kernelsp);               \
                srl     k0, k0, 23;                      \
               sll     k0, k0, 2;                       \
                addu    k1, k0;                          \
                lw      k1, %lo(kernelsp)(k1);        
 
#else
#  define GET_SAVED_SP                                   \
/*实际上就是k1 = kernelsp, kernelsp保存当前进程的内核栈指针 */
               lui     k1, %hi(kernelsp);               \
               lw      k1, %lo(kernelsp)(k1);           
#endif
 
/*判断当前运行态,设置栈顶sp
  保存寄存器--参数a0-a3:4-7,返回值v0-v1:2-3,25,28,31以及一些控制寄存器,
  */
#define SAVE_SOME                                        \
               .set    push;                            \
               .set    reorder;                         \
               mfc0    k0, CP0_STATUS;                  \
               sll     k0, 3;     /* extract cu0 bit */ \
               .set    noreorder;                       \
               bltz    k0, 8f;                          \
                move   k1, sp;                          \
               .set    reorder;                         \
               /* Called from user mode, new stack. */  \
                GET_SAVED_SP                             \
8:                                                       \
               move    k0, sp;                          \
               subu    sp, k1, PT_SIZE;                 \
               sw      k0, PT_R29(sp);                  \
                sw     $3, PT_R3(sp);                   \
               sw      $0, PT_R0(sp);                  \
               mfc0    v1, CP0_STATUS;                  \
               sw      $2, PT_R2(sp);                   \
               sw      v1, PT_STATUS(sp);               \
               sw      $4, PT_R4(sp);                   \
               mfc0    v1, CP0_CAUSE;                   \
               sw      $5, PT_R5(sp);                   \
               sw      v1, PT_CAUSE(sp);                \
               sw      $6, PT_R6(sp);                   \
               mfc0    v1, CP0_EPC;                     \
               sw      $7, PT_R7(sp);                   \
               sw      v1, PT_EPC(sp);                  \
               sw      $25, PT_R25(sp);                 \
               sw      $28, PT_R28(sp);                 \
               sw      $31, PT_R31(sp);                 \
               ori     $28, sp, 0x1fff;                 \
               xori    $28, 0x1fff;                     \
               .set    pop
 
#define SAVE_ALL                                         \
               SAVE_SOME;                               \
               SAVE_AT;                                 \
               SAVE_TEMP;                               \
               SAVE_STATIC
 
#define RESTORE_AT                                       \
               .set    push;                            \
               .set    noat;                            \
               lw      $1,  PT_R1(sp);                  \
               .set    pop;
 
#define RESTORE_TEMP                                     \
               lw      $24, PT_LO(sp);                  \
               lw      $8, PT_R8(sp);                   \
               lw      $9, PT_R9(sp);                   \
               mtlo    $24;                             \
               lw      $24, PT_HI(sp);                  \
               lw      $10,PT_R10(sp);                  \
               lw      $11, PT_R11(sp);                 \
               mthi    $24;                             \
               lw      $12, PT_R12(sp);                 \
               lw      $13, PT_R13(sp);                 \
               lw      $14, PT_R14(sp);                 \
               lw      $15, PT_R15(sp);                 \
               lw      $24, PT_R24(sp)
 
#define RESTORE_STATIC                                   \
               lw      $16, PT_R16(sp);                 \
               lw      $17, PT_R17(sp);                 \
               lw      $18, PT_R18(sp);                 \
               lw      $19, PT_R19(sp);                 \
               lw      $20, PT_R20(sp);                 \
               lw      $21, PT_R21(sp);                 \
               lw      $22, PT_R22(sp);                 \
               lw      $23, PT_R23(sp);                 \
               lw      $30, PT_R30(sp)
 
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
#define RESTORE_SOME                                     \
               .set    push;                            \
               .set    reorder;                         \
               mfc0    t0, CP0_STATUS;                  \
               .set    pop;                             \
               ori     t0, 0x1f;                        \
               xori    t0, 0x1f;                        \
               mtc0    t0, CP0_STATUS;                  \
               li      v1, 0xff00;                      \
               and     t0, v1;                         \
               lw      v0, PT_STATUS(sp);               \
               nor     v1, $0, v1;                     \
               and     v0, v1;                         \
               or      v0, t0;                         \
               mtc0    v0, CP0_STATUS;                  \
               lw      $31, PT_R31(sp);                 \
               lw      $28, PT_R28(sp);                 \
               lw      $25, PT_R25(sp);                 \
               lw      $7,  PT_R7(sp);                  \
               lw      $6,  PT_R6(sp);                  \
               lw      $5,  PT_R5(sp);                  \
               lw      $4,  PT_R4(sp);                  \
               lw      $3,  PT_R3(sp);                  \
               lw      $2,  PT_R2(sp)
 
#define RESTORE_SP_AND_RET                               \
               .set    push;                           \
               .set    noreorder;                      \
               lw      k0, PT_EPC(sp);                  \
               lw      sp,  PT_R29(sp);                 \
               jr      k0;                              \
                rfe;                                  \
                ^^^^^
/* 异常返回时,把控制转移到用户代码和把模式从内核态改为用户态要同时完成
   如果前者先完成,用户态指令有机会以内核态运行导致安全漏洞;
   反之则会由于用户态下不能修改状态而导致异常
   r3000以前使用rfe(restore from exception)指令,这个指令把status寄存器
   状态位修改回异常发生前的状态(利用硬件的一个小堆栈),但不做跳转.我们使用一个
   技巧来完成要求:在一个跳转指令的delay slot中放rte.因为delay slot的指令
   是一定会做的,跳转完成时,status也恢复了.
   MIPS III(r4000)以上的指令集则增加了eret指令来完成整个工作: 它清除
   status寄存器的EXL位并跳转到epc指定的位置.
*/
 
               .set    pop
 
#else
 
#define RESTORE_SOME                                     \
               .set    push;                            \
               .set    reorder;                         \
               mfc0    t0, CP0_STATUS;                  \
               .set    pop;                             \
               ori     t0, 0x1f;                        \
               xori    t0, 0x1f;                        \
               mtc0    t0, CP0_STATUS;                  \
               li      v1, 0xff00;                      \
               and     t0, v1;                         \
               lw      v0, PT_STATUS(sp);               \
               nor     v1, $0, v1;                     \
               and     v0, v1;                         \
               or      v0, t0;                         \
               mtc0    v0, CP0_STATUS;                  \
               lw      v1, PT_EPC(sp);                  \
               mtc0    v1, CP0_EPC;                     \
               lw      $31, PT_R31(sp);                 \
               lw      $28, PT_R28(sp);                 \
               lw      $25, PT_R25(sp);                 \
               lw      $7,  PT_R7(sp);                  \
               lw      $6,  PT_R6(sp);                  \
               lw      $5,  PT_R5(sp);                  \
               lw      $4,  PT_R4(sp);                  \
               lw      $3,  PT_R3(sp);                  \
               lw      $2,  PT_R2(sp)
 
#define RESTORE_SP_AND_RET                               \
               lw      sp,  PT_R29(sp);                 \
               .set    mips3;                          \
               eret;                                  \
               .set    mips0
 
#endif
 
#define RESTORE_SP                                       \
               lw      sp,  PT_R29(sp);                 \
 
#define RESTORE_ALL                                      \
               RESTORE_SOME;                            \
               RESTORE_AT;                              \
               RESTORE_TEMP;                            \
               RESTORE_STATIC;                          \
               RESTORE_SP
 
#define RESTORE_ALL_AND_RET                              \
               RESTORE_SOME;                            \
               RESTORE_AT;                              \
               RESTORE_TEMP;                            \
               RESTORE_STATIC;                          \
               RESTORE_SP_AND_RET
 
 
/*
 * Move to kernel mode and disable interrupts.
 * Set cp0 enable bit as sign that we're running on the kernel stack
 */
#define CLI                                             \
               mfc0    t0,CP0_STATUS;                  \
               li      t1,ST0_CU0|0x1f;                \
               or      t0,t1;                          \
               xori    t0,0x1f;                        \
               mtc0    t0,CP0_STATUS
 
/*
 * Move to kernel mode and enable interrupts.
 * Set cp0 enable bit as sign that we're running on the kernel stack
 */
#define STI                                             \
               mfc0    t0,CP0_STATUS;                  \
               li      t1,ST0_CU0|0x1f;                \
               or      t0,t1;                          \
               xori    t0,0x1e;                        \
               mtc0    t0,CP0_STATUS
 
/*
 * Just move to kernel mode and leave interrupts as they are.
 * Set cp0 enable bit as sign that we're running on the kernel stack
 */
#define KMODE                                           \
               mfc0    t0,CP0_STATUS;                  \
               li      t1,ST0_CU0|0x1e;                \
               or      t0,t1;                          \
               xori    t0,0x1e;                        \
               mtc0    t0,CP0_STATUS
 
#endif /* __ASM_STACKFRAME_H */


相关文章
· 科技奥运与计算机技术的应用[282]
· Electromedical[2577]
· 患者监控[2626]
· 基于TMS320LF2407A DSP的心电监护系统研究[3041]
· 用S3C2410实现三导联远程心电监护系统[2977]
热门评论排行
·VHDL设计中电路简化问题的
·江苏嵌入式Linux教育培训
·锐极LINUX驱动培训班定于
·基于实时操作系统μC/OS-
·ARM处理器应用开发4步骤

文章评论
    没有任何评论
*只显示最新10条评论。评论内容只代表网友观点,与本站立场无关。更多评论
发表评论
  * 请先[登陆]再进行评论,谢谢。
评分: 1分 2分 3分 4分 5分
内容: *
发帖须知:
一.所发文章必须遵守《互联网电子公告服务管理规定》;
二.严禁发布供求代理信息,公司介绍,产品信息等广告宣传信息;
三.严禁恶意重复发帖;
四.严禁对个人,实体,民族,国家等进行漫骂,污蔑,诽谤。
 
热点新闻 [更多]
 
Hitachi Elect
中国芯片供需缺口达七成
西班牙研发出视觉鼠标 眨眼
首条OLED生产线昆山投产 
宇航服电子元器件:航天员的“生命保护
美研发出可卷曲太阳能电池
美国研发嗅觉感受器获新进展 
首尔半导体就日亚(NICHIA)专利
MIPS 科技授权国家集成
美国微芯科技公司与安森美半导体拟以每
 
热门下载 [更多]
 
[ PCB设计] Protel99教程下载
[ ] 手把手学单片机20个例
[ ] 单片机做的智能台灯
[ ] 单片机入门书
[ ] linux系统移植开发文档
[ ] IC卡的读写程序
[ ] 8051单片机C语言彻底应用
[ 常用软件] 555定时器电路设计软件V1.2
[ 常用软件] 51定时器计算软件
[ ] ARM处理器应用开发4步骤
 
论坛新帖 [更多]
 
Agilent代理商 0755...
AD代理商 0755-8832...
Actel代理商 0755-8...
嵌入式系统免费网上学习!...
ARM与uClinux...
ARM与uClinux...
NORDIC最新推出nRF24...
网络摄像机技术的调试与测试...
对于新人,为什么公司不再会成为...
[转帖]低价销售各种数码相机,...

 
赞助商 [更多]
 

ICP许可证号:[粤 05056597]
联系电话:010-82517432 82517615 传真: 010-82517615

版权所有 Copyright © 2006 嵌入式技术网