On Thu, May 03, 2018 at 07:50:41PM +0100, Dr. David Alan Gilbert wrote: > * Stefan Hajnoczi (stefanha@redhat.com) wrote: > > On Thu, May 03, 2018 at 04:16:41PM +0200, Cédric Le Goater wrote: > > > Coming back to the initial motivation that Peter pointed out, would > > > the goal to be able to run vcpus of different architectures ? It would > > > certainly be interesting to model a platform, specially if we can > > > synchronize the execution in some ways and find timing issues. > > > > Yes, there is demand for heterogenous guests. People have worked on > > this problem in the past but nothing mergeable came out of it. > > > > The main issue with a monolithic binary is that today, QEMU builds > > target-specific object files (see Makefile.target). That means the same > > C source file is recompiled for each target with different #defines. We > > cannot easily link these "duplicate" object files into a single binary > > because the symbol names would collide. > > > > It would be necessary to refactor target-specific #ifdefs. Here is a > > trivial example from arch_init.c: > > > > #ifdef TARGET_SPARC > > int graphic_width = 1024; > > int graphic_height = 768; > > int graphic_depth = 8; > > #else > > int graphic_width = 800; > > int graphic_height = 600; > > int graphic_depth = 32; > > #endif > > > > This can be converted into a runtime check: > > > > static void init_graphic_resolution(void) > > { > > if (arch_type == QEMU_ARCH_SPARC) { > > graphic_width = 1024; > > graphic_height = 768; > > graphic_depth = 8; > > } else { > > graphic_width = 800; > > graphic_height = 600; > > graphic_depth = 32; > > } > > } > > target_init(init_graphic_resolution) > > > > I'm assuming target_init() registers functions that will be called once > > arch_type has been set. > > > > Of course the meaning of arch_type in a heterogenous system is different > > since there can be multiple CPUs. It would mean the overall board (e.g. > > a SPARC machine). But that is a separate issue and can only be > > addressed once target-specific files have been eliminated. > > > > I also want to point out that a monolithic binary is totally orthogonal > > to modularity (reducing attack surface, reducing dependencies). These > > two issues do not conflict with each other. We could have a single > > "qemu-softmmu" binary that dynamically loads needed machine types, CPU, > > and emulated devices. That way the monolithic binary can do everything > > but is still minimal. > > > > So to clarify, three separate steps: > > > > 1. Get rid of target-specific #ifdefs > > 2a. Modular QEMU, single binary > > 2b. Heterogenous QEMU > > > > 2a and 2b are independent but both depend on 1. > > (1) may not be required, if those ifdef's are in target-specific > builds; but that does require that any target-specific stuff goes > through a well defined interface to be a loadable module and not > have a zillion overlapping symbols. Right, there are many cases that I omitted and the arch_init.c example was the simplest case. Each instance needs to be handled on a case-by-case basis. We may need to keep multiple copies of object code. Byteswapping is an example of this: #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) #define BSWAP_NEEDED #endif Adding runtime endianness checks to all guest memory accesses could impact performance. This is why everything that includes cpu.h is currently per-target. This work is no small task but I think it's necessary. The starting point for anyone who'd like to contribute: Look at obj-y files in the makefiles. These are the target-specific object files that need to be investigated. Everything already in common-obj-y is only built once and can be ignored. Stefan