慢慢欣赏linux 系统调用

ENTRY(entry_SYSCALL_64)
	movq	%rsp, PER_CPU_VAR(rsp_scratch)	// 保存用户堆栈指针
	movq	PER_CPU_VAR(cpu_current_top_of_stack), %rsp // 获取tss段作为内核栈
		=># define cpu_current_top_of_stack (cpu_tss_rw + TSS_sp1)
	
	/* 讲用户寄存器压到tss段 */
	/* Construct struct pt_regs on stack */
	pushq	$__USER_DS			/* pt_regs->ss */
	pushq	PER_CPU_VAR(rsp_scratch)	/* pt_regs->sp */
	pushq	%r11				/* pt_regs->flags */
	pushq	$__USER_CS			/* pt_regs->cs */
	pushq	%rcx				/* pt_regs->ip */
GLOBAL(entry_SYSCALL_64_after_hwframe)
	pushq	%rax				/* pt_regs->orig_ax */


	/* IRQs are off. */
	movq	%rsp, %rdi	// rsp 作为内核栈, 也就是说 tss 是内核栈
	call	do_syscall_64		/* returns with IRQs disabled */
	=>__visible void do_syscall_64(struct pt_regs *regs)
		pt_regs的定义如下
		struct pt_regs {
		/*
		 * C ABI says these regs are callee-preserved. They aren't saved on kernel entry
		 * unless syscall needs a complete, fully filled "struct pt_regs".
		 */
			unsigned long r15;
			unsigned long r14;
			unsigned long r13;
			unsigned long r12;
			unsigned long rbp;
			unsigned long rbx;
		/* These regs are callee-clobbered. Always saved on kernel entry. */
			unsigned long r11;
			unsigned long r10;
			unsigned long r9;
			unsigned long r8;
			unsigned long rax;
			unsigned long rcx;
			unsigned long rdx;
			unsigned long rsi;
			unsigned long rdi;
		/*
		 * On syscall entry, this is syscall#. On CPU exception, this is error code.
		 * On hw interrupt, it's IRQ number:
		 */
			unsigned long orig_rax;
		/* Return frame for iretq */
			unsigned long rip;
			unsigned long cs;
			unsigned long eflags;
			unsigned long rsp;
			unsigned long ss;
		/* top of stack page */
		};


	POP_REGS pop_rdi=0 skip_r11rcx=1
	=>.macro POP_REGS pop_rdi=1 skip_r11rcx=0
		popq %r15
		popq %r14
		popq %r13
		popq %r12
		popq %rbp
		popq %rbx
		.if \skip_r11rcx
		popq %rsi
		.else
		popq %r11
		.endif
		popq %r10
		popq %r9
		popq %r8
		popq %rax
		.if \skip_r11rcx
		popq %rsi
		.else
		popq %rcx
		.endif
		popq %rdx
		popq %rsi
		.if \pop_rdi
		popq %rdi
		.endif
	.endm
	
	/*
	 * Now all regs are restored except RSP and RDI.
	 * Save old stack pointer and switch to trampoline stack.
	 */
	movq	%rsp, %rdi
	movq	PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp

	pushq	RSP-RDI(%rdi)	/* RSP */
	pushq	(%rdi)		/* RDI */

	/*
	 * We are on the trampoline stack.  All regs except RDI are live.
	 * We can do future final exit work right here.
	 */
	SWITCH_TO_USER_CR3_STACK scratch_reg=%rdi
	=>.macro SWITCH_TO_USER_CR3_STACK	scratch_reg:req
		pushq	%rax
		SWITCH_TO_USER_CR3_NOSTACK scratch_reg=\scratch_reg scratch_reg2=%rax
		popq	%rax
	.endm

	popq	%rdi
	popq	%rsp
	USERGS_SYSRET64
END(entry_SYSCALL_64)

【Linux系统调用】汇编级理解Linux系统调用
https://blog.csdn.net/Alan_cqu_cj/article/details/106272204

上一篇:pt-online-schema-change添加字段Waiting for table metadata lock等待事件处理


下一篇:Proj THUDBFuzz Paper Reading: CMFuzz: context-aware adaptive mutation for fuzzers