강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của sdyeob10024541
sdyeob10024541

câu hỏi đã được viết

Cấu trúc và nguyên lý của kiến trúc Arm cho phát triển phần mềm hệ thống - Phần 1 Giảng dạy trực tiếp bởi tác giả (Phiên bản 2024)

5.4.3 Thực hành: Thay đổi chế độ giám sát từ chế độ hủy bỏ (hủy bỏ dữ liệu) sang chế độ giám sát (TRACE32)

5.4.3 실습에서 궁금한점이 있습니다.

Viết

·

127

0

해당 실습을 진행하던 도중 궁금한점이 있어 이렇게 글 남기게 되었습니다!

data abort exception이 발생해서 vector_dabt라는 주소로 분기하게 된 상태에서는 SPSR_abt 레지스터에 이전 동작 모드인 user_mode bit encoding값이 설정이 되어있는 걸 볼 수 있었습니다.

 

그런데, Data abort를 처리하기 위해 supervisor mode로 진입하는 과정에서 movs pc, lr 명령어를 실행하면 supervisor mode로 진입은 하지만, SPSR_svc 레지스터에는 이전 동작 모드가 로드되지 않은 걸 볼 수 있었는데, 그렇다면 exception이 유발이 되어야만 SPSR_<mode>의 값이 갱신되는 것 인지 단순히 movs, subs와 같은 동작 모드를 변경하는 명령어로는 SPSR이 갱신되지 않는 것 인지 궁금합니다.

임베디드arm-architecturemicroprocessorscortex-a

Câu trả lời 2

0

austinkim님의 프로필 이미지
austinkim
Người chia sẻ kiến thức

질문하신 내용에 대해 직접 디버깅으로 확인하고 답신 드립니다.

혹시 이해가 가지 않는 부분이 있으면 다시 질문 부탁드립니다.

 

[User 모드에서 Data abort를 유발하는 동작 코드 리뷰]

1. Data abort 익셉션이 유발되면 0xFFFF0010 주소로 프로그램 카운터가 분기합니다.

NSR:FFFF0000|EA0003FF b 0xFFFF1004 ; vector_rst

NSR:FFFF0004|EA000465 b 0xFFFF11A0 ; vector_und

NSR:FFFF0008|E59FFFF0 ldr pc,0xFFFF1000

NSR:FFFF000C|EA000443 b 0xFFFF1120 ; vector_pabt

>> NSR:FFFF0010|EA000422 b 0xFFFF10A0 ; vector_dabt

이 때 CPSR과 SPSR_abt 레지스터의 값은 다음과 같습니다.

  • CPSR: 0x1D7 (현재 동작 모드는 Abort mode)

  • SPSR_abt: 0x10 (이전 동작 모드는 User mode)

NSR:FFFF10A0|vector_dabt: sub r14,r14,#0x8 ; r14,r14,#8

NSR:FFFF10A4| stm r13,{r0,r14} // r0와 r14 레지스터의 값을 프로세스의 스택에 푸시

// [1] 매우 중요한 동작

NSR:FFFF10A8| mrs r14,spsr // spsr의 값(spsr_abt과 같음)을 r14로 읽음

