[커널20차] 8주차

2023.06.24 23:10

이경재 조회 수:74

2023. 06.24. (8주차) - 약 22명 참여

 

 

[5.1 Special registers] (p.13-15)

 

레지스터 표기법

  • Wn - 하위 32 비트

  • Xn - 전체 64 비트

  • (Rn - Wn 또는 Xn으로 사용될 수 있음을 의미)

Special registers

  • Zero register

  • Stack pointer (AArch64에서는 SP_EL0 또는 SP_ELn 사용 가능) 

  • Program counter (ARMv8-A 에서는 특정 상황에서만 reference를 허용)

  • Saved Program status register (PSTATE의 값을 진입하고자 하는 Exception level의 SPSR에 저장)

  • Exception link register (특정 Exception level로 진입할 때, 돌아올 주소를 해당 Exception level의 ELR에 저장)  

 

 

Q. 레지스터에 대한 설명들이 쭉 나올 것 같은데, 이러한 레지스터의 이름, 기능들을 알아야하는 이유와 중요성 등을 포함하여 얇게나마 공유해주실 수 있을까요? 

A. 어플단 개발자는 OS레벨 입장을 볼수없어서, 바이너리를 보고 문제점을 찾는 경우가 생길 수 있다. 

덤프를 뜬 후, 어셈분석을 하거나, 기드라 같은 것들을 사용하여 역어셈블하여 레지스터들에 정보를 통해 해석하는 경우가 있었음.

 

 

Q: 64-bit address를 로드하는 instruction

A: https://developer.arm.com/documentation/dui0473/m/writing-arm-assembly-language/load-addresses-to-a-register-using-adr

 

 

Q. p.14 Stack Pointer에서 ‘EL0 can only access SP_EL0.’라고 되어 있는데요, 그럼 EL0이 아니라면, 다른 SP_ELx에도 접근할 수 있다는 의미가 되는 것일까요?

A. EL0는 SP_EL0만 접근 가능. 그 외의 Exception Level에서는 본인의 SP_ELx와 SP_EL0에 접근 가능 (Max 2개..)

 

X6t1gG9gxK2YPmtvKx-Luy4OVhnUn6RWbYRSysBP

 

 

 

Q. p.13 3번째 줄에 The increased width helps to reduce register pressure in most applications.

이 부분이 잘 이해가 안되는데요,

AArch64 Execution state에서

  • 32 bit Application

  • 64 bit Application

중에 32 bit Application 일 경우 레지스터의 pressure을 줄이는 혜택을 볼 수 있다는 것 같은데, 

아래 설명에는 32비트의 경우 0xFFFFFFFF를 단순히 0을 붙여서 0x00000000FFFFFFFF 이런식으로 변환한다면 오히려 00000000을 붙이는 작업으로 인해 더 번거롭지 않을까 하는 생각인데, 어떻게 pressure가 줄어드는지 궁금합니다.

A.

많은 양의 데이터를 처리해야 할 때, 레지스터의 값들을 메모리에 저장하거나, 덮어씌우거나 해야하는데, 불가피하게 메모리로 register의 값을 내리는 현상을 register spill이라고 한다. Width가 늘어나면 레지스터를 register spill 이 일어나는 경우를 줄일 수 있기 때문에 pressure가 줄어들 수 있다.

00000000붙이는 것은 신경안써도 될 정도이다.

 

 

[6.Processor state] (p.16-17)

 

Q. 굳이 별도의 special purpose register들 (CurrentEL, DAIF, NZCV, SPSel, etc.)을 할당하여 PSTATE의 bit-field 정보들을 읽어올 수 있도록 설계한 이유가 뭘까? PSTATE 자체를 접근 가능한 레지스터로 정의하면 더 간단해질 수 있을텐데?

A. ARMv8 아키텍처에서는 PSTATE라는 새로운 프로그램 상태를 도입하였고, 이는 이전 ARMv7에서의 CPSR(Current Program Status Register)와 달리, 하나의 특정 레지스터에 매핑되지 않습니다. PSTATE는 프로그램 상태를 나타내는 여러 비트 필드를 추상화하여 제공합니다.

