summaryrefslogtreecommitdiffstats
path: root/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuMdevPassthroughIntel.java
blob: 0a0da1a40986ee8a31fc81ca5a71a45e6935ec4f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package org.openslx.runvirt.plugin.qemu.configuration;

import org.openslx.libvirt.capabilities.Capabilities;
import org.openslx.libvirt.domain.Domain;
import org.openslx.libvirt.domain.device.Hostdev;
import org.openslx.libvirt.domain.device.HostdevMdev;
import org.openslx.libvirt.domain.device.HostdevMdev.Model;
import org.openslx.libvirt.domain.device.HostdevMdevDeviceAddress;
import org.openslx.libvirt.domain.device.Video;
import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
import org.openslx.runvirt.virtualization.LibvirtHypervisorException;
import org.openslx.virtualization.configuration.transformation.TransformationException;
import org.openslx.virtualization.configuration.transformation.TransformationSpecific;

/**
 * Specific Intel mediated device (Intel GVT-g) passthrough transformation for Libvirt/QEMU
 * virtualization configurations.
 * 
 * @author Manuel Bentele
 * @version 1.0
 */
public class TransformationSpecificQemuMdevPassthroughIntel
		extends TransformationSpecific<Domain, CommandLineArgs, LibvirtHypervisorQemu>
{
	/**
	 * Name of the configuration transformation.
	 */
	private static final String NAME = "QEMU mediated device passthrough [Intel]";

	/**
	 * Creates a new Intel mediated device passthrough transformation for Libvirt/QEMU virtualization
	 * configurations.
	 * 
	 * @param hypervisor Libvirt/QEMU hypervisor.
	 */
	public TransformationSpecificQemuMdevPassthroughIntel( LibvirtHypervisorQemu hypervisor )
	{
		super( TransformationSpecificQemuMdevPassthroughIntel.NAME, hypervisor );
	}

	/**
	 * Validates a virtualization configuration and input arguments for this transformation.
	 * 
	 * @param config virtualization configuration for the validation.
	 * @param args input arguments for the validation.
	 * @throws TransformationException validation has failed.
	 */
	private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
	{
		if ( config == null || args == null ) {
			throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
		}
	}

	/**
	 * Queries and returns the capabilities of the Libvirt/QEMU hypervisor.
	 * 
	 * @return capabilities of the Libvirt/QEMU hypervisor.
	 * @throws TransformationException failed to query and return the capabilities of the
	 *            Libvirt/QEMU hypervisor.
	 */
	protected Capabilities getCapabilities() throws TransformationException
	{
		Capabilities capabilities = null;

		try {
			capabilities = this.getVirtualizer().getCapabilites();
		} catch ( LibvirtHypervisorException e ) {
			final String errorMsg = new String(
					"Failed to retrieve host capabilities from QEMU virtualizer: " + e.getLocalizedMessage() );
			throw new TransformationException( errorMsg );
		}

		return capabilities;
	}

	@Override
	public void transform( Domain config, CommandLineArgs args ) throws TransformationException
	{
		// validate configuration and input arguments
		this.validateInputs( config, args );

		// check if passthrough of an Intel mediated device (virtual GPU) takes place
		if ( args.isIntelMdevPassthroughEnabled() ) {
			// validate submitted mediated device UUID
			final HostdevMdevDeviceAddress mdevDeviceAddress = HostdevMdevDeviceAddress.valueOf( args.getVmIlMdevId0() );
			if ( mdevDeviceAddress == null ) {
				final String errorMsg = "UUID of the Intel mediated device (virtual GPU) address is invalid!";
				throw new TransformationException( errorMsg );
			}

			// check if IOMMU support is available on the host
			if ( !this.getCapabilities().hasHostIommuSupport() ) {
				final String errorMsg = "IOMMU support is not available on the hypervisor but required for Intel mediated device (virtual GPU) passthrough!";
				throw new TransformationException( errorMsg );
			}

			// remove all existing hostdev devices
			// otherwise the Intel specific QEMU options with index 0 do not work
			for ( final Hostdev hostdevDevice : config.getHostdevDevices() ) {
				hostdevDevice.remove();
			}

			// passthrough Intel mediated device (virtual GPU)
			final HostdevMdev mdevDevice = config.addHostdevMdevDevice();
			mdevDevice.setManaged( false );
			mdevDevice.setModel( Model.VFIO_PCI );
			mdevDevice.setDisplayOn( true );
			mdevDevice.setMemoryFramebufferOn( true );
			mdevDevice.setSource( mdevDeviceAddress );

			// set Intel specific QEMU options that are not handeled by Libvirt yet
			config.addQemuCmdlnArgument( "-set" );
			config.addQemuCmdlnArgument( "device.hostdev0.x-igd-opregion=on" );
			config.addQemuCmdlnArgument( "-set" );
			config.addQemuCmdlnArgument( "device.hostdev0.driver=vfio-pci-nohotplug" );

			// disable all software video devices by disable them
			for ( Video videoDevice : config.getVideoDevices() ) {
				videoDevice.disable();
			}
		}
	}
}