리눅스 인터럽트 핸들러 부팅과정 분석
리눅스에서는 인터럽트를 호출되기 위해서는 최소한 한번의 등록이 필요하다.
이는 부팅과정에 이루어지며 인터럽트의 예는 USB나 키보드 입력등이 흔한 예다.
아래는 부팅중에 하나의 인터럽트의 코드중하나이다.
#if defined(PLATFORM_INTERFACE)
devirq = platform_get_irq_byname(_dev, fiq_enable ? "soft" : "usb");
if (devirq < 0)
devirq = platform_get_irq(_dev, fiq_enable ? 0 : 1);
#else
devirq = _dev->irq;
#endif
DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
devirq);
dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq);
retval = request_irq(devirq, dwc_otg_common_irq,
IRQF_SHARED,
"dwc_otg", dwc_otg_device);
https://github.com/raspberrypi/linux/blob/rpi-4.19.y/drivers/usb/host/dwc_otg/dwc_otg_driver.c
인터럽트를 등록하는 함수는 request_irq이며 안에는 request_threaded_irq을 호출하는거말구 아무것도 안한다.
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn, unsigned long irqflags,
const char *devname, void *dev_id)
{
struct irqaction *action;
struct irq_desc *desc;
int retval;
if (irq == IRQ_NOTCONNECTED)
return -ENOTCONN;
......
action->handler = handler;
action->thread_fn = thread_fn;
action->flags = irqflags;
action->name = devname;
action->dev_id = dev_id;
if (irq == 56 || irq == 86) {
printk("[+][irq_debug] irq_num: %d, func: %s, line:%d, caller:%pS \n",
irq, __func__, __LINE__, (void *)__builtin_return_address(0));
dump_stack();
}
부팅중의 IRQ의 등록을 확인하기 위하여 위에 코드에 if문을 추가해 콜스택을 출력해주는 함수를 작성하고 리눅스 컴파일을 하여 재부팅을 시켜주자.
재부팅이 완료되면 /var/log/kern log을 참조하자.
Jun 29 15:11:34 raspberrypi kernel: [ 0.504289] Finished setting default values for core params
Jun 29 15:11:34 raspberrypi kernel: [ 0.504491] [+][irq_debug] irq_num: 56, func: request_threaded_irq, line:1852, caller:dwc_otg_driver_probe+0x4e0/0xb54
Jun 29 15:11:34 raspberrypi kernel: [ 0.504504] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.19.127-v7+ #1
Jun 29 15:11:34 raspberrypi kernel: [ 0.504509] Hardware name: BCM2835
Jun 29 15:11:34 raspberrypi kernel: [ 0.504541] [<80112018>] (unwind_backtrace) from [<8010d364>] (show_stack+0x20/0x24)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504560] [<8010d364>] (show_stack) from [<808519b4>] (dump_stack+0xd8/0x11c)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504582] [<808519b4>] (dump_stack) from [<80183cd4>] (request_threaded_irq+0x1a0/0x1a4)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504599] [<80183cd4>] (request_threaded_irq) from [<80668f70>] (dwc_otg_driver_probe+0x4e0/0xb54)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504618] [<80668f70>] (dwc_otg_driver_probe) from [<805e4ea8>] (platform_drv_probe+0x58/0xa8)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504633] [<805e4ea8>] (platform_drv_probe) from [<805e306c>] (really_probe+0x20c/0x2cc)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504647] [<805e306c>] (really_probe) from [<805e3300>] (driver_probe_device+0x70/0x188)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504660] [<805e3300>] (driver_probe_device) from [<805e3514>] (__driver_attach+0xfc/0x100)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504676] [<805e3514>] (__driver_attach) from [<805e0f7c>] (bus_for_each_dev+0x84/0xc4)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504749] [<805e4dfc>] (__platform_driver_register) from [<80c3c6d0>] (dwc_otg_driver_init+0x78/0x11c)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504765] [<80c3c6d0>] (dwc_otg_driver_init) from [<80103004>] (do_one_initcall+0x50/0x220)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504783] [<80103004>] (do_one_initcall) from [<80c01348>] (kernel_init_freeable+0x340/0x3e0)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504799] [<80c01348>] (kernel_init_freeable) from [<80866bc0>] (kernel_init+0x18/0x128)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504814] [<80866bc0>] (kernel_init) from [<801010ac>] (ret_from_fork+0x14/0x28
)
여기서
Jun 29 15:11:34 raspberrypi kernel: [ 0.504491] [+][irq_debug] irq_num: 56, func: request_threaded_irq, line:1852, caller:dwc_otg_driver_probe+0x4e0/0xb54
Jun 29 15:11:34 raspberrypi kernel: [ 0.504504] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.19.127-v7+ #1
Jun 29 15:11:34 raspberrypi kernel: [ 0.504765] [<80c3c6d0>] (dwc_otg_driver_init) from [<80103004>] (do_one_initcall+0x50/0x220)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504783] [<80103004>] (do_one_initcall) from [<80c01348>] (kernel_init_freeable+0x340/0x3e0)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504799] [<80c01348>] (kernel_init_freeable) from [<80866bc0>] (kernel_init+0x18/0x128)
Jun 29 15:11:34 raspberrypi kernel: [ 0.504814] [<80866bc0>] (kernel_init) from [<801010ac>] (ret_from_fork+0x14/0x28
)
을 확인할수 있듯이 irq는 cpu 2에 의해 실행되는걸 확인할수있고 do_one_initcall에서 호출한걸 안듯이 부팅중에 등록이 발생한거를 알수있다.