RISC-V 아키텍처에서 레지스터를 배우려면 어떤 내용을 알아야 할까요? RISC-V 아키텍처에서는 다음과 같은 레지스터를 제공합니다.
- 범용 레지스터
- CSRs(Control and Status) 레지스터
범용 레지스터
먼저 범용 레지스터에 대해 알아 봅시다. 범용 레지스터는 어셈블리 명령어의 입력과 출력을 저장하는 용도로 사용됩니다. 개념 상 C 언어의 변수와 비슷한 개념입니다. 어셈블리 명령어를 분석하실 때 반드시 레지스터를 알아야 합니다.
RISC-V 아키텍처에서 정의된 범용 레지스터의 목록은 다음과 같습니다.
Armv8 아키텍처와 비슷하게 레지스터의 갯수는 X0에서 X31까지 있습니다. 레지스터의 갯수가 많은 편입니다. 대부분 어셈블리 명령어의 인풋과 출력 결과를 저장하기 위해 사용되는데, 함수가 호출될 때 특별히 사용되는 레지스터가 있습니다. 예를 들면:
- X1(ra): 링크 레지스터, jal 명령어를 실행하면 돌아올 주소를 Hart(RISC-V의 CPU core)가 업데이트
- X2(sp): 스택 포인터, 프로세스가 가장 마지막에 실행된 스택 주소를 가리킴
- X10~X17(a0~a7): 함수에 전달되는 아규먼트
리눅스 커널이나 RTOS에서 컨텍스트 스위칭라는 용어를 아마 들으신 적이 있을 것입니다. 여기서 말하는 컨텍스트는 실행 흐름을 뜻하며, 컨텍스트 스위칭은 실행 흐름을 바꾼다라고 볼 수 있습니다. 구체적으로는 컨텍스는 범용 레지스터를 뜻하며, 컨텍스트 스위칭은 범용 레지스터를 바꾼다라고 볼 수 있습니다.
다음은 리눅스 커널에서 컨텍스트를 저장하는 자료구조입니다.
https://elixir.bootlin.com/linux/v6.9/source/include/linux/sched.h#L748
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
/*
* For reasons of header soup (see current_thread_info()), this
* must be the first element of task_struct.
*/
struct thread_info thread_info;
#endif
unsigned int __state;
...
/* CPU-specific state of this task: */
struct thread_struct thread; //<<--
task_struct 구조체의 가장 마지막 필드는 thead입니다.
https://elixir.bootlin.com/linux/v6.9/source/arch/riscv/include/asm/processor.h#L113
/* CPU-specific state of a task */
struct thread_struct {
/* Callee-saved registers */
unsigned long ra;
unsigned long sp; /* Kernel mode stack */
unsigned long s[12]; /* s[0]: frame pointer */
struct __riscv_d_ext_state fstate;
unsigned long bad_cause;
u32 riscv_v_flags;
u32 vstate_ctrl;
struct __riscv_v_ext_state vstate;
unsigned long align_ctl;
struct __riscv_v_ext_state kernel_vstate;
};
보시는 바와 같이 thread 필드에 레지스터를 나타내는 필드가 확인됩니다. 이처럼 범용 레지스터는 운영체제 커널이나 RTOS에서 컨텍스트로 표현됩니다.
< 관련 강의 >
'RISC-V > 레지스터' 카테고리의 다른 글
[RISC-V] CSR (Control and Status) 레지스터 소개 (0) | 2024.08.03 |
---|