3 min read

리눅스 인터럽트 핸들러 부팅과정 분석

리눅스에서는 인터럽트를 호출되기 위해서는 최소한 한번의 등록이 필요하다.

이는 부팅과정에 이루어지며 인터럽트의 예는 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에서 호출한걸 안듯이 부팅중에 등록이 발생한거를 알수있다.