I am trying to get a custom embedded 386 computer to be virtualized with qemu. In order to avoid loading my program from disk, I'm including the target binary inside a custom kernel. This kernel is used as a bootloader, and uses nasm's incbin to include the raw binary dump of target. This works, and I am able to execute code, but if I run a checksum on the loaded data, it fails to match what it should be.
I'm loading the data in RAM at 0x20000, which overlaps the video memory. I suspect that the system is tinkering with these bits between the time that the "-kernel" parameter loads the kernel and the time it's actually executed. If I pass "-vga none" I would expect no video hardware to load, but qemu crashes before it even gets to my code.
The error I get is "(qemu) qemu: fatal: Trying to execute code outside RAM or ROM at 0x1badb002"
Does anyone know of an easy way to either manually load the program into RAM or make sure that the area is protected from the BIOS and Qemu updating it? Since I'm working on a custom board in a custom system, I can't rely on the standard memory maps.
Thanks!
Running QEMU as Embedded Guest
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Running QEMU as Embedded Guest
Video memory starts at 0xA0000, and there's some system-critical memory owned by the firmware just before that. If your binary really is that bigI'm loading the data in RAM at 0x20000, which overlaps the video memory.
- you probably made an error making that binary.
- you shouldn't be loading it to that address because it doesn't fit.
Also, there's a VGA device at 0xA0000 and not actual RAM. If you write to that address it might not get stored at all, nor can it typically be read back in the same way.
Re: Running QEMU as Embedded Guest
I take it from your comment that I don't fully understand the memory used by a default QEMU configuration. Where can I find out what the firmware owns?
To address your two points:
- The binary I'm using is a software release that is identical to the one running on physical hardware. It is an image that is loaded directly into ram at those locations. This is unchangeable on the real system. Because the binary is a RAM image, the symbols are all absolute (I have no relocation information, and I am not decoding ELF or any other encoding). I am able to follow the code in the debugger as it correctly completes many relative and absolute jumps. This leads me to have high confidence in the location and size.
- The binary needs to be placed at 0x20000 and it has 0xCC6D0 bytes. On the board that I am emulating, there is no video output, so the original developers did not have this limitation. I am probably being stupid, but that would place the binary image under 945 Kilobytes from the beginning of RAM. My board has a whopping 2MB, so it "fits". I think we agree that the firmware is reserving some of this space. Can I change this? The real board runs a custom firmware that is explicitly designed to use the space lower than 0x20000.
To address your two points:
- The binary I'm using is a software release that is identical to the one running on physical hardware. It is an image that is loaded directly into ram at those locations. This is unchangeable on the real system. Because the binary is a RAM image, the symbols are all absolute (I have no relocation information, and I am not decoding ELF or any other encoding). I am able to follow the code in the debugger as it correctly completes many relative and absolute jumps. This leads me to have high confidence in the location and size.
- The binary needs to be placed at 0x20000 and it has 0xCC6D0 bytes. On the board that I am emulating, there is no video output, so the original developers did not have this limitation. I am probably being stupid, but that would place the binary image under 945 Kilobytes from the beginning of RAM. My board has a whopping 2MB, so it "fits". I think we agree that the firmware is reserving some of this space. Can I change this? The real board runs a custom firmware that is explicitly designed to use the space lower than 0x20000.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Running QEMU as Embedded Guest
QEMU, and pretty much every other VM/emulator out there, implements an IBM PC-compatible clone. If your reference board has contiguous ram from A0000-FFFFF, then it's a completely different machine, and I doubt you can find anything that would be able to virtualise that out of the box. Most likely, your devices are equally incompatible with the ones you find on a desktop.
In other words, you'll have to modify the virtual hardware first, followed by writing custom firmware for your machine.
In addition QEMU doesn't actually emulate an i386. It emulates a copy of your computer's CPU. If you intent to continue, you'll probably want to get a copy of Bochs and modify that to match whatever hardware you actually have on the target platform.
In other words, you'll have to modify the virtual hardware first, followed by writing custom firmware for your machine.
In addition QEMU doesn't actually emulate an i386. It emulates a copy of your computer's CPU. If you intent to continue, you'll probably want to get a copy of Bochs and modify that to match whatever hardware you actually have on the target platform.
- xenos
- Member
- Posts: 1118
- Joined: Thu Aug 11, 2005 11:00 pm
- Libera.chat IRC: xenos1984
- Location: Tartu, Estonia
- Contact:
Re: Running QEMU as Embedded Guest
Wait, doesn't QEMU have an option which CPU to emulate? Also, there are qemu-system-i386 and qemu-system-x86_64, both of which should emulate the desired architecture, regardless of whether they run on i386 or x86_64 hardware.Combuster wrote:In addition QEMU doesn't actually emulate an i386. It emulates a copy of your computer's CPU.
Re: Running QEMU as Embedded Guest
I am using qemu-system-i386, and not using KVM. I believe this does it's best to emulate the 386. If not, I'd like to understand it better.XenOS wrote:there are qemu-system-i386 and qemu-system-x86_64, both of which should emulate the desired architecture, regardless of whether they run on i386 or x86_64 hardware.
Re: Running QEMU as Embedded Guest
That's definitely not true. You can get something quite similar to your host CPU if you use KVM and specify an explicit -cpu host.Combuster wrote:In addition QEMU doesn't actually emulate an i386. It emulates a copy of your computer's CPU.
By default, however, you don't use KVM and unless you specify something else you the the qemu32 or qemu64 CPU type, depending on whether you're running qemu-system-i386 or qemu-system-x86_64. In any case, what you get by this emulation is something that is close enough to some generic x86 CPU that guests work with it, but it's by far not 100% accurate with respect to enabling the right features for the selected CPU model: Even if you specify -cpu 486, your guest will probably support more instructions than any 486 ever did. The CPU setting mostly affects the CPUID result, and for some of the flags it's actually their presence that enables the corresponding functionality, but there are also cases where CPUID wouldn't advertise the feature any more, but it would still be working.
Anyway, it's rather rare that code relies on CPUs not supporting a given feature, so this shouldn't be a serious problem.