이러한 변화의 주요 이유는 아키텍처의 유연성과 확장성을 향상시키기 위함입니다. ARMv7 아키텍처에서는 CPSR과 SPSR(Saved Program Status Register)와 같은 특정 레지스터가 프로그램 상태를 나타내는 데 사용되었습니다. 이러한 방식은 간단하지만, 아키텍처가 진화하고 새로운 기능이 추가됨에 따라 제한적일 수 있습니다. 특정 레지스터에 대한 의존성은 아키텍처 변경을 어렵게 만들 수 있습니다.

반면에, PSTATE는 하나의 특정 레지스터에 매핑되지 않기 때문에, 이는 아키텍처의 변화에 더 유연하게 대응할 수 있습니다. PSTATE는 여러 레지스터에 분산된 프로그램 상태를 추상화하여 제공할 수 있으며, 이를 통해 새로운 기능을 추가하거나 기존 기능을 변경하는 데 더 큰 자유를 가질 수 있습니다.

또한, PSTATE는 ARMv8 아키텍처에서 도입된 새로운 예외 모델과 더 잘 통합됩니다. ARMv8에서는 여러 예외 레벨(Exception Level, EL)을 도입하여 보안과 가상화를 지원합니다. 각 예외 레벨에서는 별도의 프로그램 상태를 유지하며, 이는 PSTATE를 통해 관리됩니다. 이러한 방식은 각 예외 레벨에서의 상태를 더 명확하게 분리하고, 보안과 격리를 향상시키는 데 도움을 줍니다.

 

 

Q: Overview 문서에서 얘기하는, 특정 Exception Level n에서 SP_ELn이 아니라 SP_EL0로 switch하는 use case가 어떻게 되는지? 예를 들어, 커널이 EL1에서 동작하고 있을 때 SP_EL0로 스택을 바꾸는 use case는? (EL1에서 EL0로 돌아가는 경우를 묻는 것이 아니라, 같은 EL1 레벨 안에서 SP_EL1이 가리키는 스택에서 SP_EL0가 가리키는 스택으로 바꾸는 경우를 묻는 것이다.)

 

A: 아래 Linux Kernel의 커밋 메시지를 보면 알 수 있듯, 현재 AArch64 Linux Kernel은 EL1에서 동작하고 있을 때 SP_EL0가 가리키는 스택(EL1에서는 이 레지스터를 수정할 수 있기 때문에 어느 스택이든 가리키게 할 수 있다)으로 switch하지 않는 것으로 보인다. 즉, EL1에서는 SP_EL1 스택만 사용한다, SP_EL0 스택으로 switch하는 use case가 없다. 그런데 아래 커밋에서 성능 최적화와 Management 편의를 위해, SP_EL0 레지스터를 다른 용도로(특정 스택으로 갈아타려는 용도가 아닌) 사용하는 코드를 들여왔다. EL1에서는 SP_EL0 레지스터가 특정 struct의 주소를 가리키게 함으로써 특정 데이터 접근을 용이하게 하는 것이다.

 

https://github.com/torvalds/linux/commit/6cdf9c7ca687e01840d0215437620a20263012fc

arm64: Store struct thread_info in sp_el0

There is need for figuring out how to manage struct thread_info data when

IRQ stack is introduced. struct thread_info information should be copied

to IRQ stack under the current thread_info calculation logic whenever

context switching is invoked. This is too expensive to keep supporting

the approach.

 

Instead, this patch pays attention to sp_el0 which is an unused scratch

register in EL1 context. sp_el0 utilization not only simplifies the

management, but also prevents text section size from being increased

largely due to static allocated IRQ stack as removing masking operation

using THREAD_SIZE in many places.

 

http://jake.dothome.co.kr/head-64-60/

https://stackoverflow.com/questions/65059491/why-save-init-task-struct-address-to-sp-el0-in-arm64-boot-code-primary-switche

 

 

 

 

 

 

 

[7.The Saved Process Status Register] (p.18)

 

sORgAfliJ70cjv4Yq3B_Hcd5ie_oXJmFnwJyMDjW

 

