강좌 & 팁
글 수 2,412
2012.10.03 23:29:30 (*.52.177.29)
43361
커널 산책 - SWI와 시스템 콜 (4)
저번 산책 때
SWI 명령을 통해서
함수 번호(인덱스)를 넘기는 부분을 살펴 보았습니다.
그렇다면...
커널은 이 번호를 어떻게 얻을까요?
ARM 어셈블러 명령에 이런 번호를 얻는 명령이나 코프로세서 명령이 따로 있을까요?
불행하게도 그런 것 없습니다.
그래서
ARM의 입셉션에 대한 사전 지식이 필요합니다.
왜냐?
ARM에서 SWI 명령에 대한 입셉션이 발생했을 때
처리 되는 상태를 이용해서 시스템 콜 함수 인덱스를 얻거든요..
실제로 커널 코드는 좀 복잡하니깐
먼저
간단한 ARM 어셈블러를 이용해서 설명하기로 하죠..
전에 open() 시스템 콜을 호출하기 위해서는
swi __NR_SYSCALL_BASE(==0x900000)+1
로 명령을 만들고 호출 한다고 했죠?
이 명령이 수행되는 순간 Software Interrupt 입셉션이 발생합니다.
ARM 프로세서는 이 순간에 하드웨어적인 처리 방식으로
다음과 같은 일을 합니다.
1) PC 값을 LR 레지스터에 넣습니다.
LR 은 Link Register 의 약자인데 R14 레지스터의 별칭입니다.
PC 는 Program Counter 의 약자인데 R15 레지스터의 별칭입니다.
이때 PC 값은 SWI 명령 다음에 수행할 명령 주소 값을 가지고 있게 됩니다.
SWI 명령의 입셉션을 수행하고 난 후 원래 위치로 올 필요는 없죠..
발생했을 당시의 명령이 SWI 명령인데 이 위치로 돌아 오면 무한 반복 하잖아요..
그래서 SWI 명령 다음에 수행할 명령의 주소가 PC 에 있게 되고
이 값을 LR 에 저장하므로써
나중에 LR 값을 PC 에 지정하면
그 순간 SWI 명령 다음의 명령을 수행하게 되는 거죠.
이거 무척 중요합니다.
꼭! 기억하세요..
2) CPSR 을 SPSR 에 넣습니다.
CPSR 은 현재 프로세스 상태 레지스터인데
이것을 SPSR 에 저장하므로써 복귀할때 이 저장된 값을 복구하면
입셉션 발생 전 상태로 쉽게 돌아 올 수 있지요..
3) PC 에 입셉션 벡터 테이블의 소프트웨어 인터럽트 테이블 주소를 넣습니다.
이때 하이벡터 상태가 아니면
PC 에 0x00000008 을 지정하게 되고요
하이벡터 상태이면
PC 에 0xFFFF0008 을 지정하게 됩니다.
이전에 익셉션 벡터 테이블에 대한 설명 기억 나시나요?
이렇게 해서 소프트웨어 인터럽트 핸들러가 수행되게 됩니다.
이제 인터럽트 핸들러는 시스템 콜을 처리해야 겠죠?
그런데 문제는 시스템 콜 함수를 구별해야 하잖아요?
어떻게 시스템 콜 함수 인덱스를 구할까요?
위에서 제가 꼭 기억하라고 한 것 있었죠?
예..
LR 레지스터에 저장된 값이 있죠...
이 값에 들어 있는 주소가 무슨 주소라고 했죠?
SWI 명령 다음 주소라고 했죠...
그러면 SWI 명령이 있는 주소는 ?
맞아요...
LR 레지스터에서 4 를 빼주면 됩니다.
예를 들어 SWI 명령 자체를 R0 에 넣고 싶다면 이렇게 하면 됩니다.
ldr R0, [LR-4]
이 명령을 통해서 R0 에는SWI 명령 자체가 들어 있습니다 .
이제 R0를 가공해서 시스템 콜 함수 인덱스를 얻어 오면 됩니다.
시스템 콜 할 때 다음과 같이 사용했죠?
swi __NR_SYSCALL_BASE(==0x900000)+1
그리고 SWI 명령은 다음과 같은 구조라고 했죠?
수행 조건(4비트) + SWI 명령(4비트) + 임의값(24비트)
이중 임의값 24 비트가 __NR_SYSCALL_BASE(==0x900000)+1 부분입니다.
그러면 R0 에서 먼저 24비트 값만 구해야 겠죠?
그리고 0x900000을 빼버리면 +1 한 값만 남겠죠?
이렇게 하면 시스템 콜 함수 번호를 얻게 됩니다.
실제 커널 소스가 이걸 구현하는 가는 조금 있다 봐야 하구요...
오늘은 시간도 늦었고
( 아시나요? 이 글쓰는 이시간 즉 저녁 11시에 전 회사에 있고 오늘은 개천절 즉 공휴일이라는 사실 ㅠㅠ )
다음 산책 시간엔
시스템 콜을 호출하는 최신 방식에 대해서 알아 보려구요..
그럼...
여기서 잠깐! -----------------------------------------------------
ARM 에 대해서 공부하다보면
APCS 라는 것이 있다는 것을 알게 될 수도 있습니다.
APCS 는 ARM Procedure Call Standard 의 약자인데
이 말을 한글로 하면 흠... 영어가 딸리는 군요..
ARM 에서 권장하는 C 언어 함수 호출에 대한 몇 가지 규칙입니다.
이 규칙은 gcc 같은 컴파일러가 따르게 됩니다.
이 규칙은 ARM 의 레지스터의 별칭을 지칭하고
어떻게 C 의 변수들을 사용하는 지
레지스터는 어떤 용도로 사용하면 좋은지를 권장합니다.
다음과 같은 규칙이 있습니다.
r0 a1 argument 1/scratch register/result
r1 a2 argument 2/scratch register/result
r2 a3 argument 3/scratch register/result
r3 a4 argument 4/scratch register/result
r4 v1 register variable
r5 v2 register variable
r6 v3 register variable
r7 v4 register variable
r8 v5 register variable
r9 v6/sb register variable/static base
r10 v7/sl register variable/stack limit/stack chunk handle
r11 fp register variable/frame pointer
r12 ip new-sb in inter-link-unit call/sscratch register
r13 sp stack pointer
r14 lr link register/scratch register
r15 pc program counter
이에 대한 정확한 뜻은 시스템 콜 산책을 하다보면 좀 더 자세하게 알게 됩니다.
이 규칙은 여러 곳에서 필요하거든요..
ARM 커널을 이해하기 위한 지식 중 꼭 필요한 것중 하나 입니다.
-----------------------------------------------------------------------
어떤 분이 글 보기가 너무 어지럽고 텍스트만 있어서 읽기 어렵다고 하네요
흠 ...
제가 봐도 그래요...
그런데 그냥 이렇게 살다 죽을래요...
저도 짬내서 쓰는 글인데다가
보통...
글 꾸미는 시간이
글쓰는 시간 만큼 걸려요...
나중에 혹시라도 책으로 쓰면 그때 정리 할래요..
저 무척 게으르거든요...
그리고 글쓰는 것이 노동으로 느껴지면 글 안쓰게 돼요 ㅠㅠ
이해해 주세용..