PCI Compat Layer
The QXL PCI device driver uses structures directly that are used both in the spice internals and in the network protocol. This is problematic because we can't change these structures without breaking ABI compatibility with qxl drivers. We want to change this by making the QXL API totally stand-alone and then have a layer that converts the QXL structures to whats used internally in spice.
This also lets us support multiple versions of QXL ABIs by having multiple implementations of this layer.
The current qxl_dev.h includes structures from the spice protocol definition, such as SpiceFill, SpiceBlend, etc. Everywhere this happens we want to make a copy of that struct for QXL use (i.e. SpiceBlend => QXLBlend) and put it in the qxl header. This way the ABI for the pci protocol is independent of the internal structures used in spice, allowing us to change these as needed.
In order for this to work we need to introduce a layer between the pci commands and the spice-server internal commands. This layer will copy the QXL commands into their spice counterpart, while at the same time validating the data (ensuring e.g. that all pointers are valid in the guest, etc).
There are multiple advantages to this:
- Validation is done in one place rather scattered all over the code, which is easier to get right and review
- We can have multiple copies of the layer, supporting different version of the QXL device
- We isolate the Spice representation of commands from the guest driver, allowing us (in cooperation with the new marshalling layer) to change these as we please
- We can make the QXL structures more suited for PCI commands, as they are currently somewhat optimized for network size rather than performance when used locally. For instance, we want to 32bit align all fields.
There is one risk in this. The extra copy introduces some overhead which may affect performance. However, I think this will be offset by some changes we can do like making the internal structs be non-packed and ensuring that validation only happens once, when the data is hot in cache.