Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

51107
469
422683


[리눅스커널][인터럽트후반부] IRQ 스레드는 언제 생성할까? 6. 인터럽트 후반부 처리


디바이스 드라이버의 초기화 코드는 대부분 부팅 과정에서 실행됩니다. 이 과정에서 request_threaded_irq() 함수를 호출해 IRQ 스레드를 생성합니다. IRQ 스레드는 생성되면 시스템 전원이 공급돼 동작하는 동안 해당 인터럽트 후반부를 처리하는 기능을 수행합니다.

이제, IRQ 전체 실행 흐름도를 보면서 IRQ 스레드 생성 과정을 배워볼까요? 

* 유튜브 강의 동영상도 있으니 같이 들으시면 좋습니다.



     "혹시 글을 읽고 궁금한 점이 있으면 댓글로 질문 남겨주세요. 아는 한 성실하게 답변 올려 드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  
 

# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


repository-[리눅스커널][인터럽트후반부] IRQ 스레드는 언제 생성할까?
http://rousalome.egloos.com/10024576

    핑백

    덧글

    • Paran Lee 2022/04/25 13:53 # 삭제 답글

      안녕하세요. 이파란입니다.

      바닐라 커널 소스와 "디버깅을 통해 배우는 리눅스 커널의 구조와 원리" 서적을 보면서 스터디 중에
      바닐라 리눅스 커널 소스에 drivers/mmc/host/bcm2835-mmc.c 드라이버가 없는 것을 확인했습니다.
      <질문1> 이런 부분도 라즈베리파이 재단에서 라즈베리파이 보드에 최적화한 동작을 위해 BSP 한 부분이라고 보면되나요?
      - 이번에 비교해보니, Ubuntu 20.04 를 설치했을 때 보다 라즈베리파이 OS 를 설치했을 때 더 쾌적하게 동작합니다.

      라즈베리파이 400 보드에서
      kim@raspberrypi:~ $ cat /proc/interrupts
      CPU0 CPU1 CPU2 CPU3
      47: 3055532 0 0 0 GICv2 158 Level mmc1, mmc0

      # rpi-4.19.y bcm2835-mmc.c 드라이버 코드
      - https://github.com/raspberrypi/linux/blob/rpi-4.19.y/drivers/mmc/host/bcm2835-mmc.c#L1399

      ret = request_threaded_irq(host->irq, bcm2835_mmc_irq,
      bcm2835_mmc_thread_irq, IRQF_SHARED,
      mmc_hostname(mmc), host);

      # rpi v5.15 - bcm2835-mmc.c
      최신 라즈베리파이 OS 64비트 (前 라즈비언) 리눅스 커널 v5.15 소스
      - https://github.com/raspberrypi/linux/blob/6f921e98008589258f97243fb6658d09750f0a2f/drivers/mmc/host/bcm2835-mmc.c#L1377

      아래와 같이 request_threaded_irq 에서 3번째 인자인 thread_fn 을 넣지않거나, IRQ_NOTHREAD 플래그 설정을 안하면
      __setup_irq() 에서 irq_setup_forced_threading() 에서 handle 을 thread_fn 으로 강제하는 동작을 확인했습니다.

      ret = request_irq(host->irq, bcm2835_mmc_irq, IRQF_SHARED,
      mmc_hostname(mmc), host);

      - https://elixir.bootlin.com/linux/v5.15.35/source/include/linux/interrupt.h#L71
      #define IRQF_SHARED0x00000080

      - https://elixir.bootlin.com/linux/v5.15.35/source/include/linux/irq.h#L98
      IRQ_NOTHREAD= (1 << 16) /* 0x10000 */

      - https://elixir.bootlin.com/linux/v5.15.35/source/kernel/irq/manage.c#L1504
      if (irq_settings_can_thread(desc)) {
      ret = irq_setup_forced_threading(new);


      <질문2> 만약에 제가 이런 동작 원리를 전혀 모르고 있었다고 가정하고, 구글에 보이는 드라이버 소스 코드를 스윽 잔뜩 붙여넣기를 하여
      IRQ_NOTHREAD 플래그를 설정없이 request_irq 한 서비스들이 irq_setup_forced_threading() 로 강제되어 thread irq 로 몽땅 등록이 되면,
      어떤 문제점이 발생할 수 있나요?
      최신 커널버전의 __setup_irq() 에서 등록한 인터럽트 서비스는 되도록이면 thread irq 를 사용을 권하는 맥락이 보여집니다.
      p.s.
      제 노트북 asus ROG 는 터치 스크린 드라이버로 스레드 IRQ 방식을 쓰고 있더라구요.
    • Paran Lee 2022/04/25 13:57 # 삭제

      추가)
      (1) 라즈베리파이 400 에서 mmc 드라이버의 thread irq 확인
      kim@raspberrypi:~ $ ps -ef | grep "irq"
      root 89 2 0 00:24 ? 00:00:00 [irq/47-mmc0]

      (2) thread IRQ 강제하는 irq_setup_forced_threading() 함수
      https://elixir.bootlin.com/linux/v5.15.35/source/kernel/irq/manage.c#L1356

      irq_setup_forced_threading(struct irqaction *new)
      안에서
      new->thread_fn = new->handler;
    • AustinKim 2022/04/26 20:15 #

      5.15.33 버전 라즈비안을 라즈베리 파이 4B에 올려서 ftrace를 확인하니 아래와 같은 메시지가 확인되는군요.

      <idle>-0 [000] d.h1. 691.622997: irq_handler_entry: irq=47 name=mmc1
      <idle>-0 [000] d.h1. 691.622998: bcm2835_mmc_irq+0x8/0x854 <ffffffdeb2577228> <-__handle_irq_event_percpu+0xc4/0x370 <ffffffdeb1d0bb24>
      kworker/u9:2-624 [001] d..2. 691.622999: sched_switch: prev_comm=kworker/u9:2 prev_pid=624 prev_prio=100 prev_state=D ==> next_comm=swapper/1 next_pid=0 next_prio=120
      <idle>-0 [000] d.h1. 691.623001: <stack trace>
      => bcm2835_mmc_irq+0xc/0x854 <ffffffdeb257722c>
      => __handle_irq_event_percpu+0xc4/0x370 <ffffffdeb1d0bb24>
      => handle_irq_event+0x70/0x16c <ffffffdeb1d0bed4>
      => handle_fasteoi_irq+0xcc/0x220 <ffffffdeb1d11ddc>
      => handle_domain_irq+0xa4/0xf0 <ffffffdeb1d0b168>
      => gic_handle_irq+0x58/0xe0 <ffffffdeb1c10138>
      => call_on_irq_stack+0x2c/0x58 <ffffffdeb1c173b4>
      => do_interrupt_handler+0x5c/0x70 <ffffffdeb1c1929c>
      => el1_interrupt+0x30/0x80 <ffffffdeb27db4c0>
      => el1h_64_irq_handler+0x18/0x24 <ffffffdeb27dc0a8>
      => el1h_64_irq+0x78/0x7c <ffffffdeb1c11b74> // 익셉션 벡터 주소에서 브랜치되는 심벌
      => arch_cpu_idle+0x1c/0x2c <ffffffdeb27dc7e0>
      => default_idle_call+0x5c/0xe8 <ffffffdeb27e6c8c>
      => do_idle+0x260/0x2b0 <ffffffdeb1cd3940>
      => cpu_startup_entry+0x34/0x90 <ffffffdeb1cd3bb4>
      => rest_init+0x160/0x174 <ffffffdeb27dd490>
      => arch_call_rest_init+0x1c/0x28 <ffffffdeb2c40ba8>
      => start_kernel+0x6dc/0x71c <ffffffdeb2c41320>
      => __primary_switched+0xc0/0xc8 <ffffffdeb2c40364>
      <idle>-0 [000] d.h1. 691.623016: irq_handler_exit: irq=47 ret=handled

      라즈베리 파이 4B에서는 bcm2835_mmc_irq() 함수가 인터럽트 핸들러로 등록돼 사용됩니다. 라즈베리 파이 400은 약간
      달리 동작하는 것 같은데요.

      인터럽트 핸들러로 irq_default_primary_handler() 함수가 호출된 다음에,

      static irqreturn_t irq_default_primary_handler(int irq, void *dev_id)
      {
      return IRQ_WAKE_THREAD;
      }

      bcm2835_mmc_irq() 함수가 threaded IRQ 의 스레드 핸들러로 호출될 꺼에요.
      사실 많은 드라이버가 이런 방식을 사용하긴 합니다.

      그럼 화이팅! 하세요.
    • AustinKim 2022/04/26 20:17 #

      바닐라 리눅스 커널 소스에 drivers/mmc/host/bcm2835-mmc.c 드라이버가 없구요. 해당 파일은 라즈베리파이 보드에서 구동되는 mmc 드라이버 코드(BSP로 봐도 무방)입니다.
    • Paran Lee 2022/04/26 21:41 # 삭제 답글

      네 감사합니다!
      라즈베리파이 4 에서도 모델별로 동작이 다르네요!
      감사합니다~
    • JohnLee 2023/02/01 17:09 # 삭제 답글

      지금 보고 있는 단원과 크게 관련은 없지만 mmc1에 관한 interrupt를 주로 활용하셔서 mmc1이 무엇일까 하여 검색해보았는데
      SD카드와 기능이 같은 Multi Media Card인 것 같았습니다.(아니라면... 뭘까요?)

      그런데 현재 raspberry pi 3과 4 는 micro SD를 사용하는데 왜 아직 interrupt 이름이 mmc일까요 이것도 레거시라서 그런건가요?
      아님 eMMC라고 임베디드 mmc라는 것이 있던데 현재는 mmc를 내장하여서 아직 있는 것인가요?(제가 가지고 있는 라파는 다 발열판으로 가려서... 모델명이 안 보이네요...)
    댓글 입력 영역