VGA arbiter

Background

When multiple video cards are uncoordinatedly using the legacy VGA interface, one card might decode messages that were not sent to it. To solve this problem, it is needed an entity that controls all the accesses made using the legacy VGA interface. In Xorg this happens when multiple instances are running. It is important to note that some GPUs can skip completely if they are able to disable their VGA decoding resources (unfortunately this seems not so usual).

A good explanation of this problem is presented here: http://people.freedesktop.org/~dodji/arbitration-log.txt

Required Functionality

Devices that decode legacy VGA IO and/or MEM need to be identified. In addition, their IO/MEM enable/disable bits need to be toggled (along with the VGA forwarding enables on any bridges on the path to the devices). This is needed to prevent multiple devices from decoding legacy access. Drivers need to disable legacy decoding completely on their hardware, which most modern cards can do. The driver must be able to inform the arbiter of that fact to take out the card from the picture. This must be done carefully since bad things will happen if the card generates an interrupt when the arbiter has disabled MEM decoding on the card. The arbiter needs to either forbid cards to use interrupts if they are set to decode legacy space (and thus can be disabled at any time) or have a driver callback for disabling IRQ emission on a given card when it's being disabled by the arbiter. IO and MEM can't be treated separately since there is only one VGA forward bit on PCI-to-PCI bridges.

Project Status

The implementation provided is just a proof-of-concept, and it shows that the VGA Arbiter works. Now we need to decide the definitive interfaces and start writing the definitive code. There is an interesting blog post regarding the performance of this proof-of-concept.

The current implementation is split into 3 pieces.

Kernel Module

The VGA Arbiter, a Linux Kernel module, provides a device node that has to be used by applications that decode the legacy VGA interface. This can be easily ported to others platforms.

Currently, it is just a Kernel module because modules are way much easier to compile and test than built-in Kernel code. Ideally, this module will be integrated into the Kernel so that Kernel code will also be able to use the module without using its device node interface.

Also, the device node interface could also be changed to something else, to improve performance.

User Space Library

There is a little user space library that communicates with the arbiter using the device node interface. It was made so that the code inside the applications would be much easier to write. Also, when something on the device node interface changes, we wouldn't need to change all the applications, only the library (considering that its interface doesn't change).

X Server Code

There is a modified version of the X server that uses the VGA Arbiter instead of RAC when it can. The current implementation works exactly like the RAC implementation: it's a wrapper on the video drivers. Ideally, only the code that accesses the VGA Arbiter should be moved to inside the video drivers, because this would allow a much better performance. So, the video driver wrapper could be just removed.

Current Implementation

http://people.freedesktop.org/~vignatti/VGA.Notes

Source code

The current repository address is just temporary, so when it stops working, be sure to visit this page again to get the updated link.

Building and installing

Beyond these repositories above, to bring up an Xorg server with the VGA arbiter, we'll need to clone the input devices and the video driver repository from fd.o. After cloned all these repositories, the first step is building the kernel module. We'll need this environment variable set:

    export PKG_CONFIG_PATH=/opt/master/lib/pkgconfig

then,

    cd vga-module
    make

After we need to build the vgaaccess library:

    cd libvgaaccess
    ./autogen.sh --prefix=/opt/master
    make
    sudo make install

Now we can build the X server:

    cd xserver
    git-checkout -b server-1.4-branch origin/server-1.4-branch  # to checkout the server-1.4-branch where the arbiter implementation resides
    ./autogen.sh --prefix=/opt/master -disable-xnest -disable-kdrive -disable-xprint -disable-xvfb
    make
    sudo make install

So now it's time to run it all. Lets do it using two servers:

    cd vga-module
    insmod vgaarb.ko
    cd ..
    cd xserver
    ./hw/xfree86/Xorg -ac -fp /usr/share/fonts/X11/misc -noreset -sharevts -VGAarbiter vt7 :1 &
    ./hw/xfree86/Xorg -ac -fp /usr/share/fonts/X11/misc -noreset -sharevts -VGAarbiter vt7 :2 &

TODO

Kernel Module:

  • make it a built-in Kernel Code.
  • decide if the device node interface will be the definitive interface.
  • make other parts Kernel code that use the VGA Interface use the module functions
  • need to be DRI (interruptions) aware. X server code:

  • call the arbiter functions inside the video drivers, not using the current video driver wrapper (like in RAC). (this sentence means: start the X server code all over again, but now doing it the right way).

FAQ

Q: Why?

A: To start several instances of Xorg at same time using different graphical devices (e.g. to deploy a multiseat)

Q: Who is working here?

A: TiagoVignatti, PauloZanoni and Benjamin Herrenschmidt