NSR:FFFF10AC| str r14,[r13,#0x8] // r14의 값(spsr_abt)을 프로세스의 스택에 푸시 // [2] 매우 중요한 동작

NSR:FFFF10B0| mrs r0,cpsr

NSR:FFFF10B4| eor r0,r0,#0x4 ; r0,r0,#4

NSR:FFFF10B8| msr spsr_cxsf,r0 // spsr.m를 supervisor 모드 필드로 변경

// spsr는 뱅크드 레지스터이므로, 어보트 모드에서

// spsr을 변경하면 spsr_abt가 함께 변경

NSR:FFFF10BC| and r14,r14,#0x0F ; r14,r14,#15

NSR:FFFF10C0| cpy r0,r13

NSR:FFFF10C4| ldr r14,[pc,+r14,lsl #0x2] // r14 레지스터에 분기할 레이브를 저장

// 이전 동작 모드가 user 모드이면: __dabt_usr로 분기

NSR:FFFF10C8| movs pc,r14

NSP:FFFF10CC| dcd 0xC0201CE0 ; __dabt_usr

NSP:FFFF10D0| dcd 0xC0201910 ; __dabt_invalid

__dabt_usr 레이블의 동작

NSR:C0201CE0|__dabt_usr: sub r13,r13,#0x48 ; r13,r13,#72

NSR:C0201CE4| stmib r13,{r1-r12}

NSR:C0201CE8| mrc p15,#0x0,r7,c1,c0,#0x0 ; p15,#0,r7,c1,c0,#0 (system control)

NSR:C0201CEC| ldr r8,0xC0201C20

...

NSR:C0201D1C| cpy r2,r13

NSR:C0201D20| bl 0xC021BB20 ; v7_early_abort

NSR:C0201D24| b 0xC0201FA4 ; ret_from_exception

v7_early_abort 함수를 호출한 다음에 ret_from_exception 레이블로 분기

여기서 v7_early_abort는 data abort에 대한 서비스 루틴을 실행

 

ret_from_exception 레이블은 r9와 r8 레지스터를 업데이트한 다음에 ret_to_user 레이블 분기

NSR:C0201FA4|ret_from_exception: lsr r9,r13,#0x0D

NSR:C0201FA8| lsl r9,r9,#0x0D

NSR:C0201FAC| mov r8,#0x0 ; r8,#0

NSR:C0201FB0| b 0xC0201048 ; ret_to_user

ret_to_user 레이블에서는 유저 모드로 복귀

NSR:C0201048|ret_to_user: cpsid i

...

NSR:C0201068| cpy r2,r13

NSR:C020106C| ldr r1,[r2,#0x40] // '[2] 매우 중요한 동작'으로 위에 명시한 프로세스의 스택 주소에 이전에 저장된 spsr_abt의 값(0x10, 이전 동작 모드는 user 모드)을 r1레지스터로 읽음

NSR:C0201070| ldr r14,[r2,#0x3C]!

NSR:C0201074| tst r1,#0x8F ; r1,#143 // 예외 처리 확인

NSR:C0201078| bne 0xC0201094

NSR:C020107C| msr spsr_cxsf,r1 // spsr(spsr_svc)에 r1 레지스터를 저장

NSR:C0201080| strex r1,r2,[r2]

NSR:C0201084| ldmdb r2,{r0-r14}^ // 스택에 푸시된 값을 로딩해서 r0~r14 레지스터 업데이트, 스택에 되돌아갈 주소가 저장된 r14 값이 이미 푸시됨 - '[1] 매우 중요한 동작'으로 표기

NSR:C0201088| nop

NSR:C020108C| add r13,r13,#0x48 ; r13,r13,#72

NSR:C0201090| movs pc,r14 // 유저 모드로 복귀하면서 data abort가 유발된 프로그램 카운터로 분기

 

[질문에 대해 정리]

  • SPSR 레지스터의 값은 익셉션이 유발될 때 Arm 프로세서가 하드웨어적으로 업데이트합니다. 즉 익셉션이 유발된 시점의 CPSR의 값을 SPSR_<mode>에 업데이트합니다.

  • movs, subs와 같은 동작 모드를 변경하는 명령어를 실행하면, movs 혹은 subs 명령어를 실행한 시점의 CPSR의 값이 SPSR_<mode>로 복사되지는 않습니다.

  • SPSR 레지스터의 값은 msr spsr_cxsf,r0 명령어와 같이 어셈블리 명령어로 변경할 수 있습니다. 대부분 동작 모드를 변경하기 직전에 spsr 레지스터의 값을 변경합니다.

언제든 궁금한 점이 있으면 질문해주세요.

감사합니다.

sdyeob10024541님의 프로필 이미지
sdyeob10024541
Người đặt câu hỏi

답변 감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다. 동엽님.

ARM 아키텍처에서 예외가 발생하면, 다루고 있는 모드에 따라 특정한 예외 처리 동작을 수행하게 됩니다. 이 과정에서 사용되는 레지스터에 대한 질문을 주셨습니다. 구체적으로는 예외 발생 시와 동작 모드 전환 시의 SPSR 레지스터에 대해 궁금해 하셨네요.

예외 및 SPSR 동작 이해

  1. 예외 발생 시:

    • SPSR: 예외가 발생하면, 해당 예외 모드의 SPSR 레지스터에는 예외가 발생하기 직전에 실행 중이던 상태 정보가 저장됩니다. 예를 들어, user mode에서 data abort가 발생하면, SPSR_abt에는 user mode의 CPSR 값이 저장됩니다.
    • 이때 예외 벡터는 예외가 발생한 상황에 따라 해당 주소로 분기합니다.
  2. 동작 모드 전환 시:

    • MOVS 명령어: movs pc, lr과 같은 명령어는 예외 처리 모델이 아닌 일반적인 명령어로 사용될 때 CPSR 이하의 레지스터 값만을 갱신하며, SPSR에는 영향을 주지 않습니다.
    • 따라서, 단순히 모드 전환 자체로는 SPSR이 갱신되지 않으며, 예외 발생에 의해서만 SPSR_가 업데이트됩니다.

이와 같은 특성으로 인해 내리신 결론처럼, 예외 상황에서의 전환이 아닌 단순한 명령어로는 SPSR의 갱신이 이루어지지 않는 것입니다.

관련하여 더 심층적인 이해를 돕기 위해 리눅스 커널 동작 모드별 스택 포인터 초기화 관련 유사 질문 보기를 참조하시면, 추가적인 사례와 설명을 확인할 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Hình ảnh hồ sơ của sdyeob10024541
sdyeob10024541

câu hỏi đã được viết

Đặt câu hỏi