6

我想编写我的代码来处理 Microblaze 上的 TLB 未命中,当然还有页表等。这一切都在 OVPsim 上完成。

当我边走边学的时候,我编写了这个小程序集来引用一个未映射的位置(0x1000000)——我将它作为特权代码运行,并在 VM 上运行:

ori r20, r0, 0
ori r12, r0, 0x1000000
/* next line should break it */
sw  r20, r12, r0

(即,将r20 == 0out的内容写入ORing形成的地址r12 == 0x1000000r0 == 0 => 0x1000000显然。)

但是 GDB 没有跳转到异常向量,而是报告“程序收到 SIGSEV”——我做错了什么?我没有在 MSR 中启用硬件异常位,但手册说您在任何情况下都不能屏蔽这些异常,所以这不应该是问题。

更多信息无论我是否使用调试器,我都无法执行任何异常处理代码(例如,包括未对齐异常)(除非我明确调用它)。关闭调试器后,我从 OVPsim 得到了这个输出(注意我只是改变了测试地址——上面的 0xA000000 和 0x100000 之间的区别没有意义):

Processor Exception (PC_PRX) Processor 'platform/cpu0' 0x248: sw       r20, r12, r0
Processor Exception (PC_WPX) No write access at 0xa000000

这是所有代码都在特权模式下运行,所以我看不出它不调用处理程序的明显理由,除非我没有正确配置 Microblaze。我打开了这些:

icmAddStringAttr(cpu1_attr, "endian", "big");
icmAddDoubleAttr(cpu1_attr, "mips", 100.000000);
icmAddStringAttr(cpu1_attr, "variant", "V8_20");
icmAddBoolAttr(cpu1_attr, "verbose", "true");
icmAddUns32Attr(cpu1_attr, "C_PVR", 2);
icmAddUns32Attr(cpu1_attr, "C_USE_MMU", 3);
icmAddStringAttr(cpu1_attr, "C_USE_BARREL", "1");
icmAddStringAttr(cpu1_attr, "C_USE_DIV", "1");
icmAddUns32Attr(cpu1_attr, "C_USE_INTERRUPT", 1);
icmAddUns32Attr(cpu1_attr, "C_MMU_TLB_ACCESS", 3);
icmAddUns32Attr(cpu1_attr, "C_UNALIGNED_EXCEPTIONS", 1);
icmAddUns32Attr(cpu1_attr, "C_ILL_OPCODE_EXCEPTION", 1);
icmAddUns32Attr(cpu1_attr, "C_DIV_ZERO_EXCEPTION", 1);
icmAddUns32Attr(cpu1_attr, "C_OPCODE_0x0_ILLEGAL", 1);
icmAddUns32Attr(cpu1_attr, "C_DEBUG_ENABLED", 1);

没有理由相信这不会奏效,因为 OVPsim 将在 Microblaze 上运行 Linux。

4

2 回答 2

3

您的 TLB 异常已生成,是 GDB 阻止您进入处理程序。

调试 VM 模式是一件棘手的事情。我不熟悉 OVPsim 以及它与 GDB 的集成程度,但有几种方法可以帮助您完成它:

  1. 显式软件断点。只需brk r16, 0x18在要在代码中设置断点的地方使用指令,然后让 GDB 使用continue命令即可。一旦执行此中断,它将停止,无论是其 VM 用户代码还是异常处理程序。

    不利的一面是,一旦达到这种中断,就没有简单的方法从 GDB 继续。您需要修改r16到下一个指令地址,或者用GDB替换您的brk指令。nop

  2. 硬件断点。这是您可以用来调试异常端和 VM 端代码的最简单的中断,而无需担心 TLB 页面的存在。但是硬件断点需要 Microblaze 的硬件支持(不确定 OSPsim 是否支持它们)。要在 GDB 中使用它,只需使用hbreak(或hb) 而不是break命令。

  3. GDB 软断点。如果您知道它们是如何工作的并且您的 VM 模型足够简单,那么您仍然可以使用常规样式的 GDB 断点。基本上,GDB 需要对要中断的代码页的写访问权(以便编写brk指令)。因此,在 VM 模式下,您必须确保该页面存在于 TLB 中并具有写入权限。

    当您的虚拟地址与物理地址不同时,将非 VM 模式的中断设置为 VM 代码甚至更加棘手。您需要确保要放置断点的页面已加载到物理内存中,并手动将虚拟地址转换为物理地址并设置断点。因此,除非您有 1:1 映射(并且所有代码和数据都在内存中)或者您编写了自己的GDB stub,否则使用 GDB 断点是一种绘画。

不幸的是,单步执行 GDB 中的代码几乎就像一直使用 GDB 软断点一样。即你可以进入非 VM 代码,或者进入具有写入权限的单个加载的 VM 页面。但是一旦你需要处理 TLB 之外的事情或从非 VM 访问 VM 代码,它就会变得非常令人沮丧。

于 2014-11-19T19:01:18.020 回答
2

感谢约克大学实时系统小组的 Jamie Garside:OVP 模拟器的默认设置是捕获异常并退出模拟,这就是为什么没有以我预期的方式执行任何异常 - 相反它们只是被报告为某种错误,模拟被暂停。

但是,如果ICM_ATTR_SIMEX为模拟定义了 ,那么模拟将以真实处理器的方式执行异常处理程序 - 因此添加ICM_ATTR_SIMEX到我的实例的属性 - 例如,通过 ORing 如下所示,将所有内容放在正确的位置:

#define SIM_ATTRS (ICM_ATTR_DEFAULT|ICM_ATTR_SIMEX)
于 2014-11-20T19:43:24.603 回答