ARM64 커널 시스템 호출 상세 정보(kernel-4.9 기반)
20214 단어 커널 노트
우선 이상 벡터표의 설정을 보십시오. 내부 핵은arch/arm64/kernel/entry에 있습니다.S 어셈블리 코드에 비정상 벡터 테이블이 설정되어 있습니다.
/*
* Exception vectors.
*/
.pushsection ".entry.text", "ax"
.align 11
ENTRY(vectors)
kernel_ventry 1, sync_invalid // Synchronous EL1t
kernel_ventry 1, irq_invalid // IRQ EL1t
kernel_ventry 1, fiq_invalid // FIQ EL1t
kernel_ventry 1, error_invalid // Error EL1t
kernel_ventry 1, sync // Synchronous EL1h
kernel_ventry 1, irq // IRQ EL1h
kernel_ventry 1, fiq_invalid // FIQ EL1h
kernel_ventry 1, error_invalid // Error EL1h
kernel_ventry 0, sync // Synchronous 64-bit EL0
kernel_ventry 0, irq // IRQ 64-bit EL0
kernel_ventry 0, fiq_invalid // FIQ 64-bit EL0
kernel_ventry 0, error_invalid // Error 64-bit EL0
#ifdef CONFIG_COMPAT
kernel_ventry 0, sync_compat, 32 // Synchronous 32-bit EL0
kernel_ventry 0, irq_compat, 32 // IRQ 32-bit EL0
kernel_ventry 0, fiq_invalid_compat, 32 // FIQ 32-bit EL0
kernel_ventry 0, error_invalid_compat, 32 // Error 32-bit EL0
#else
kernel_ventry 0, sync_invalid, 32 // Synchronous 32-bit EL0
kernel_ventry 0, irq_invalid, 32 // IRQ 32-bit EL0
kernel_ventry 0, fiq_invalid, 32 // FIQ 32-bit EL0
kernel_ventry 0, error_invalid, 32 // Error 32-bit EL0
#endif
END(vectors)
위의 코드는 서로 다른 모델 아래의 이상 벡터표를 설정해도 이상은 4개 조로 나눌 수 있고 각 조의 이상은 4개 있기 때문에 여기에 모두 16개의 entry를 설정한다.4조의 이상은 각각 4가지 상황에서 이상이 발생할 때의 처리에 대응한다.위의 4개 그룹은 다음과 같은 4가지 상황에 순서대로 대응한다.
(1) ELx에서 ELx로 운영 수준 전환 없이 SP 사용EL0, 이 경우 Linuxkernel에서 처리되지 않으며 invalid entry를 사용합니다.
(2) ELx에서 ELx로 운영 단계 전환 없이 SP 사용ELx.이 경우 Linux에서 흔히 볼 수 있습니다.
(3) 이상은 레벨 전환을 통해 처리해야 하고aarch64 모드로 처리해야 한다. 예를 들어 64비트 사용자 모드 프로그램에서 시스템 호출이 발생하면 CPU는 EL0에서 EL1로 전환되고aarch64 모드로 이상을 처리한다.
(4) 이상은 단계 전환을 통해 처리하고aarch32 모드로 처리해야 한다.예를 들어 32개의 사용자 상태 프로그램이 시스템 호출을 일으키면 CPU는 EL0에서 EL1로 전환되고aarch32 모드로 처리된다.
앞에 이상 벡터표가 설정되어 있습니다. SVC 모드의 처리를 더 살펴보겠습니다.시스템이 호출될 때 CPU는 SVC mode로 전환되고 해당하는 주소로 이동합니다.
kernel에서 SVC Handler 두 개를 구성하여 각각 SVC32/SVC_64 두 가지 모델, 32bit 프로그램과 64bit 프로그램 실행 시스템 호출은 두 개의handler로 이동합니다.
커널은arch/arm64/kernel/entry에 있습니다.SVC 예외 entry가 S-어셈블리 코드에 설정되어 있습니다.
64-bit 실행 모드 확인
다음 함수는 64-bit 상태의 예외 벡터 테이블 설정을 설정합니다. 여기서 빨간색 부분은 svc handler 구성입니다.
arch/arm64/kernel/entry.S:
.align 6
el0_sync:
kernel_entry 0
mrs x25, esr_el1 // read the syndrome register
lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class
cmp x24, #ESR_ELx_EC_SVC64 // SVC in 64-bit state
b.eq el0_svc
cmp x24, #ESR_ELx_EC_DABT_LOW // data abort in EL0
b.eq el0_da
cmp x24, #ESR_ELx_EC_IABT_LOW // instruction abort in EL0
b.eq el0_ia
cmp x24, #ESR_ELx_EC_FP_ASIMD // FP/ASIMD access
b.eq el0_fpsimd_acc
cmp x24, #ESR_ELx_EC_FP_EXC64 // FP/ASIMD exception
b.eq el0_fpsimd_exc
cmp x24, #ESR_ELx_EC_SYS64 // configurable trap
b.eq el0_sys
cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
b.eq el0_sp_pc
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
b.eq el0_sp_pc
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
b.eq el0_undef
cmp x24, #ESR_ELx_EC_BREAKPT_LOW // debug exception in EL0
b.ge el0_dbg
b el0_inv
el0_svc의 구현은 다음과 같습니다.
/*
* SVC handler.
*/
.align 6
el0_svc:
adrp stbl, sys_call_table // load syscall table pointer
uxtw scno, w8 // syscall number in w8
mov sc_nr, #__NR_syscalls
el0_svc_naked: // compat entry point
stp x0, scno, [sp, #S_ORIG_X0] // save the original x0 and syscall number
enable_dbg_and_irq
ct_user_exit 1
ldr x16, [tsk, #TSK_TI_FLAGS] // check for syscall hooks
tst x16, #_TIF_SYSCALL_WORK
b.ne __sys_trace
cmp scno, sc_nr // check upper syscall limit
b.hs ni_sys
ldr x16, [stbl, scno, lsl #3] // address in the syscall table
blr x16 // call sys_* routine
b ret_fast_syscall
ni_sys:
mov x0, sp
bl do_ni_syscall
b ret_fast_syscall
ENDPROC(el0_svc)
보시면 sys를 찾으러 갈 거예요call_table 이 그룹을 찾아서 대응하는 시스템 호출 함수를 찾으십시오. 그 중 관건적인 함수do 가 있음을 주의하십시오.ni_syscall, (no implement syscall) 시스템 호출이 제한이나 문제에 부딪혔을 때 이 함수로 이동합니다.
sys_call_테이블의 정의는 다음 파일에 있습니다.
arch/arm64/kernel/sys.c:
/*
* The sys_call_table array must be 4K aligned to be accessible from
* kernel/entry.S.
*/
void * const sys_call_table[__NR_syscalls] __aligned(4096) = {
[0 ... __NR_syscalls - 1] = sys_ni_syscall,
#include
};
이 그룹은 만들 때 우선 모든 그룹 구성원을sys 로 설정합니다ni_syscall 이후 asm/unistd에 따라h의 내용을 한층 더 초기화하다.사실 최종적으로 이 헤더 파일은include/uapi/asm-generic//unistd를h가 포함됩니다. 즉, 이 헤더 파일은 최종적으로 그룹을 정의하는 곳입니다.
......
__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
#define __NR_ustat 1070
__SYSCALL(__NR_ustat, sys_ustat)
#define __NR_vfork 1071
__SYSCALL(__NR_vfork, sys_vfork)
#define __NR_oldwait4 1072
__SYSCALL(__NR_oldwait4, sys_wait4)
#define __NR_recv 1073
__SYSCALL(__NR_recv, sys_recv)
#define __NR_send 1074
__SYSCALL(__NR_send, sys_send)
#define __NR_bdflush 1075
__SYSCALL(__NR_bdflush, sys_bdflush)
#define __NR_umount 1076
__SYSCALL(__NR_umount, sys_oldumount)
#define __ARCH_WANT_SYS_OLDUMOUNT
#define __NR_uselib 1077
__SYSCALL(__NR_uselib, sys_uselib)
#define __NR__sysctl 1078
__SYSCALL(__NR__sysctl, sys_sysctl)
#define __NR_fork 1079
#ifdef CONFIG_MMU
__SYSCALL(__NR_fork, sys_fork)
#else
__SYSCALL(__NR_fork, sys_ni_syscall)
#endif /* CONFIG_MMU */
......
32-bit 실행 모드 분석
다음 함수는 32-bit 상태의 비정상 벡터 테이블 설정을 설정합니다. 여기서 빨간색 부분은 svc handler 구성입니다.
arch/arm64/kernel/entry.S
#ifdef CONFIG_COMPAT
.align 6
el0_sync_compat:
kernel_entry 0, 32
mrs x25, esr_el1 // read the syndrome register
lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class
cmp x24, #ESR_ELx_EC_SVC32 // SVC in 32-bit state
b.eq el0_svc_compat
cmp x24, #ESR_ELx_EC_DABT_LOW // data abort in EL0
b.eq el0_da
cmp x24, #ESR_ELx_EC_IABT_LOW // instruction abort in EL0
b.eq el0_ia
cmp x24, #ESR_ELx_EC_FP_ASIMD // FP/ASIMD access
b.eq el0_fpsimd_acc
cmp x24, #ESR_ELx_EC_FP_EXC32 // FP/ASIMD exception
b.eq el0_fpsimd_exc
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
b.eq el0_sp_pc
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
b.eq el0_undef
cmp x24, #ESR_ELx_EC_CP15_32 // CP15 MRC/MCR trap
b.eq el0_undef
cmp x24, #ESR_ELx_EC_CP15_64 // CP15 MRRC/MCRR trap
b.eq el0_undef
cmp x24, #ESR_ELx_EC_CP14_MR // CP14 MRC/MCR trap
b.eq el0_undef
cmp x24, #ESR_ELx_EC_CP14_LS // CP14 LDC/STC trap
b.eq el0_undef
cmp x24, #ESR_ELx_EC_CP14_64 // CP14 MRRC/MCRR trap
b.eq el0_undef
cmp x24, #ESR_ELx_EC_BREAKPT_LOW // debug exception in EL0
b.ge el0_dbg
b el0_inv
el0_svc_compat:
/*
* AArch32 syscall handling
*/
adrp stbl, compat_sys_call_table // load compat syscall table pointer
uxtw scno, w7 // syscall number in w7 (r7)
mov sc_nr, #__NR_compat_syscalls
b el0_svc_naked
.align 6
el0_irq_compat:
kernel_entry 0, 32
b el0_irq_naked
#endif
el0_svc_compat의 구현은 다음과 같습니다.
el0_svc_compat:
/*
* AArch32 syscall handling
*/
adrp stbl, compat_sys_call_table // load compat syscall table pointer
uxtw scno, w7 // syscall number in w7 (r7)
mov sc_nr, #__NR_compat_syscalls
b el0_svc_naked
.align 6
el0_irq_compat:
kernel_entry 0, 32
b el0_irq_naked
보시면 compat을 찾으러 갈 거예요sys_call_table 이 그룹을 찾아서 대응하는 시스템 호출 함수를 찾으십시오.compatsys_call_테이블의 정의는 다음 파일에 있습니다.
arch/arm64/kernel/sys32.c:
/*
* The sys_call_table array must be 4K aligned to be accessible from
* kernel/entry.S.
*/
void * const compat_sys_call_table[__NR_compat_syscalls] __aligned(4096) = {
[0 ... __NR_compat_syscalls - 1] = sys_ni_syscall,
#include
};
이 그룹은 만들 때 우선 모든 그룹 구성원을sys 로 설정합니다ni_syscall, 이후 asm/unistd32.h의 내용을 한층 더 초기화하다.사실 이 헤더 파일은arch/arm64/include/asm/unistd32를h가 포함됩니다. 즉, 이 헤더 파일은 최종적으로 함수 그룹을 정의하는 곳입니다.
arch/arm64/include/asm/unistd32.h:
......
__SYSCALL(__NR_process_vm_writev, compat_sys_process_vm_writev)
#define __NR_kcmp 378
__SYSCALL(__NR_kcmp, sys_kcmp)
#define __NR_finit_module 379
__SYSCALL(__NR_finit_module, sys_finit_module)
#define __NR_sched_setattr 380
__SYSCALL(__NR_sched_setattr, sys_sched_setattr)
#define __NR_sched_getattr 381
__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
#define __NR_renameat2 382
__SYSCALL(__NR_renameat2, sys_renameat2)
#define __NR_seccomp 383
__SYSCALL(__NR_seccomp, sys_seccomp)
#define __NR_getrandom 384
__SYSCALL(__NR_getrandom, sys_getrandom)
#define __NR_memfd_create 385
__SYSCALL(__NR_memfd_create, sys_memfd_create)
#define __NR_bpf 386
__SYSCALL(__NR_bpf, sys_bpf)
#define __NR_execveat 387
__SYSCALL(__NR_execveat, compat_sys_execveat)
#define __NR_userfaultfd 388
__SYSCALL(__NR_userfaultfd, sys_userfaultfd)
#define __NR_membarrier 389
__SYSCALL(__NR_membarrier, sys_membarrier)
#define __NR_mlock2 390
__SYSCALL(__NR_mlock2, sys_mlock2)
#define __NR_copy_file_range 391
__SYSCALL(__NR_copy_file_range, sys_copy_file_range)
#define __NR_preadv2 392
__SYSCALL(__NR_preadv2, compat_sys_preadv2)
#define __NR_pwritev2 393
__SYSCALL(__NR_pwritev2, compat_sys_pwritev2)
......
마지막으로 Do 볼게요.ni_syscall, 커널의 무의미한 시스템 호출 번호가 함수 위에 실행됩니다.
asmlinkage long do_ni_syscall(struct pt_regs *regs)
{
#ifdef CONFIG_COMPAT
long ret;
if (is_compat_task()) {
ret = compat_arm_syscall(regs);
if (ret != -ENOSYS)
return ret;
}
#endif
if (show_unhandled_signals_ratelimited()) {
pr_info("%s[%d]: syscall %d
", current->comm
task_pid_nr(current), (int)regs->syscallno);
dump_instr("", regs);
if (user_mode(regs))
__show_regs(regs);
}
return sys_ni_syscall();
}
본고는kernel-4.9버전, 오리지널 문장을 바탕으로 옮겨 싣고 표시해 주십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
kernel 시작 과정 중 디버깅 인쇄내부 핵의 가동 과정은 여러 군데와 관련되고 가동 과정의 코드는 어셈블리 코드와 C 코드로 구성된다.그중의 인쇄 함수도 여러 개가 있다.1. 어셈블리 단계 인쇄 함수는 다음과 같은 몇 가지를 포함한다. 이 함수들은k...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.