Features/Modules

From QEMU
Revision as of 16:12, 30 June 2013 by Mjt (talk | contribs) (→‎Summary)

Summary

Introduce a mechanism to support loadable modules in QEMU similar to the Linux kernel. It should integrate into the existing build system. Currently, we allow features to be specified in for inclusion in a boolean fashion (either 'y' or 'n' to include or exclude). This proposal would add a third state to allow building as a loadable module ('m').

The most obvious reason why we may want such a feature is to allow downstreams to package different parts of qemu in separate binary packages, reducing runtime dependencies of the main package. For example, on a headless server there's no need to install sdl or gtk display types which require all the client-side X stack and all surrounding support packages.

This system should not be (ab)used to allow 3rd-party modules to be loaded into qemu, especially to "work around" GPL restrictions. For this to work, the plugins system should ensure that only plugins built together with qemu works, by adding, for example, hashes of current build to the main exported symbols.

Owner

What this is not

  • A mechanism to support third party extensions to QEMU or out of tree drivers/features
  • A stable interface
  • A GPL barrier

Usage

The build system already allows features to be specified by setting appropriate flags in <target-subdir>/config-devices.mak. Initially, configuring modules would involve setting build options to 'm' instead of 'y' as below:

   # Default configuration for x86_64-softmmu
   
   CONFIG_VGA=y
   # Build QXL as a loadable module
   CONFIG_QXL=m
   CONFIG_VGA_PCI=y
   CONFIG_VGA_ISA=y
   CONFIG_VGA_CIRRUS=y
   # Build VMware devices as loadable modules
   CONFIG_VMWARE_VGA=m
   CONFIG_VMMOUSE=m
   CONFIG_SERIAL=y
   ...

The build system will install all generated modules in ${prefix}/lib/qemu/libqemu-<modulename>.so. When built as a module, the module_init() function will be defined as a public function with a fixed name instead of a static function marked as a constructor.

Loading Modules

All modules in ${prefix}/lib/qemu will be scanned at early startup and loaded. When loaded, the public function will be invoked to register the module init functions. Note that this must happens before any module init functions are invoked. Also not that QEMU must *not* dlclose the library, since that would unload it!

In the long term, we should also support a QMP/HMP command to load a module after startup. We will need to consider how module init ordering should work here. Any easy solution would be to force all modules to use type_init() and call all new MODULE_TYPE init functions any time we load a module.

Unloading Modules

While not strictly needed at first, we should consider implementing module unloading in the long run.

Rough implementation idea

Only devices that are compiled once can be modularized.

For a single-file module:

  module-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o

For a multi-file module (actually, one could use two single-file modules for this particular example):

  modules-$(CONFIG_XIO3130) += xio3130.so
  common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o
  $(obj)/xio3130.so: $(obj)/xio3130_upstream.o $(obj)/xio3130_downstream.o

In Makefile.target:

  common-obj-y += $(module-obj-y)

In Makefile:

  # Add single-file modules to modules-m
  modules-m += $(patsubst %.o,%.so,$(module-obj-m))

  # Build modules
  all: $(modules-m)

  # Auto-create dependencies for single-file modules
  $(foreach M, $(module-obj-m), $(eval $(M:.o=.so): $M))

  # Rule for building modules
  $(modules-m): %.so:
         libtool --mode=link ...

  ifneq ($(obj-m),)
  $(error obj-m must be empty!)
  endif

Note that modules-y and common-obj-m are ignored.

Individual libs from libs_softmmu have to be split into their own variables, then:

  $(obj)/pulseaudio.so: LDFLAGS += $(LIBS_PULSEAUDIO)
  libs-$(CONFIG_PULSEAUDIO) += $(LIBS_PULSEAUDIO)

where again, libs-m is ignored.

Status

No code exists for this feature yet.