【问题标题】:What is the canonical way to execute code directly from a QEMU device?直接从 QEMU 设备执行代码的规范方法是什么?
【发布时间】:2019-07-24 13:18:10
【问题描述】:

我正在为一个特定的评估板建模,它有一个 leon3 处理器和多个映射到特定地址的 MRAM 组。我的目标是使用我的引导加载程序 ELF 启动 qemu-system-sparc,然后跳转到 MRAM 库的基地址以开始在其中执行裸机程序。为此,我已经能够成功运行我的引导加载程序并跳转到第一条指令,但是 QEMU 立即停止并退出而没有报告任何错误/陷阱。我还可以通过将 ELF 格式的裸机程序作为内核传递给 qemu-system-sparc 来单独运行裸机程序。

短版:是否有规范的方法来设置设备,以便可以直接从中执行代码?编译该代码以使其正确执行时,我需要采取哪些步骤?

我将 MRAM 建模为具有 MemoryRegion 的设备,以及适当的读写操作,以在我的程序中公开堆分配的数组。在我的板代码(qemu/hw/sparc/leon3.c 的修改版本)中,对 MRAM 地址的写入被映射到设备的 MemoryRegion。使用 printfs,我以未实现设备 (qemu/hw/misc/unimp.c) 的样式报告读取和写入,并且我已验证我正在正确读取和写入设备。

很遗憾,这对于在设备上运行代码不起作用。在引导加载程序跳转到我设备的基地址后,我可以立即看到读取内容,但读取的指令实际上并没有做任何事情。引导加载程序使用 void 函数指针,该指针与 MRAM 设备的地址绑定以引发跳转。

我尝试的另一种方法是从地址 0 开始为我的设备创建一个别名;我想也许我的二进制文件的所有地址都设置为相对于零,因此通过将地址 [0, MRAM_SIZE) 的写入作为别名映射到我的设备基地址,代码最终将读取设备 MemoryRegion 中的相应指令。

这种方法在 memory.c 中的断言失败:

static void memory_region_add_subregion_common(MemoryRegion *mr,
                                               hwaddr offsset,
                                               MemoryRegion *subregion)
{
    assert(!subregion->container);
    subregion->container = mr;
    subregion->addr = offset;
    memory_region_update_container_subregions(subregion);
}

我需要做什么来强制 QEMU 在我的 MRAM 设备中执行代码?我需要生成具有绝对地址的二进制文件吗?

【问题讨论】:

    标签: c qemu sparc


    【解决方案1】:

    旧版本的 QEMU 根本无法从 RAM 或 ROM 以外的任何地方处理执行,并且尝试这样做会给出“qemu: fatal: Trying to perform code outside RAM or ROM”错误。 QEMU 3.1 及更高版本修复了这个限制,现在可以从任何地方执行代码——尽管从设备执行将比从 RAM 执行慢得多。

    您提到您“将 MRAM 建模为具有 MemoryRegion 的设备,以及适当的读写操作以公开堆分配的数组”。这听起来可能是错误的方法——它会起作用,但速度很慢。如果 MRAM 在来宾看来就像 RAM,则将其建模为 RAM(即带有 RAM MemoryRegion)。如果它就像用于读取的 RAM,但写入需要做的不仅仅是写入内存(或者有时需要这样做),那么使用“romd”区域对其进行建模,与现有的方法相同pflash 设备可以。尽管如此,将其建模为具有纯读写功能的设备应该可以工作,但速度会非常慢。

    您遇到的断言是“您不能同时将一个内存区域放入两个事物中”——您传入的“子区域”已经在其他地方使用,但是您'已经尝试将其放入第二个容器中。如果您有一个 MemoryRegion 需要出现在物理内存映射的两个位置,那么您需要: 创建 MemoryRegion;创建一个别名 MemoryRegion ,它为真实的别名;将实际的 MemoryRegion 映射到一个地方;将别名映射到另一个。在 QEMU 的现有板模型中有很多这样的例子。

    更一般地说,您需要弄清楚评估板硬件实际上是什么,然后对其进行建模。如果评估板的 MRAM 在多个物理地址可见,那么可以,使用别名 MR。如果不是,那么问题出在其他地方,您需要弄清楚实际发生了什么,而不是试图用真实硬件上不存在的别名来逃避它。 QEMU 的调试日志(各种 -d 子选项,加上 -D 文件以记录到文件)对于检查模拟 CPU 在早期启动阶段实际执行的操作很有用——但要注意日志可能非常大,而且它们除非您对 QEMU 内部结构有所了解,否则有时很难解释。

    【讨论】:

    • 感谢您的回复。目前,性能不如概念证明重要,但我会在未来调整这些以使用 romd MemoryRegions。评估板的 MRAM 库位于片外,可通过引导加载程序代码直接访问。也就是说,假设我得到了正确的寻址,我是否可以通过设置 pc、npc 来简单地跳转到该代码?
    • 是的,客户代码应该能够像跳转到任何其他内存区域一样直接跳转到 MRAM。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 2010-10-25
    • 2021-11-20
    • 2019-06-15
    • 2011-01-05
    相关资源
    最近更新 更多