Q: AArch32의 SPSR에는 존재하나 AArch64의 SPSR에는 존재하지 않는 bit-field 들에 대한 의문

A. AArch64 또는 AArch32 execution state들에서 각각 필요한 bit-field들이 달라서 그런 것으로 추측. 가령 T[5] (Thumb-mode bit)의 경우 AArch32에서만 의미가 있음.

 

Q. AArch32 SPSR의 IT field의 의미는? 심지어 두 개로 나뉘어 있음

  1. Thumb 명령어셋(2byte)에서 쓰이는 IT(If-then) 명령어를 위한 상태비트

  2. https://wpaud16.tistory.com/entry/Arm-Thumb-blx-bx-Thumb2-IT%EB%AA%85%EB%A0%B9%EC%96%B4-if-then

대부분의 Arm 명령어는 조건을 비교할 수 있는 condition bit를 가지고 있다. 하지만 Thumb은 16bit 밖에 없어서 조건을 비교하기에 bit가 모자라다. 그래서 IT 명령어가 필요하다. 

CPSR에 보면 IT bit가 존재한다. 여기서 보고 어떤 명령어를 수행하는지 판단한다. arm은 조건이 머신 코드에 들어있지만 thumb은 CPSR에 들어있다 

_kwz5q5YY8whN_h_l_9mNPJ-kRy8MrNVjeU_33kN

자세한 설명은 위의 링크를 참고..

 

Q: Process context switching과 연관되는 지점이 있는지?
    있다면 어떤 부분들이 연결이 될 수 있을지

A. processor의 status, task들도 중복되는 정보가 많아보인다. 

     각 중복되는 정보들이 따로 저장되어있을거 같다 task structure에 있을 것으로 추정

     Switching in 될때 PSTATE에 write이 될거 같다.

  • Task structure (엄밀하게는 thread) 

    • 자신이 돌아가야하는 프로세스의 상태 정보가 있을 것이다.

    • Hardware core에 반영해야하니까 위 정보가 있을 것이다.

    • Task들을 위한 정보는 메모리에 있을 것이라 생각
      그들이 실행될때 PSTATE로 가는 것이라 생각

 

 

[8.The System Register] (p.19~p.23)

 

Q, ARMv8-A는 31개의 레지스터를 제공한다고 나와있던 것 같은데, 시스템 레지스터만 해도 31개가 넘는 것 같아서 헷갈립니다… 그리고 처음 생각으로는 X0~X30 까지의 레지스터 범위가 있다면, 해당 범위마다 특정 유형의 레지스터가 1대1로 매칭이 되어야 할 것 같았는데(가령 X1에는 SP_EL1), 레지스터의 사용 범위가 X0~X30 까지이지, 실제로 레지스터 사용 동작은 범위 내에 특정 유형의 레지스터를 배치하고, 사용한 후 다 읽으면 버리고, 다시 새로운 유형의 레지스터를 배치하는 일이 계속 반복되는건가요??

A. 31개의 레지스터는 범용 레지스터(일반적으로 연산을 하는 데 사용) 시스템 레지스터 및 특수한 레지스터는 그와는 별도로 존재한다. 11장을 참고하면 AArch32의 모드에 따른 범용 레지스터와 특수 목적 레지스터, 시스템 레지스터터에 대한 내용이 나오니 참고.

 

Q. TPIDR_ELn 설명에서 location의 정확한 의미는?

A. 스레드 별로 공유할 수 있는 스레드 로컬 스토리지 포인터를 가리키고 있을 것 같음 (일반적인 용도는 아닌것으로 보임)

OS마다 사용 용도가 다른 것으로 보임

