Exception

EEEFFEE·2023년 11월 22일
0

Armv8 Architecture

목록 보기
2/15

23.11.22 최초 작성
23.11.27 ftrace 메시지 추가

1. Exception Level

  • Armv8아키텍처는 EL0 ~ EL3까지 Exception Level 을 정의한다.

  • EL0, PL0

    • 다양한 사용자 Application이 구동 됨
    • unprivileged level : 하드웨어에 직접 접근할 수 없음
    • 인터럽트, MMU, 캐시 기능을 설정할 수 없음
  • EL1, PL1

    • OS kernel이나 privileged function이 구동 됨
    • 인터럽트, MMU, 캐시 와 가은 시스템을 설정 가능
  • EL2, PL2

    • 여러 OS가 구동될 수 있는 하이퍼바이저가 구동 됨
    • 게스트 OS끼리 스위칭하고 게스트 OS의 시스템에 접근 가능
  • EL3, PL3

    • Non-Secure ModeSecure Mode를 구분해 구동 함
    • 시스템을 모두 설정할 수 있고 모든 레지스터에 접근 가능해 Booting 과정에서 해당 레벨로 설정 됨

2. Exception

  • 예외적인 상황이 발생했을 때 처리되는 이벤트

2.1 종류

  • Synchronous

    • System call, Data abort, Instruction abort,
      Misaligned 스택 포인터 접근, Unknown reason
  • IRQ Interrupt : 외부 인터럽트(Non-secure interrupt)

  • FIQ Interrupt : 외부 인터럽트(Secure interrupt)

  • Serror : 외부 메모리 Data abort

2.2 Exception 처리 방식

  • Exception발생 시 종류별로 미리 정의된 주소(Exception Vector)로 분기

  • 해당 주소에는 Exception을 핸들링하는 코드가 존재

  • Exception Vector Table에 지정된 주소에 따라 분기함

    • Lower EL : EL0에서 발생하는 Exception
    • Current EL : EL1에서 발생하는 Exception
  • Exception Level에 따라 Exception Vector Table이 존재하며

2.3 처리 과정

  1. Exception발생 시 ELR<N>에 복귀 주소를, 현재 프로세스 상태를 SPSR_EL<N>에 저장

  2. 프로세스 상태 갱신 후 Exception Vector Table엔트리로 분기

  3. 정해진 Exception Vector에 따라PC값 변경

  4. ESR<N>Exception원인 저장

  5. ERET을 통해 Exception처리 복귀 및 SPSR_EL<N>, ELR<N>값을 통해 프로세스 상태, PC값 복원

2.3.1 Hypervisor의 경우

  • IRQ의 경우
    1. IRQ발생 시 EL2Exception Vector로 분기
    2. 이후 각 Guest OSEL1Interrupt분배
  • Abort의 경우
    1. IRQ발생 시 EL2Exception Vector로 분기

2.3.2 ftrace message 분석

인터럽트 발생 (Interrupt Vector 주소로 이동)


<idle>-0 [000] d.h1. 2228.822487: irq_handler_entry: irq=37 name=mmc1
	<idle>-0 [000] d.h1. 2228.822488: bcm2835_mmc_irq+0x4/0x680 <-__handle_irq_event_percpu+0x88/0x280
	<idle>-0 [000] d.h1. 2228.822489: <stack trace>
=> bcm2835_mmc_irq+0x8/0x680
=> __handle_irq_event_percpu+0x88/0x280
=> handle_irq_event_percpu+0x20/0x68
=> handle_irq_event+0x50/0xa8
=> handle_fasteoi_irq+0xe4/0x198
=> generic_handle_domain_irq+0x34/0x50 // handle_domain_irq
=> gic_handle_irq+0xa0/0xd8
=> call_on_irq_stack+0x2c/0x54
=> do_interrupt_handler+0xe0/0xf8
=> el1_interrupt+0x38/0x70
=> el1h_64_irq_handler+0x18/0x28
=> el1h_64_irq+0x64/0x68
=> finish_task_switch+0x98/0x290
=> __schedule+0x2ac/0x830
=> schedule_idle+0x28/0x50
=> do_idle+0xec/0x240
=> cpu_startup_entry+0x2c/0x38
=> rest_init+0xe4/0xe8
=> arch_post_acpi_subsys_init+0x0/0x28
=> start_kernel+0x6f8/0x730
=> __primary_switched+0xbc/0xc4

  • <idle>-0 [000] d.h1. 2228.822487: irq_handler_entry: irq=37 name=mmc1

    • 이름이 mmc인 37번 인터럽트 핸들러가에 진입
  • VBAR_EL_1 + 0x280 (Current EL with SPx/IRQ) 주소로 분기

  • arch/arm64/kernel/entry-common.c

    • el1h_64_irq
    • e1h_64_irq_handler
    • el1_interrupt
    • do_interrupt_handler
  • arch/arm64/kernel/entry.S

    • call_on_irq
  • arch/arm64/kernel/entry-common.c

    • gic_handle_irq
    • handle_domain_irq

IRQ 서브시스템 (인터럽트 컨텍스트 활성화, Interrupt Handler 호출)

  • /source/kernel/irq/irqdesc.c

    • handle_fasteoi_irq
  • /source/kernel/irq/handle.c

    • handle_irq_event
    • handle_irq_event_percpu

0개의 댓글