飞腾CPU体系结构之从用户态进入内核态的上下切换

飞腾CPU体系结构之从用户态进入内核态的上下切换

1. 用户态与内核态之间的上下文切换

当飞腾CPU从用户态进入内核态,主要是汇编宏kernel_entry的执行过程;与这个过程相反的是飞腾CPU从内核态退回到用户态,主要是汇编宏kernel_exit。这两个宏的基本定义为

//arch/arm64/kernel/entry.S
/*宏参数el = 0, 表示从用户态进入到内核态
 *宏参数regsize = 64, 这是默认参数,表示是进入内核态之前属于AArch64。 
*/
.macro kernel_entry, el, regsize = 64

.endm

/*宏参数el =0, 表示内核态退回到用户态*/
.macro kernel_exit, el

.endm

2. 从用户态进入内核态的上下切换

我们这里仅仅分析kernel_entry 0的情况,即el = 0且regsize = 64的情况。注意:内核态堆栈寄存器sp为sp_el1。

2.1 将30个通用寄存器保存在堆栈空间上

        stp     x0, x1, [sp, #16 * 0]
        stp     x2, x3, [sp, #16 * 1]
        stp     x4, x5, [sp, #16 * 2]
        stp     x6, x7, [sp, #16 * 3]
        stp     x8, x9, [sp, #16 * 4]
        stp     x10, x11, [sp, #16 * 5]
        stp     x12, x13, [sp, #16 * 6]
        stp     x14, x15, [sp, #16 * 7]
        stp     x16, x17, [sp, #16 * 8]
        stp     x18, x19, [sp, #16 * 9]
        stp     x20, x21, [sp, #16 * 10]
        stp     x22, x23, [sp, #16 * 11]
        stp     x24, x25, [sp, #16 * 12]
        stp     x26, x27, [sp, #16 * 13]
        stp     x28, x29, [sp, #16 * 14]

2.2 将30个通用寄存器清零

该过程用汇编宏clear_gp_regs完成

        .macro  clear_gp_regs
        .irp    n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29
        mov     x\n, xzr
        .endr
        .endm

2.3 在堆栈中保存链接寄存器和指针寄存器sp_el0的值

        mrs     x21, sp_el0
        ...
        stp     lr, x21, [sp, #S_LR]

2.4 关闭软件单步功能

获取进入内核时任务的线程标志,如果设置了TIF_SINGLESTEP(21)标志,就关闭软件单步功能。

        ldr_this_cpu    tsk, __entry_task, x20  // Ensure MDSCR_EL1.SS is clear,
        ldr     x19, [tsk, #TSK_TI_FLAGS]       // since we can unmask debug
        disable_step_tsk x19, x20               // exceptions when scheduling.

1) tsk其实就是寄存器x28,这个注释说是thread_info,很可能不正确,其实是task_struct。

tsk     .req    x28             // current thread_info

2)x20在这个过程中,一直扮演的是中间变量角色,可以暂时不管。

3)线程标志在ldr x19, [tsk, #TSK_TI_FLAGS ]之后就已经读取到寄存器x19中。

4)最后就是标志与TIF_SINGLESTEP(21)进行比较,如果没有设置该标志,就跳转,如果设置了该标志,就将寄存器mdscr_el1的DBG_MDSCR_SS位清零。

5)  在kernel_entry退出之前,要将tsk的值写入寄存器sp_el0

        msr     sp_el0, tsk

2.5 在堆栈中保存异常链接寄存器elr_el1和处理器状态保存寄存器spsr_el1

        mrs     x22, elr_el1
        mrs     x23, spsr_el1
        ...
        stp     x22, x23, [sp, #S_PC]

2.6 在堆栈中占一个系统调用号的坑??

        mov     w21, #NO_SYSCALL
        str     w21, [sp, #S_SYSCALLNO]

猜你喜欢

转载自blog.csdn.net/lsshao/article/details/119381338