加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

Linux 64位上下文切换

发布时间:2020-12-13 22:57:09 所属栏目:Linux 来源:网络整理
导读:在32位模式的switch_to宏中,在调用__switch_to函数之前执行以下代码: asm volatile("pushflnt" /* save flags */ "pushl %%ebpnt" /* save EBP */ "movl %%esp,%[prev_sp]nt" /* save ESP */ "movl %[next_sp],%%espnt" /* restore ESP */
在32位模式的switch_to宏中,在调用__switch_to函数之前执行以下代码:

asm volatile("pushflnt"       /* save    flags */ 
         "pushl %%ebpnt"      /* save    EBP   */ 
         "movl %%esp,%[prev_sp]nt"    /* save    ESP   */ 
         "movl %[next_sp],%%espnt"    /* restore ESP   */ 
         "movl $1f,%[prev_ip]nt"  /* save    EIP   */ 
         "pushl %[next_ip]nt" /* restore EIP   */ 
         __switch_canary                    
         "jmp __switch_ton"    /* regparm call  */

EIP被压入堆栈(恢复EIP).当__switch_to完成时,会有一个返回到该位置的ret.
这是相应的64位代码:

asm volatile(SAVE_CONTEXT                     
     "movq %%rsp,%P[threadrsp](%[prev])nt" /* save RSP */   
     "movq %P[threadrsp](%[next]),%%rspnt" /* restore RSP */    
     "call __switch_tont"

在那里,只保存和恢复rsp.我认为RIP已经在
堆栈的顶部.但是我无法找到指示的地方.
如何实际完成64位上下文切换,特别是对于RIP寄存器?

提前致谢!

解决方法

在32位内核中,thread.ip可能是以下之一:

> switch_to中的1个标签
> ret_from_fork
> ret_from_kernel_thread

通过使用push jmp对模拟呼叫来确保返回正确的位置.

在64位内核中,thread.ip不是这样使用的.在调用之后执行总是继续(以前是32位情况下的1标签).因此,不需要模拟呼叫,它可以正常完成.在__switch_to返回后使用条件跳转调度到ret_from_fork(您已省略此部分):

#define switch_to(prev,next,last) 
        asm volatile(SAVE_CONTEXT                                         
             "movq %%rsp,%P[threadrsp](%[prev])nt" /* save RSP */       
             "movq %P[threadrsp](%[next]),%%rspnt" /* restore RSP */    
             "call __switch_tont"                                       
             "movq "__percpu_arg([current_task])",%%rsint"              
             __switch_canary                                              
             "movq %P[thread_info](%%rsi),%%r8nt"                       
             "movq %%rax,%%rdint"                                       
             "testl  %[_tif_fork],%P[ti_flags](%%r8)nt"                 
             "jnz   ret_from_forknt"                                    
             RESTORE_CONTEXT                                              

ret_from_kernel_thread包含在ret_from_fork路径中,使用entry_64.S中的另一个条件跳转:

ENTRY(ret_from_fork)
        DEFAULT_FRAME

        LOCK ; btr $TIF_FORK,TI_flags(%r8)

        pushq_cfi $0x0002
        popfq_cfi                               # reset kernel eflags

        call schedule_tail                      # rdi: 'prev' task parameter

        GET_THREAD_INFO(%rcx)

        RESTORE_REST

        testl $3,CS-ARGOFFSET(%rsp)            # from kernel_thread?
        jz   1f

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读