summaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/openslx/libvirt/domain/DomainUtils.java78
1 files changed, 77 insertions, 1 deletions
diff --git a/src/main/java/org/openslx/libvirt/domain/DomainUtils.java b/src/main/java/org/openslx/libvirt/domain/DomainUtils.java
index 2462371..34dcdd6 100644
--- a/src/main/java/org/openslx/libvirt/domain/DomainUtils.java
+++ b/src/main/java/org/openslx/libvirt/domain/DomainUtils.java
@@ -2,9 +2,11 @@ package org.openslx.libvirt.domain;
import java.math.BigInteger;
+import org.openslx.libvirt.domain.device.HostdevPciDeviceAddress;
+
/**
* Collection of helper functions to maintain a Libvirt domain XML document.
- *
+ *
* @author Manuel Bentele
* @version 1.0
*/
@@ -115,4 +117,78 @@ public final class DomainUtils
return value.divide( dividend ).toString();
}
+
+ /**
+ * Builds a PCI slot usage map from all devices in the given domain configuration.
+ * <p>
+ * The returned array tracks which PCI device slots are in use on the primary bus
+ * (domain 0, bus 0). Array indices correspond to device numbers (0-63), with:
+ * </p>
+ * <ul>
+ * <li>{@code 0} = slot is free</li>
+ * <li>{@code >0} = slot is occupied (value encodes domain:bus:device lookup)</li>
+ * </ul>
+ * <p>
+ * Slots 0 and 1 are pre-marked as reserved.
+ * </p>
+ *
+ * @param config domain configuration to scan for existing PCI devices
+ * @return array of size 64 tracking PCI slot usage
+ */
+ public static int[] buildPciSlotUsageMap( Domain config )
+ {
+ int[] inUse = new int[ 64 ];
+ inUse[ 0 ] = Integer.MAX_VALUE;
+ inUse[ 1 ] = Integer.MAX_VALUE;
+
+ for ( org.openslx.libvirt.domain.device.Device dev : config.getDevices() ) {
+ HostdevPciDeviceAddress target = dev.getPciTarget();
+ if ( target == null )
+ continue;
+ if ( target.getPciDomain() != 0 || target.getPciBus() != 0 )
+ continue; // Ignore non-primary bus
+ if ( target.getPciDevice() >= inUse.length )
+ continue;
+ inUse[ target.getPciDevice() ] = Integer.MAX_VALUE;
+ }
+
+ return inUse;
+ }
+
+ /**
+ * Finds a free PCI device slot on the primary bus (domain 0, bus 0) that doesn't
+ * collide with existing device addresses.
+ * <p>
+ * The method first checks if the exact same PCI address was already assigned
+ * (for reuse), otherwise returns the first free slot starting from device 2.
+ * </p>
+ *
+ * @param inUse PCI slot usage map from {@link #buildPciSlotUsageMap(Domain)}
+ * @param pciDeviceAddress original PCI device address to find a slot for
+ * @return free PCI device number (0-63) for assignment
+ * @throws IllegalStateException if no free PCI slot is available
+ */
+ public static int findFreePciDeviceSlot( int[] inUse, HostdevPciDeviceAddress pciDeviceAddress )
+ {
+ int devAddr;
+ int firstFree = -1;
+ int lookup = ( pciDeviceAddress.getPciDomain() << 16 )
+ | ( pciDeviceAddress.getPciBus() << 8 )
+ | ( pciDeviceAddress.getPciDevice() );
+
+ for ( devAddr = 0; devAddr < inUse.length; ++devAddr ) {
+ if ( firstFree == -1 && inUse[ devAddr ] == 0 ) {
+ firstFree = devAddr;
+ } else if ( inUse[ devAddr ] == lookup ) {
+ return devAddr;
+ }
+ }
+
+ if ( firstFree == -1 ) {
+ throw new IllegalStateException( "No free PCI device slot available" );
+ }
+
+ inUse[ firstFree ] = lookup;
+ return firstFree;
+ }
}