【问题标题】:Catching a data bus error exception in kernel mode在内核模式下捕获数据总线错误异常
【发布时间】:2015-10-23 01:35:07
【问题描述】:

我在 Virtex 5 芯片的 microblaze 上运行 Linux。我实际上有两个芯片运行相同的 Linux 代码,但芯片中有不同的 HDL 模块。我正在编写一个驱动程序,我希望能够检测它在哪个芯片上运行并基于它做不同的事情。在驱动程序初始化期间,我尝试从一个芯片上而不是另一个芯片上存在的 HDL 模块读取 ID 寄存器,但在它不存在的芯片上,我得到一个“内核中的数据总线错误异常”模式。'哎呀。有什么方法可以捕获这个异常并继续加载我的驱动程序?

代码如下:

unsigned region;
unsigned long *res;
unsigned int val;

region = request_mem_region( 0x66000000, 100, NULL );
if ( region ) {
  res = ioremap( 0x66000000, 100 );
  if ( res ) {
    val = ioread32( res ); // exception happens here
    if ( val == REGID1 )
      printk( "we are on chip 1\n" );
    else
      printk( "we are on chip 2\n" );
    iounmap( res );
  }
  release_mem_region( 0x66000000, 100 );
}

【问题讨论】:

  • 您使用的物理地址似乎是错误的。检查您的处理器 i/o 内存映射。验证 cat /proc/iomem 的范围
  • 我在问题中说地址不存在,这就是我确定代码运行在哪个芯片上的方式。我需要捕获异常并使用异常发生的事实作为指标。

标签: linux linux-kernel linux-device-driver


【解决方案1】:

Linux 启动过程对内存访问违规非常宽容,尤其是在内核代码中(例如内核模式访问)。查看 Microblaze 代码后,您无法“捕获”此类异常,因为它们会立即致命(异常处理程序将调用 die() 函数)。

【讨论】:

  • 那我不能编辑异常处理程序不调用 die() 吗?它是哪个处理程序?
  • 检查 /arch/microblaze/kernel/exceptions.c,在 MICROBLAZE_DBUS_EXCEPTION 的情况下,在第 106 行附近。我想您可以编辑代码以简单地以用户模式下的方式返回,然后重建所有内容。至少那时它不应该是致命的......
【解决方案2】:

在 AXI 总线上带有 FPGA 结构的 ARM64 SoC 上遇到类似问题,我想在这里分享我找到的解决方案:

Linux 内核提供(在 4.14 内核上检查)一个名为 probe_kernel_read(以及 probe_kernel_write)的函数,它捕获对不存在的 FPGA 寄存器的访问(在这种情况下,我的 FPGA 显式中止传输),以及访问非对齐地址(在我的设计中未处理)。

probe_kernel_read 似乎不是为 IOMEM 资源设计的,不像 ioread32readl,但由于我的 FPGA 被映射为设备内存(请参阅 ARM ARM),这不应该成为问题我。我还直接在 AXI 总线上检查了一些事务,没有发现任何问题。请注意,行为可能取决于 CPU 架构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-06
    • 2014-11-06
    • 2018-11-13
    • 2019-04-09
    • 2015-06-11
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多