(kernel-4.19/arch/arm64/kernel/entry.S)el0_svc:mov x0, spbl el0_svc_handlerb ret_to_userENDPROC(el0_svc)(kernel-4.19/arch/arm64/kernel/syscall.c)
asmlinkage voidel0_svc_handler(struct pt_regs *regs){sve_user_discard();el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table);}staticvoidel0_svc_common(struct pt_regs *regs,int scno,int sc_nr,const syscall_fn_t syscall_table[]){unsignedlong flags =current_thread_info()->flags;regs->orig_x0 = regs->regs[0];regs->syscallno = scno;cortex_a76_erratum_1463225_svc_handler();local_daif_restore(DAIF_PROCCTX);user_exit();if(has_syscall_work(flags)){/* set default errno for user-issued syscall(-1) */if(scno == NO_SYSCALL)regs->regs[0]=-ENOSYS;scno =syscall_trace_enter(regs);if(scno == NO_SYSCALL)goto trace_exit;}invoke_syscall(regs, scno, sc_nr, syscall_table);/** The tracing status may have changed under our feet, so we have to* check again. However, if we were tracing entry, then we always trace* exit regardless, as the old entry assembly did.*/if(!has_syscall_work(flags)&&!IS_ENABLED(CONFIG_DEBUG_RSEQ)){local_daif_mask();flags =current_thread_info()->flags;if(!has_syscall_work(flags)){/** We're off to userspace, where interrupts are* always enabled after we restore the flags from* the SPSR.*/trace_hardirqs_on();return;}local_daif_restore(DAIF_PROCCTX);}trace_exit:syscall_trace_exit(regs);}staticvoidinvoke_syscall(struct pt_regs *regs,unsignedint scno,unsignedint sc_nr,const syscall_fn_t syscall_table[]){long ret;if(scno < sc_nr){syscall_fn_t syscall_fn;syscall_fn = syscall_table[array_index_nospec(scno, sc_nr)];ret =__invoke_syscall(regs, syscall_fn);//syscall_fn 就是tab表中的函數(shù)}else{ret =do_ni_syscall(regs, scno);}regs->regs[0]= ret;}staticlong__invoke_syscall(struct pt_regs *regs, syscall_fn_t syscall_fn){returnsyscall_fn(regs);//調(diào)用tab表中的函數(shù)}