asm volatile("pushfl\n\t" /* save flags */ \ "pushl %%ebp\n\t" /* save EBP */ \ "movl %%esp,%[prev_sp]\n\t" /* save ESP */ \ "movl %[next_sp],%%esp\n\t" /* restore ESP */ \ "movl f,%[prev_ip]\n\t" /* save EIP */ \ "pushl %[next_ip]\n\t" /* restore EIP */ \ __switch_canary \ "jmp __switch_to\n" /* regparm call */
EIP被压入堆栈(恢复EIP).当__switch_to完成时,会有一个返回到该位置的ret.
这是相应的64位代码:
asm volatile(SAVE_CONTEXT \ "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \ "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \ "call __switch_to\n\t"
在那里,只保存和恢复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])\n\t" /* save RSP */ \ "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \ "call __switch_to\n\t" \ "movq "__percpu_arg([current_task])",%%rsi\n\t" \ __switch_canary \ "movq %P[thread_info](%%rsi),%%r8\n\t" \ "movq %%rax,%%rdi\n\t" \ "testl %[_tif_fork],%P[ti_flags](%%r8)\n\t" \ "jnz ret_from_fork\n\t" \ 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 x0002 popfq_cfi # reset kernel eflags call schedule_tail # rdi: 'prev' task parameter GET_THREAD_INFO(%rcx) RESTORE_REST testl ,CS-ARGOFFSET(%rsp) # from kernel_thread? jz 1f总结
以上是内存溢出为你收集整理的Linux 64位上下文切换全部内容,希望文章能够帮你解决Linux 64位上下文切换所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)