How to Add a New Device in Qemu Source Code

How to add new QEMU machine types without modifying the mainline source code?

without having to recompile qemu or write code?

No. There must be some code doing the device specific emulation, like for example the way the Raspberry Pi or the Pandaboard implement video output. This is not a matter of just a few config files.

How do I make my device available to QEMU

The documentation is unclear or missing on how this ought to be done, but I did find a solution that worked in the interim.

In the directory where the source file is stored (here, qemu/hw/misc/), there is a file called Makefile.objs with a list of object file targets to create. Adding the following line will induce the main Makefile (in the QEMU root directory) to create a target whenever the configuration flag CONFIG_HELLO is defined:

common-obj-$(CONFIG_HELLO) += hello-world-device.o

To define this custom flag, an entry can be added to the target architecture of choice. Here, I add it to my configuration for x86_64 in qemu/default-configs/x86_64-softmmu.mak:

CONFIG_HELLO=y

After making the above changes, running make creates a rule to build the custom device, and runs it at the appropriate time when building the architecture. This revealed an includes bug in the existing code, repeated here with the corrections for convenience:

#include "qemu/osdeps.h"
#include "hw/hw.h"
#define TYPE_HELLO "hello-world-device"
#define HELLO(obj) OBJECT_CHECK(HelloState, (obj), TYPE_HELLO)

typedef struct{
DeviceClass parent_obj;
uint8_t member0, member1;
} HelloState;

static const TypeInfo hello_info = {
.name = TYPE_HELLO,
.parent = TYPE_DEVICE,
.instance_size = sizeof(HelloState),
.class_init = class_init,
};

static void class_init(ObjectClass *klass, void *data){
DeviceClass *dc = DEVICE_CLASS(klass);
}

static void hello_register_types(void){
type_register_static(&hello_info);
}

type_init(hello_register_types)

How to create a new system or board to be emulated by QEMU

There is no documentation for how to write new machine models for QEMU. The best advice is to look at the source code for an existing machine type that seems similar to the one you want to add. Avoid looking at machine types that have been added to QEMU a long time ago -- they are often written in an older style or using older APIs which are no longer recommended for new code.

As a very rough rule of thumb, you should assume that a new machine model is about as much effort as porting an operating system to that new hardware. (Roughly, a device model is about as much code as a device driver.) Depending on how much functionality you need, you may be able to leave some or many devices in your SoC unimplemented -- the absolute minimum is usually something like a UART and a timer. You'll need documentation of the SoC (technical reference manual or similar, with detailed descriptions of the devices down to the register level).

(Out of curiosity, what is the M33-based SoC?)

Adding a new instruction to QEMU

The fact that you mention a "CHERI_HELPER_IMPL" macro tells me that you're not working with upstream QEMU, but with the CHERI project's fork of it. So you should talk to them about anything special that might be needed there. As I understand it their local modifications may be quite significant.

For upstream QEMU, this depends on whether the target architecture is using decodetree or not.

For decodetree-based architectures:

  • add a suitable instruction pattern or patterns to the .decode file. This will result in the generation of code which calls a function whose name begins trans_ to handle instructions that match that pattern, passing it a pointer to a structure which contains the values of the various instruction fields defined by your pattern.
  • implement the trans_ functions appropriately. What you need to do depends on what the instruction behaviour is. For simple instructions, you can just emit TCG ops which do the actions the instruction must do. For more complicated work, you might want to emit TCG ops for "call a runtime helper function". The tcg/README file has some "recommended coding rules" at the bottom which include a rule of thumb for when to use a helper function.
  • if you decided to emit a helper call, you need to implement the helper function. The DEF_HELPER_* macros in helper.h both define the prototype for the C function you're going to write and also auto-generate a function gen_helper_whatever that your translate-time code can call to generate the TCG code to call it.

For non-decodetree-based architectures:

  • There will be hand-written code, usually starting in translate.c, which identifies instructions using switch statements and bit-masking code. You'll need to look at that code to find out where in that to add the code which identifies the instruction that you're adding. This is all completely target-specific; some targets use a somewhat table-driven setup or some preprocessor macros as part of this, some use completely hand-written code.
  • Once you've figured out where to add the "is this my instruction type?" check, the rest is similar to decodetree-based targets: you need to emit TCG ops to either do the work or to call a helper to do the work at runtime.

You'll find that there's a lot of specific detail that needs to be got right in each of these steps, but that's the basic outline.

What I need to read/analyze in order to understand how QEMU emulates supported network devices?

For basic introduction to qemu and its networking functionalities:

  • What's a good source to learn about QEMU?

To get started with source code

  • original qemu paper
  • qemu-internals
  • http://www.ecs.syr.edu/faculty/yin/Teaching/TC2010/Proj4.pdf
  • https://wiki.aalto.fi/download/attachments/41747647/qemu.pdf


Related Topics



Leave a reply



Submit