Exception
본 노트는 System programming뿐만 아니라 OS, Advanced Computer Architecture 내용이 같이 들어가 있다.
1. Exceptional Control Flow
1-1. Control Flow
-
프로그램은 sequence of instruction이고, 결국 code에 있는 instruction을 순서대로 읽어서 실행하는 것
- 이런 식의 코드를 읽고 실행하는 것을 control flow라고 한다.
-
하지만, 우리 모두가 알고있는 것처럼 코드는 순서대로만 실행되지 않는다.
- 코드의 순서는 바뀐다!(코드의 흐름을 바꾼다.)
- e.g. if, while, function call...
- 이것들은 보통 jmp, call/return으로 implement된다.
-
이러한 것들은 사실 program의 자체적인 state에 의해서 결정된다.(변수의 값이나 기타 여러가지 조건)
- 근데, 프로그램의 내부적인 state 뿐만 아니라, system의 전체적인 state도 반영해야할 필요가 있다.
- e.g. disk data move, network packet recieve, segmentation fault, page fault...
- 이런 system의 state에 대해서는 어떻게 코드가 대처할 것인가?
- 당연하겠지만 User의 script는 이런 system의 전체적인 state를 고려하지 않는다.(하는 경우도 있지만 대부분은 아니다.)
- 보통은 이러한 것들은 OS/hardware의 몫이 되는 것
- 여튼 이러한 system state에 대해서는 OS/hardware가 처리하는 것이 일반적이고, 이런 경우에 의해서 control flow가 변경되는 것을 우리는 exceptional control flow라고 부른다.
1-2. Exceptional Control Flow
- exception은 2개의 부분에서 처리된다.
- Hardware
- OS(kernel)
- 이 두 부분은 분리되어있지 않고 긴밀하게 협력하여 exception을 처리한다.
2. Exceptions
2-1. Hardware Support for Exception
- exception detection은 기본적으로 hardware에서 이루어진다
- instruction을 실행하는 과정에서 이것이 이루어진다.
- stage로 나뉘어지는 건 이제 익숙할 것인데, 각 stage마다 exception을 감지하는 경우가 있다.
- 여튼 이렇게 exception이 감지되면, 즉시 CPU는 해당 instruction 이전의 inst를 전부 dumping한다.
- 보통 instruction이 실행이 완료되어 commit이 된 경우 instruction이 끝났다고 표현하기 때문에, exception은 instruction이 완료되기 이전에 일어난다.
- 이렇게 exception이 일어나면, CPU는 context switching을 시작해야 한다.
- exception을 처리할 곳으로 이동해야하지 않겠는가?
- 이 때 사용되는 것이 stvec이다. - exception handler의 주소를 저장해놓는 special regsiter(kernel mode와 user mode에 따라 다른 값이 저장되어있음)
- stvec의 장소로 PC를 변경하고, 기존 PC는 또 다른 register에 저장하고, exception의 원인을 scause register에 저장하고... hardware도 굉장히 많은 일을 수행해야한다...(register 이름들은 RISC-V register로 x86-64는 아예 다른 register를 사용한다)
- 이렇게 stvec으로 이동하면 하는일이 user -> kernel 전환
- 이는 당연한 것이, 기존의 process의 state는 저장해야하지 않겠는가?
- 여기서 등장하는 것이 trapframe이니, trampoline이니하는 것들
- 이제 handler로 전환되었다!
- Handler는 어떤 구조로 이루어져 있는가?
- Interrupt Vector Table : Series of Interrupt Handler
- 여기 vector table에 저장되어 있는 주소중에 적당한 주소로(scause에 따라서) 다시 이동해서 interrupt를 처리하면 된다...
나중에 계속