我正在为一个特定的评估板建模,该评估板具有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中的相应指令。 / p>
这种方法使内存中的断言失败。
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设备中执行代码?我需要产生一个带有绝对地址的二进制文件吗?
答案 0 :(得分:1)
较早版本的QEMU根本无法处理除RAM或ROM以外的任何内容,而尝试执行此操作将产生“ qemu:致命:试图在RAM或ROM之外执行代码”错误。 QEMU 3.1和更高版本修复了此限制,现在可以在任何地方执行代码-尽管从设备执行比在RAM中执行要慢得多。
您提到您“将MRAM建模为具有MemoryRegion的设备,以及适当的读写操作以公开堆分配的数组”。听起来这可能是错误的方法-虽然可以,但是速度很慢。如果MRAM对来宾来说就像是RAM,则将其建模为RAM(即带有RAM MemoryRegion)。如果就像读取RAM一样,但是写入需要做的事情不只是写到内存中(或者有时需要做),那么可以使用“ romd”区域对其进行建模,就像现有的方式一样pflash设备可以。尽管如此,将其建模为具有纯读写功能的设备应该可以正常工作,但速度却非常慢。
您遇到的断言是“不能一次将一个内存区域放入两件事”的断言–您传入的“子区域”已经在其他地方使用,但是您试图将其放入另一个容器中。如果您有一个需要在物理内存映射中的两个位置出现的MemoryRegion,则需要:创建一个别名MemoryRegion来别名真实的别名;将实际的MemoryRegion映射到一个地方;将别名映射到另一个。 QEMU中的现有电路板模型中有很多示例。
通常,您需要确定评估板硬件实际上是什么,然后对其建模。如果评估板的MRAM在多个物理地址上可见,则可以,使用别名MR。如果不是,则问题出在其他地方,您需要弄清楚实际情况,而不是尝试使用实际硬件上不存在的别名来解决问题。 QEMU的调试日志记录(各种-d子选项,再加上-D文件记录到文件)对于检查此早期启动阶段中仿真CPU的实际作用非常有用-但请注意,因为日志可能很大,而且它们除非您对QEMU内部有一点了解,否则有时很难解释。