Linux 64位上下文开关
在32位模式下的switch_to宏中,在调用switch_to函数之前执行以下代码:Linux 64位上下文开关,linux,assembly,linux-kernel,x86,x86-64,Linux,Assembly,Linux Kernel,X86,X86 64,在32位模式下的switch_to宏中,在调用switch_to函数之前执行以下代码: 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"
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 $1f,%[prev_ip]\n\t" /* save EIP */ \
"pushl %[next_ip]\n\t" /* restore EIP */ \
__switch_canary \
"jmp __switch_to\n" /* regparm call */
EIP被推送到堆栈上(还原EIP)。当切换到结束时,有一个返回到该位置的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。我想裂缝已经开始了
堆栈的顶部。但我找不到这样做的指导。
64位上下文切换,特别是对于RIP寄存器,实际上是如何完成的
提前谢谢 在32位内核中,
线程.ip
可能是以下之一:
中的
标签切换到1
ret\u from\u fork
ret\u from\u kernel\u thread
push
+jmp
对模拟调用
,可以确保返回到正确的位置
在64位内核中,thread.ip
不是这样使用的。执行总是在调用后继续执行(在32位的情况下,它曾经是1
标签)。因此,不需要模拟调用
,它可以正常完成。在切换到返回后,使用条件跳转将从\u fork
发送到ret\u(您省略了此部分):
使用entry\u 64.S
中的另一个条件跳转,将ret\u from\u kernel\u线程
合并到ret\u from\u fork
路径中:
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
call
显然保存了%%rip
。是的,但我们讨论的是下一个进程的rip。它以相同的方式保存在目标堆栈上
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