From 4543ecf07f311c8032ce0f7bf05e251ce0b49930 Mon Sep 17 00:00:00 2001 From: Alexandre Derumier Date: Mon, 23 Jun 2014 17:41:54 +0200 Subject: [PATCH] add pci multifunction support multifunction device should be define without the .function hostpci0: 00:00 example ------- if 00:00.0 00:00.1 00:00.2 exists, then we generate the multifunction devices -device (pci-assign|vfio-pci),host=00:00.0,id=hostpci0.0,bus=...,addr=0x0.0,multifunction=on -device (pci-assign|vfio-pci),host=00:00.1,id=hostpci0.1,bus=...,addr=0x0.1 -device (pci-assign|vfio-pci),host=00:00.2,id=hostpci0.2,bus=...,addr=0x0.2 Signed-off-by: Alexandre Derumier --- PVE/QemuServer.pm | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 597d013..3041dd5 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -22,7 +22,7 @@ use PVE::SafeSyslog; use Storable qw(dclone); use PVE::Exception qw(raise raise_param_exc); use PVE::Storage; -use PVE::Tools qw(run_command lock_file lock_file_full file_read_firstline); +use PVE::Tools qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach); use PVE::JSONSchema qw(get_standard_option); use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file); use PVE::INotify; @@ -1267,9 +1267,15 @@ sub parse_hostpci { my $res = {}; foreach my $kv (@list) { - if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9])$/) { + if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) { $found = 1; - $res->{pciid} = $2; + if(defined($4)){ + push @{$res->{pciid}}, { id => $2 , function => $4}; + + }else{ + my $pcidevices = lspci($2); + $res->{pciid} = $pcidevices->{$2}; + } } elsif ($kv =~ m/^driver=(kvm|vfio)$/) { $res->{driver} = $1; } elsif ($kv =~ m/^rombar=(on|off)$/) { @@ -2430,9 +2436,26 @@ sub config_to_command { my $driver = $d->{driver} && $d->{driver} eq 'vfio' ? "vfio-pci" : "pci-assign"; my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ? ",x-vga=on" : ""; $driver = "vfio-pci" if $xvga ne ''; + my $pcidevices = $d->{pciid}; + my $multifunction = 1 if @$pcidevices > 1; - push @$devices, '-device', "$driver,host=$d->{pciid},id=hostpci$i$pciaddr$rombar$xvga"; + my $j=0; + foreach my $pcidevice (@$pcidevices) { + my $id = "hostpci$i"; + $id .= ".$j" if $multifunction; + my $addr = $pciaddr; + $addr .= ".$j" if $multifunction; + my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr"; + + if($j == 0){ + $devicestr .= "$rombar$xvga"; + $devicestr .= ",multifunction=on" if $multifunction; + } + + push @$devices, '-device', $devicestr; + $j++; + } } # usb devices @@ -5167,4 +5190,17 @@ sub get_current_qemu_machine { return $current || $default || 'pc'; } +sub lspci { + + my $devices = {}; + + dir_glob_foreach("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub { + my (undef, $id, $function) = @_; + my $res = { id => $id, function => $function}; + push @{$devices->{$id}}, $res; + }); + + return $devices; +} + 1; -- 2.39.2