현재 리눅스에서는 TPID를 저장하는 목적으로 사용하지 않고 각 cpu의 per-cpu offset을 저장하여 더 빠른 per-cpu data의 access를 위해 사용된다. (출처: http://jake.dothome.co.kr/smp_setup_processor_id)

 

TzAdjyuCtYZw4-61Og29WyllPg7KogZzhsBO_hiR

실험삼아 해봤는데 aarch64에서는 별다른 옵션 없이도 tls를 tpidr_el0으로 접근하는 것 같네요.

 

 

[9.The System Control Register] (p.24 ~ 26)

 

Q. 비트 중 회색깔부분은 ? 

  1. Reserved 된 부분. 앞으로를 위해 남겨둔 부분으로 예상 

  2. http://jake.dothome.co.kr/registers64/ 의 SCTLR 부분을 보면 회색 부분도 version에 따라 특정 기능을 위해 사용되는 것으로 보임. 

      

Q. SCTLR (시스템 제어 레지스터) 에서  EE, EOE 필드를 보면 엔디안을 level 별로 따로 설정할 수 있는 것처럼 보인다. 그 이유는 무엇인가요?

  1. ARM 프로세서들은 성능 향상을 위해 빅 엔디안과 리틀엔디안을 선택할 수 있습니다
    https://duzi077.tistory.com/201

  2. cf)  bi-endian - ARM 뿐 아니라  PowerPC, DEC 알파, MIPS, PA-RISC, IA-64 등에서도 사용 

산술 연산에서는 little endian이 유리하고, 네트워크 byte order는 big endian으로 되어있기 때문에 이를 처리할 때는 big endian이 유리하다. 따라서 각 장점을 사용하기 위해 endian을 따로 설정할 수 있게 두는 것 같다. (이 때, 바뀌는 endian은 data access에 대한 endian, instruction은 바뀌지 않음.)

 

Q.마지막 Caches in the processor must be invalidated 부분에 대한 추가설명

A: 캐쉬 초기화를 의미함 (http://jake.dothome.co.kr/registers64/)

 

Q. 26p “Caches in the processor must be invalidated before data and instruction caches are enabled in any of the Exception levels.” Cache invalid 란 어떻게 하는가? calloc()처럼 0으로 초기화하는가?

A: 초기화하는 instruction이 있을 것이다.
kjxLmeJK3SkRIwsBj2u_q93_BUF_BcYdxDwhgsJD

 

 

[10. Changing Execution state (registers)] (p 27)

 

Q. OS가 32비트와 64비트 어플리케이션을 동시에 실행하고 있을 때 일어나는 상황일까요?

A. 아마 이런 상황을 말하는거 같습니다..!

xvpJ7dgvyD7RvYviL-RG7cZPenWIVn5tNtt-oyBb

 

Q. aarch32 아직 쓰이는가??

A. 바이너리 레벨에서 하위 호환성을 제공하려면 필수적일 것으로 보임. 아직 32비트로 돌아가는 app들이 많아보입니다..!!

https://news.ycombinator.com/item?id=27277351

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 627
228 [커널 20차] 20주차 [2] 이민찬 2023.09.17 182
227 [커널 20차] 19주차 이민찬 2023.09.10 103
226 [커널 20차] 18주차 이민찬 2023.09.03 85
225 [커널 20차] 17주차 이민찬 2023.08.27 129
224 [커널 20차] 16주차 이민찬 2023.08.20 132
223 [커널 19차] 64 주차 Min 2023.08.19 91
222 [커널 20차] 15주차 이민찬 2023.08.13 126
221 [커널 19차] 63 주차 Min 2023.08.12 60
220 [커널 19차] 62 주차 Min 2023.08.05 79
219 [커널 20차] 13주차 이민찬 2023.07.30 107
218 [커널 19차] 61 주차 Min 2023.07.30 45
217 [커널 20차] 12주차 이민찬 2023.07.22 87
216 [커널 19차] 59 ~ 60 주차 Min 2023.07.22 37
215 [커널 18차] 113주차 kkr 2023.07.22 78
214 [커널20차] 11주차 이경재 2023.07.15 86
213 [커널20차] 10주차 이경재 2023.07.09 90
212 [커널20차] 9주차 이경재 2023.07.02 85
211 [커널 19차] 58 주차 Min 2023.07.01 41
210 [커널 19차] 56 ~ 57 주차 Min 2023.06.25 40
209 [커널 18차] 109주차 kkr 2023.06.24 33
XE Login