OS/navilnux

ARM 에서 소프트웨어 인터럽트(Software interrupt)발생시 ISR 과정 이해하기!

dp. 2010. 9. 14. 16:11
책 4, 5장 관련 전반적인 내용에 관한 정리이다 .
먼저 main.c 에는 
..
__asm__("swi 77");  
..
명령어가 들어있고, entry.S에는
....
_ram_entry:
        bl      main           0xa0008000
        b       _ram_entry   0xa0008004
        b       navilnux_swiHandler    0xa0008008
        b       navilnux_irqHandler     0xa000800c

.global navilnux_swiHandler
navilnux_swiHandler:
...
부트로더 에는 이미 swiHandler의 주소가 0xa0008008 가 고정되어 있는상태이고, 커널 이미지상에서도 위에서 보는 바와 같이 고정 시켜뒀다.
일단 arm에 각기다른 모드별로 사용할 수 있는 레지스트리가 다르다.
여기서 총 arm에서 사용할 수 있는 레지스트리는 37개 이다 . 어떻게 알지?.. 직접 세어봐라. 

다만 헷갈리지 말아야 할 부분을 적어보겠다. 
모드별 r0~r12번중 표시 안된건 공유, cpsr(현재 어떤모드인지)은 1개 , spsr(예전에 어떤모드였는지)은 user모드에는 필요없다. r15(pc, 다음에실행될 명령어 주소)는 공유. 기억하자!!

이제 main 함수에서 swi  라는 소프트웨어 인터럽트를 발생시키는 명령어로 인한 ISR진입과정 을  자세히 설명해 보도록 하겠다. swi 는 소프트웨어 인터럽트를 발생시키는 명령어로서 svc모드로 동작하게 된다. 

예를들자. main에서 swi 발생할때 예를 들어 설명하겠다.  

1. main에서 swi 77 명령어가 실행되면 인터럽트 발생!
2. 현재 cpsr을 svc모드의 spsr에 복사
3. r15(pc)를 svc모드의 r14(lr)에 복사
4. cpsr값을  svc모드로 바꾸기
5. r15(pc)값을 exception handler주소로 변경 여기서는 0xa0008008(위에서 부트로더와 커널에서 다~ 지정했다.부트로더에서와 커널에서의 주소지정 방법은 책에..)
========================================
요기까지가 arm코어에서 자동으로 해주는 작업이다. 
뭐... cpsr값을 개발자가 바꿔줘야 할 때도 있지만 swi여기서는 자동!
이 다음부턴 개발자가 핸들러를 짜줘야 하는 부분이다.
========================================
6. r0~r14까지 스택에 백업한다. 왜냐? 각 모드별로 따로 할당되어 있는 레지트스리가 그림에서 보듯이 있는데 svc모드는 따로 할당된게 없지 않은가(공유한다)? 일단 인터럽트 발생해서 넘어왔으니 할일을 해야한다. 그 할일을 하는것이 handler이고 여기서 지정된 곳으로 분기하게 되어 레지스트리를 사용하지 않은가? 그니까 백업해놔야한다. 어디에? 각자 지정된 스택에 (그래서 각자 r13(sp) -따로 있잖아.!!)
만약 FIQ 가 발생하면 r0~r7 , r13,r14 정도만 백업한다. 이렇게 레지스터 몇개 줄이는 것도 시간줄일 수 있다. 우선순위도 다르지만...
7. svc모드의 spsr도 스택에 백업한다.
8. ISR코드 수행한다. 즉, 위의 entry.S 코드에서
.global navilnux_swiHandler
navilnux_swiHandler:
....                             
bl   swiHandler                              <====요기   (main.c 에 함수로 정의되어 있다. bl 을 사용하면 c코드로 넘어감.)
이부분을 수행하게 되는 것이다. 이거 수행할때 레지스트리 r0~~~부터 해서 레지스트리 사용하게된다. 그래서 백업하는것이다.
9 . 작업이 끝난 후 반대로 돌려주면된다. 스택포인터는 spsr을 저장한 다음의 위치를 가리키고 있으므로 스택에서 4바이트 빼서 spsr에 다시 저장한다. arm은 4바이트씩.
10.r0~r14까지 다시 되돌려준다. 

그러니까  main.c에서 swi명령어로 인해 소프트웨어 인터럽트가 발생할 때 ISR 핸들러를 만들어 주는 과정을 요약하면
자동으로 arm코어에서 하는 과정은 놔두고

entry.S에서
.global navilnux_swiHandler
navilnux_swiHandler:
r0-r14내용을 스택에 백업
spsr 내용을 스택에 백업
bl   swiHandler 
스택의 마지막 4바이트를 spsr에 쓰기
스택에서 차례대로 r0-r14쓰기

이렇게 요약할 수 있겠다. 
천재!

ps. 2010.9.29일 추가내용
주의 arm은 기본모드가 svc란다. user모드에서 svc로 바뀌는게 아니라 모드의 변경은 없고, isr처리 과정에 중점을 두어 살펴봐야한다.