인터럽트 디스크립터란?
- 인터럽트에 대한 객체를 관리하는 자료구조.
linux/include/linux/irqdesc.h에서 볼 수 있다.
struct irq_desc {
...
unsigned int __percpu *kstat_irqs;
...
struct irqaction *action; /* IRQ action list */
...
}
kstat_irqs: 인터럽트가 발생한 횟수 저장
action: 인터럽트의 주요 정보 저장
irqaction은 linux/include/linux/interrupt.h에서 볼 수 있다.
struct irqaction {
irq_handler_t handler;
void *dev_id;
...
irq_handler_t thread_fn;
...
unsigned int irq;
unsigned int flags;
...
}
handler: 인터럽트 핸들러의 함수 주소
*dev_id: 인터럽트 핸들러에 전달되는 매개변수 (ex bcm2835_host)
thread_fn: threaded IRQ 함수의 주소
irq: 인터럽트 번호
flags: 인터럽트 플래그 (RISING, FALLING, HIGH, LOW)
인터럽트 디버깅
- 인터럽트 핸들러에 ftrace 설정하기
echo 1 > /sys/kernel/debug/tracing/events/irq/irq_handler_entry/enable
echo 1 > /sys/kernel/debug/tracing/events/irq/irq_handler_exit/enable
- ftrace 메시지 분석
kworker/u8:0-8 [001] d.h.. 213.981681: irq_handler_entry: irq=27 name=arch_timer
kworker/u8:0-8 [001] d.h.. 213.981685: irq_handler_exit: irq=27 ret=handled
kworker/u8:0: 프로세스 이름
8: pid
[001]: 실행중인 cpu 번호
213.981691: 초단위 타임스탬프
irq=27: IRQ번호
name: 인터럽트 이름
- ftrace로 인터럽트 핸들러 파악하기
일단 linux/kernel/irq/handle.c에서 새로운 코드를 넣어줘야 한다. (+처리된 부분이 추가된 부분)
irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int *flags)
{
irqreturn_t retval = IRQ_NONE;
unsigned int irq = desc->irq_data.irq;
struct irqaction *action;
for_each_action_of_desc(desc, action) {
irqreturn_t res;
+ void *irq_handler = (void*)action->handler;
...
trace_irq_handler_entry(irq, action);
+ trace_printk("[+] irq:[%d] handler: %pS caller:(%pS) \n",
+ irq, irq_handler, (void*)__builtin_return_address(0));
res = action->handler(irq, action->dev_id);
trace_irq_handler_exit(irq, action, res);
...
}
}
그리고 빌드하면 다음과 같이 irq_desc, irqaction에 있는 값들을 알아볼 수 있다.
<idle>-0 [000] d.h.. 213.981640: irq_handler_entry: irq=31 name=fe00b880.mailbox
<idle>-0 [000] d.h.. 213.981642: __handle_irq_event_percpu: [+] irq:[31] handler: bcm2835_mbox_irq+0x0/0x90 caller:(handle_irq_event+0x74/0xe4)
<idle>-0 [000] d.h.. 213.981646: irq_handler_exit: irq=31 ret=handled
이 로그를 보면 irq가 31, handler함수가 bcm2835_mbox_irq로 나온다.
+ 기타
최신 배포버전의 linux/drivers/mmc/host/bcm2835-mmc.c 에선 threaded IRQ 처리 함수가 없다!
(bcm2835_mmc_thread_irq라는 함수가 없다)
이는, https://github.com/raspberrypi/linux/commit/496556b93db22d3e770a563e06cf7dc45e63ab37 에서 사라진 탓인데, 커밋내용을 보면 알 수 있다.
With SDIO processing now managed by the MMC framework with a
workqueue, the bcm2835_mmc driver no longer needs a threaded
IRQ.
MMC 프레임워크가 워크큐에서 SDIO 프로세싱을 관리함에 따라,
bcm2835_mmc 드라이버는 더이상 스레드 IRQ가 필요 없다.
봐도 이해 안된다 -_-; 아무튼 이런 이유로 인터럽트 실행 횟수를 확인하는 실습은 못했다.
'디버깅을 통해 배우는 리눅스 커널의 구조' 카테고리의 다른 글
리눅스 커널 스터디 결산 (1주차) (0) | 2022.06.17 |
---|---|
IRQ 스레드 (threaded IRQ) (0) | 2022.06.17 |
bcm2711 라즈베리파이에서 bcm2835 라이브러리 사용 (0) | 2022.06.12 |
스터디 계획(1주차) (0) | 2022.06.11 |
_do_fork의 행방 (0) | 2022.05.29 |