Linux 内核 request_irq 引起的Call Trace等问题

奇怪的是在2.6用request_irq时发现好几个问题
我引入的头文件如下:
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/signal.h>

1、不认识SA_INTERRUPT,会提示 implicite declartion of SA_INTERRUPT
后来发现2.6下没有对SA_INTERRUPT的宏定义,而在2.4下定义为0x20000000。但是若在request_irq时直接用0x20000000时则可以用,而且成功后返回值为0
但是我在2.6下用哪个中断标志比较好呢?

2、编译的时候提示一个警告:
warning: passing argument 2 of ‘request_irq’ from incompatible pointer type

3、运行时触发中断时发生:
irq event 126: bogus return value b0043000
Call Trace:
[ <8002043c>] dump_stack+0x8/0x34
[ <80072314>] __report_bad_irq+0x44/0xd8
[ <800726f0>] note_interrupt+0x348/0x3c8
[ <800714d4>] __do_IRQ+0x164/0x1a4
[ <800115e0>] plat_irq_dispatch+0x268/0x288
[ <80019340>] ret_from_irq+0x0/0x4
[ ] MACTasks+0xf54/0x28b4 [zigbee]
[ ] ZigBeeTasks+0x1d8/0x43c [zigbee]
[ ] testRfd+0xb0/0xca8 [zigbee]
[ ] uspi_ioctl+0x18/0x30 [zigbee]
[ <800bea34>] do_ioctl+0xc4/0xd4
[ <800beab8>] vfs_ioctl+0x74/0x3d4
[ <800bee68>] sys_ioctl+0x50/0x98
[ <80022670>] stack_done+0x20/0x3c

handlers:
[ ] (HighISR+0x0/0x474 [zigbee])

关于问题1,这个是中间过渡版本里的定义,自从2.6.24后就被remove了。 你可以用对应的现在的宏,IRQF_DISABLED
原来以SA_开头的定义很不好,跟信号容易混到一块。
还有SA_INTERRUPT指的是快速中断也不明显,现在意思清楚了很多。
+/*

    • Migration helpers. Scheduled for removal in 1/2007
    • Do not use for new code !
  • */
    +#define SA_INTERRUPT          IRQF_DISABLED
    +#define SA_SAMPLE_RANDOM      IRQF_SAMPLE_RANDOM
    +#define SA_SHIRQ              IRQF_SHARED
    +#define SA_PROBEIRQ            IRQF_PROBE_SHARED

关于问题2,请检查你用的内核源码中request_irq函数的原形,看看与你程序中使用的request_irq函数参数类型是否一致,我记得是改动过。
如果不相同最好修改程序中的定义方式,改动很小,很容易。

关于2, 参数strcut pt_regs 去掉了,因为没有用。

irqreturn_t (*handler)(int, void *, struct pt_regs *)
int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
                unsigned long flags, const char *dev_name, void *dev_id);

变为
typedef irqreturn_t (*irq_handler_t)(int, void *);
int request_irq(unsigned int irq, irq_handler_t handler,
                unsigned long irqflags, const char *devname, void *dev_id)

关于问题3,你的中断处理函数  有没有类似这样的返回

return IRQ_HANDLED;

从你的log看来是这样的,你check一下:
irq event 126: bogus return value b0043000
Call Trace:
[ <8002043c>] dump_stack+0x8/0x34
[ <80072314>] __report_bad_irq+0x44/0xd8

static void
__report_bad_irq(unsigned int irq, struct irq_desc *desc,
                irqreturn_t action_ret)
{
        struct irqaction *action;
                                                                                                                         
        if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
                printk(KERN_ERR “irq event %d: bogus return value %x/n”,
                                irq, action_ret);
        } else {
                printk(KERN_ERR "irq %d: nobody cared (try booting with "
                                “the /“irqpoll/” option)/n”, irq);
        }

原来是在2.6下中断处理函数一定要有返回值(0或1),而在2.4下则没有要求!

作者:willand1981
来源:优快云
原文:https://blog.youkuaiyun.com/willand1981/article/details/5701068
版权声明:本文为博主原创文章,转载请附上博文链接!

