• arm64系统调用分析


    1、理解整个中断/系统调用流程的关键是kernel_entry和kernel_exit,也就是如何保存现场,并且恢复现场的。

    我们先来看下armv8的寄存器,PLR(X30)无论是用户态还是内核态都用这个寄存器来存储程序的返回值。

    sp_el0,sp_el1分别是有用户态和内核态的堆栈。

    ELR_EL1用于存储,当在发生系统调用、异常、中断时,当前程序的pc值(无论是用户态还是内核态)。

    SPSR_EL1用于存储,当在发生系统调用、异常、中断时,当前程序的PSTATE(无论是用户态还是内核态)。

     

    2、当发生中断、异常、系统调用时,硬件会自动:

    1)把当前程序的pc值放入ELR_EL1中

    2)把当前状态PSTATE存入SPSR_EL1中

    3)根据发生在内核态还是用户态,中断还是异常,会自动跳转到el1_sync,el1_irq,el0_sync,el0_irq

    4)改变PSTATE,如果是用户态发生中断、异常、系统调用,此时已经进入内核态,堆栈是sp_el1。

    3、kernel_entry

     

    执行完kernel_entry的堆栈,ELR_EL1存放的是返回的PC值,SPSR_EL1存放的是返回的PSTATE。

    如果是用户态发生的中断、异常、系统调用,则栈中保存都是用户态的寄存器信息。

    如果是内核态发生的中断、异常,则栈中保存的内核态的寄存器信息。

    4、kernel_exit

    前面我们已经说过:

    el1_sync,el1_irq调用的是kernel_entry 1,kernel_exit 1,也就是上面宏el为1。

    el0_sync,el0_irq调用的是kernel_entry 0,kernel_exit 0,也就是上面宏el为0。

    我们可以看到 .macro kernel_exit, el, ret = 0,还有一个参数ret,只有在el0_sync处理系统调用时会被置成1。

    发生中断、异常、系统调用前是用户态,则返回用户态的寄存器(pc,lr,sp_el0,pstate)。注意还要把内核态的栈平衡了:ldr lr, [sp], #S_FRAME_SIZE - S_LR // 恢复lr,恢复内核sp_el1

    发生中断、异常、系统调用前是内核态,则返回内核态的寄存器(pc,lr,sp_el1,pstate)。

    如果处理系统调用x0存放的是系统的调用的返回值,所以不需要从堆栈中恢复。

     系统调用实现

    .macro kernel_ventry, el, label, regsize = 64
    .align = 7   // 地址对齐要求
    sub sp, sp, #S_FRAME_SIZE   //堆栈指针处理
    b el\()\el\()_\label        //跳转
    .endm

    系统调用是从“kernel_ventry 0, sync”进入,即el=0,label=sync。因此最终跳转进入el0_sync汇编

    其中" \()"是汇编符号连接,\el和\label是汇编宏的参数引用。

    汇编宏el0_sync

    汇编宏el0_sync主要分为两部分:第一部分实现从用户空间到内核空间的上下文切换, kernel_entry 0;第二部是根据异常症状寄存器esr_el1判断异常原因,然后再进入具体处理函数。系统调用是用户态执行SVC指令导致的,因此要进入el0_svc处理函数。
     

    /*
     * EL0 mode handlers.
     */
            .align  6
    el0_sync:
            kernel_entry 0
            mrs     x25, esr_el1                    // read the syndrome register
            lsr     x24, x25, #ESR_ELx_EC_SHIFT     // exception class
            cmp     x24, #ESR_ELx_EC_SVC64          // SVC in 64-bit state 
            b.eq    el0_svc                         // 这系统调用入口
            cmp     x24, #ESR_ELx_EC_DABT_LOW       // data abort in EL0
            b.eq    el0_da
            cmp     x24, #ESR_ELx_EC_IABT_LOW       // instruction abort in EL0
            b.eq    el0_ia
            cmp     x24, #ESR_ELx_EC_FP_ASIMD       // FP/ASIMD access
            b.eq    el0_fpsimd_acc
            cmp     x24, #ESR_ELx_EC_SVE            // SVE access
            b.eq    el0_sve_acc
            cmp     x24, #ESR_ELx_EC_FP_EXC64       // FP/ASIMD exception
            b.eq    el0_fpsimd_exc
            cmp     x24, #ESR_ELx_EC_SYS64          // configurable trap
            ccmp    x24, #ESR_ELx_EC_WFx, #4, ne
            b.eq    el0_sys
            cmp     x24, #ESR_ELx_EC_SP_ALIGN       // stack alignment exception
            b.eq    el0_sp
            cmp     x24, #ESR_ELx_EC_PC_ALIGN       // pc alignment exception
            b.eq    el0_pc
            cmp     x24, #ESR_ELx_EC_UNKNOWN        // unknown exception in EL0
            b.eq    el0_undef
            cmp     x24, #ESR_ELx_EC_BREAKPT_LOW    // debug exception in EL0
            b.ge    el0_dbg
            b       el0_inv
     


     

    案例

    [root@centos7 arm]# uname -a
    Linux centos7 4.14.0-115.el7a.0.1.aarch64 #1 SMP Sun Nov 25 20:54:21 UTC 2018 aarch64 aarch64 aarch64 GNU/Linux
    [root@centos7 arm]#

    svc指令

    //静态编译
    [root@centos7 arm]# gcc test.c -o test --static
    //反汇编
    objdump -D  test > test.txt




     20634 0000000000413d8c <__libc_open>:
     20635   413d8c:       a9af7bfd        stp     x29, x30, [sp,#-272]!
     20636   413d90:       910003fd        mov     x29, sp
     20637   413d94:       f90073a2        str     x2, [x29,#224]
     20638   413d98:       a90153f3        stp     x19, x20, [sp,#16]
     20639   413d9c:       2a0103e2        mov     w2, w1
     20640   413da0:       f90077a3        str     x3, [x29,#232]
     20641   413da4:       f9007ba4        str     x4, [x29,#240]
     20642   413da8:       f9007fa5        str     x5, [x29,#248]
     20643   413dac:       f90083a6        str     x6, [x29,#256]
     20644   413db0:       f90087a7        str     x7, [x29,#264]
     20645   413db4:       3d801ba0        str     q0, [x29,#96]
     20646   413db8:       3d801fa1        str     q1, [x29,#112]
     20647   413dbc:       3d8023a2        str     q2, [x29,#128]
     20648   413dc0:       3d8027a3        str     q3, [x29,#144]
     20649   413dc4:       3d802ba4        str     q4, [x29,#160]
     20650   413dc8:       3d802fa5        str     q5, [x29,#176]
     20651   413dcc:       3d8033a6        str     q6, [x29,#192]
     20652   413dd0:       3d8037a7        str     q7, [x29,#208]
     20653   413dd4:       aa0003e1        mov     x1, x0
     20654   413dd8:       37300262        tbnz    w2, #6, 413e24 <__libc_open+0x98>
     20655   413ddc:       52880003        mov     w3, #0x4000                     // #16384
     20656   413de0:       72a00803        movk    w3, #0x40, lsl #16
     20657   413de4:       0a030043        and     w3, w2, w3
     20658   413de8:       7150107f        cmp     w3, #0x404, lsl #12
     20659   413dec:       d2800003        mov     x3, #0x0                        // #0
     20660   413df0:       540001a0        b.eq    413e24 <__libc_open+0x98>
     20661   413df4:       f0000460        adrp    x0, 4a2000 <initial+0x248>
     20662   413df8:       b94f0800        ldr     w0, [x0,#3848]
     20663   413dfc:       35000380        cbnz    w0, 413e6c <__libc_open+0xe0>
     20664   413e00:       92800c60        mov     x0, #0xffffffffffffff9c         // #-100
     20665   413e04:       93407c42        sxtw    x2, w2
     20666   413e08:       d2800708        mov     x8, #0x38                       // #56
     20667   413e0c:       d4000001        svc     #0x0
     20668   413e10:       b140041f        cmn     x0, #0x1, lsl #12
     20669   413e14:       540001e8        b.hi    413e50 <__libc_open+0xc4>
     20670   413e18:       a94153f3        ldp     x19, x20, [sp,#16]
     20671   413e1c:       a8d17bfd        ldp     x29, x30, [sp],#272
     20672   413e20:       d65f03c0        ret
     20673   413e24:       910383a0        add     x0, x29, #0xe0
     20674   413e28:       f9002ba0        str     x0, [x29,#80]
     20675   413e2c:       128005e0        mov     w0, #0xffffffd0                 // #-48
     20676   413e30:       910443a4        add     x4, x29, #0x110
     20677   413e34:       b9005ba0        str     w0, [x29,#88]
     20678   413e38:       12800fe0        mov     w0, #0xffffff80                 // #-128
     20679   413e3c:       b980e3a3        ldrsw   x3, [x29,#224]
     20680   413e40:       f90023a4        str     x4, [x29,#64]
     20681   413e44:       f90027a4        str     x4, [x29,#72]
     20682   413e48:       b9005fa0        str     w0, [x29,#92]
     20683   413e4c:       17ffffea        b       413df4 <__libc_open+0x68>
     20684   413e50:       90000462        adrp    x2, 49f000 <__FRAME_END__+0x10aa8>
     20685   413e54:       f947c842        ldr     x2, [x2,#3984]
     20686   413e58:       4b0003e0        neg     w0, w0
     20687   413e5c:       d53bd041        mrs     x1, tpidr_el0
     20688   413e60:       b8226820        str     w0, [x1,x2]
     20689   413e64:       92800000        mov     x0, #0xffffffffffffffff         // #-1
     20690   413e68:       17ffffec        b       413e18 <__libc_open+0x8c>
     20691   413e6c:       f9001ba1        str     x1, [x29,#48]

    可以看到将寄存器x8设置为系统调用号0x38 (openat),
    然后调用了svc进入异常处理。

    进入异常模式后,内核根据异常类型(同步异常)及当前所处的ELx, 调用相应的异常处理函数,这里是el0_sync。

    进入异常模式后,内核根据异常类型(同步异常)及当前所处的ELx, 调用相应的异常处理函数,这里是el0_sync。
    arch/arm64/kernel/entry.S
    Screen Shot 2021-06-18 at 1.43.32 PM.png

    Screen Shot 2021-06-18 at 1.46.03 PM.png
    667,668行:通过读取esr_el1得到产生异常的原因,保存到寄存器x24
    669行:判断x24中保存的异常原因是否为svc
    670行:上一行如果判断相等,调用el0_svc
    Screen Shot 2021-06-18 at 1.47.26 PM.png
    914行:读入syscall table的指针
    915行:将系统调用号(w8)保存到wscno中,上面的讲解中libc库将系统调用号写入了x8寄存器
    928行:以系统调用号为索引,得到syscall table表中相应的函数地址,这里就是sys_openat
    929行:调用sys_openat




    更详细分析见:

    https://cloud.tencent.com/developer/article/1413292

  • 相关阅读:
    数据仓库与数据挖掘的一些基本概念
    System.currentTimeMillis();
    html练习(3)
    HDU 1556 Color the ball【算法的优化】
    ubuntu12.04 安装配置jdk1.7
    java中的switch用String作为条件
    oracle中 connect by prior 递归算法
    C#复习题
    AngularJS:Http
    AngularJS:Service
  • 原文地址:https://www.cnblogs.com/dream397/p/15993907.html
Copyright © 2020-2023  润新知