<think>好的,我现在需要帮助用户分析Linux内核崩溃或调用栈问题,涉及blk_mq、scsi_io_completion和handle_percpu_devid_fasteoi_ipi这些函数。首先,我得回顾用户之前的问题和我的回答,确保连贯性。用户之前询问了关于blk_mq框架下SCSI请求完成的调用堆栈,我给出了详细的分析步骤和相关工具的使用建议。现在用户的新问题涉及内核崩溃或调用栈分析,可能与中断处理、SCSI请求完成或块设备队列相关。我需要结合用户提供的引用和之前的知识来解答。 首先,用户提供的引用中,引用[1]提到了进程调度中的switch_mm函数,这可能与上下文切换有关,但当前问题更关注中断和块设备。引用[2]是关于编译错误的解决方案,可能与当前问题关系不大。引用[3]是深度学习模型的错误,可能也不相关。引用[4]提到了Linux内核的TCP/IP栈,但用户的问题是关于块设备和SCSI的,所以可能不需要这部分。不过需要确认是否有其他联系。 用户当前的调用栈涉及handle_percpu_devid_fasteoi_ipi,这是处理IPI(处理器间中断)的函数,属于中断处理的一部分。结合之前的分析,SCSI请求完成时会触发中断,然后进入软中断处理,可能涉及IPI。这可能与多核环境下的并发操作有关,比如在释放资源时出现竞争条件。 接下来,我需要确定如何分析这类崩溃或调用栈问题。可能的步骤包括: 1. **调用栈解析**:检查崩溃时的调用栈,确定各个函数的关系。例如,handle_percpu_devid_fasteoi_ipi属于IPI处理,可能在多核间同步时出现问题。 2. **并发与锁分析**:检查涉及到的代码路径是否正确地使用了锁,尤其是在中断上下文和进程上下文之间的共享资源访问。 3. **内存管理问题**:如引用[1]中的mm_struct切换,可能在某些情况下导致地址空间错误,但需要结合具体上下文。 4. **硬件相关错误**:SCSI设备可能出现硬件故障,导致IO完成处理异常,进而引发内核崩溃。 5. **调试工具使用**:如trace-cmd、perf、kdump等,帮助捕捉崩溃时的状态和调用路径。 需要考虑到用户提到的blk_mq、scsi_io_completion,这些属于块层和SCSI子系统的交互。在之前的回答中,我提到了scsi_end_request会通过blk_mq_end_request通知块层请求完成,而最终可能触发IPI处理,比如在软中断中。如果在处理这些请求时,资源已被释放或出现竞争,可能导致崩溃。 可能的根本原因包括: - **无效指针访问**:在请求完成后,结构体可能已被释放,但中断处理仍尝试访问。 - **锁未正确获取**:在中断上下文中未能正确禁用中断或获取自旋锁,导致数据竞争。 - **中断风暴**:设备中断处理异常,导致系统资源耗尽。 - **内核配置或版本问题**:某些内核版本的已知bug可能导致此类问题。 建议用户进行以下步骤: 1. **获取完整崩溃日志和Oops信息**:分析寄存器状态、堆栈回溯,确定崩溃点。 2. **检查相关内核代码**:特别是scsi_io_completion、blk_mq_free_request等函数的实现,确认是否存在潜在的竞态条件。 3. **使用调试工具复现问题**:如kdump生成vmcore,利用crash工具分析。 4. **确认硬件状态**:检查SCSI设备是否正常工作,排除硬件故障。 另外,结合引用[2],虽然主要解决编译问题,但如果用户在内核编译时启用了堆栈保护,可能需要检查是否有栈溢出导致的问题,不过可能性较低。引用[3]的BLAS错误可能与当前问题无关,但如果有用户空间和内核空间的交互问题,也可能需要考虑,但暂时可以忽略。 最后,需要生成相关问题,帮助用户进一步排查,比如关于blk_mq的并发处理、中断上下文的安全操作、内核调试工具的使用等。</think>### Linux内核崩溃/调用栈分析(涉及blk_mq、SCSI、IPI) #### 一、关键调用路径分析 根据堆栈信息中的函数链: ``` handle_percpu_devid_fasteoi_ipi → do_handle_IPI → flush_smp_call_function_queue → __blk_mq_complete_request_remote → scsi_softirq_done → scsi_finish_command → scsi_io_completion → scsi_end_request → blk_mq_end_request → blk_mq_free_request ``` 这揭示了**跨CPU核的请求完成处理流程**,主要涉及以下子系统交互: 1. **IPI(处理器间中断)**:通过`handle_percpu_devid_fasteoi_ipi`处理跨核中断 2. **块设备队列**:`blk_mq`框架的请求释放路径 3. **SCSI子系统**:IO完成回调`scsi_io_completion` #### 二、常见崩溃场景及分析方法 ##### 场景1:跨核竞争条件(Race Condition) 当`blk_mq`在多个CPU核上并行处理请求时,若资源未正确同步,可能导致: - **UAF(Use-After-Free)**:请求结构体在CPU-A释放后,CPU-B仍尝试访问 - **内存损坏**:并发修改共享数据结构(如`sbitmap`队列) **调试方法**: 1. 检查内核配置`CONFIG_DEBUG_ATOMIC_SLEEP`,捕获非法原子上下文操作 2. 使用`KASAN`检测内存访问越界: ```bash echo 1 > /proc/sys/kernel/kptr_restrict # 解除符号限制 dmesg | grep "BUG: KASAN" ``` 3. 通过`trace-cmd`追踪跨核函数调用: ```bash trace-cmd record -e sched:sched_switch -e irq:irq_handler_entry ``` ##### 场景2:中断上下文异常 `handle_percpu_devid_fasteoi_ipi`属于**中断上下文**,若在此上下文中执行了以下操作会引发崩溃: - 调用可能睡眠的函数(如`kmalloc(GFP_KERNEL)`) - 未正确关闭本地中断导致嵌套中断 **检查点**: ```c // 在drivers/scsi/scsi_lib.c中检查scsi_io_completion if (in_interrupt()) { printk(KERN_ERR "非法上下文调用!\n"); // 使用WARN_ON_ONCE(in_interrupt())更优 } ``` ##### 场景3:SCSI设备状态异常 当SCSI设备返回异常状态(如`CHECK_CONDITION`)时,若驱动未正确处理可能触发二次错误。 **诊断步骤**: 1. 捕获SCSI命令状态码: ```bash echo 1 > /sys/module/scsi/parameters/logging_level # 启用SCSI调试日志 dmesg | grep "scsi.*status" ``` 2. 检查SCSI层错误处理路径: ```c // drivers/scsi/scsi_error.c scsi_check_sense() ``` #### 三、关键代码定位与修复 ##### 1. blk_mq请求释放路径 文件:`block/blk-mq.c` ```c void blk_mq_free_request(struct request *rq) { struct request_queue *q = rq->q; // 检查request的引用计数 if (unlikely(!__blk_mq_free_request(rq))) return; // 可能触发sbitmap队列唤醒(注意锁状态) sbitmap_queue_clear(&q->sched_bitmap_tags, rq->internal_tag); } ``` **风险点**:`sbitmap_queue_clear`未正确处理多核竞争可能导致位图损坏。 ##### 2. IPI处理逻辑 文件:`kernel/smp.c` ```c void flush_smp_call_function_queue(void) { // 遍历待处理回调函数 while (entry) { func = entry->func; func(info); // 此处调用__blk_mq_complete_request_remote entry = entry->next; } } ``` **注意**:回调函数必须在原子上下文中执行,且不能持有锁。 #### 四、实战调试工具 | 工具 | 用途 | 示例命令 | |----------------|-----------------------------------|---------------------------------------------| | `crash` | 分析vmcore转储文件 | `crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux vmcore` | | `ftrace` | 追踪函数调用关系 | `echo function_graph > /sys/kernel/debug/tracing/current_tracer` | | `perf` | 捕获实时调用栈 | `perf record -g -a -e cycles` | | `objdump` | 反汇编内核函数 | `objdump -dS vmlinux > vmlinux.asm` | #### 五、修复建议 1. **增加同步机制**:在`blk_mq_free_request`中使用`atomic_inc_not_zero`确保请求存活 2. **限制IPI范围**:通过`cpumask`限制回调函数仅在相关CPU核执行 3. **强化错误处理**:在`scsi_io_completion`中增加异常状态断言 ```c BUG_ON(scsi_result != DRIVER_OK); // 仅调试阶段使用 ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值