X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FQemuServer.pm;h=794558bff2471a0e3dabbc4adf49f25618097695;hb=90b20b152c04577f0889540c54c448578cbc07f2;hp=14a17af0adb5013425aa0333dc8711a2bca5bdcf;hpb=483ceeabef9a631c2680301f5188e9e36943b36a;p=qemu-server.git diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 14a17af..794558b 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -64,6 +64,14 @@ eval { my $EDK2_FW_BASE = '/usr/share/pve-edk2-firmware/'; my $OVMF = { x86_64 => { + '4m-no-smm' => [ + "$EDK2_FW_BASE/OVMF_CODE_4M.fd", + "$EDK2_FW_BASE/OVMF_VARS_4M.fd", + ], + '4m-no-smm-ms' => [ + "$EDK2_FW_BASE/OVMF_CODE_4M.fd", + "$EDK2_FW_BASE/OVMF_VARS_4M.ms.fd", + ], '4m' => [ "$EDK2_FW_BASE/OVMF_CODE_4M.secboot.fd", "$EDK2_FW_BASE/OVMF_VARS_4M.fd", @@ -1844,7 +1852,6 @@ sub print_vga_device { my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf); my $vgaid = "vga" . ($id // ''); my $pciaddr; - if ($q35 && $vgaid eq 'vga') { # the first display uses pcie.0 bus on q35 machines $pciaddr = print_pcie_addr($vgaid, $bridges, $arch, $machine); @@ -2112,9 +2119,16 @@ sub verify_usb_device { sub json_config_properties { my $prop = shift; + my $skip_json_config_opts = { + parent => 1, + snaptime => 1, + vmstate => 1, + runningmachine => 1, + runningcpu => 1, + }; + foreach my $opt (keys %$confdesc) { - next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate' || - $opt eq 'runningmachine' || $opt eq 'runningcpu'; + next if $skip_json_config_opts->{$opt}; $prop->{$opt} = $confdesc->{$opt}; } @@ -3159,15 +3173,16 @@ sub get_vm_machine { return $machine; } -sub get_ovmf_files($$) { - my ($arch, $efidisk) = @_; +sub get_ovmf_files($$$) { + my ($arch, $efidisk, $smm) = @_; my $types = $OVMF->{$arch} or die "no OVMF images known for architecture '$arch'\n"; my $type = 'default'; if (defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') { - $type = $efidisk->{'pre-enrolled-keys'} ? "4m-ms" : "4m"; + $type = $smm ? "4m" : "4m-no-smm"; + $type .= '-ms' if $efidisk->{'pre-enrolled-keys'}; } return $types->{$type}->@*; @@ -3313,11 +3328,8 @@ sub config_to_command { $pbs_backing) = @_; my $cmd = []; - my $globalFlags = []; - my $machineFlags = []; - my $rtcFlags = []; + my ($globalFlags, $machineFlags, $rtcFlags) = ([], [], []); my $devices = []; - my $pciaddr = ''; my $bridges = {}; my $ostype = $conf->{ostype}; my $winversion = windows_version($ostype); @@ -3433,7 +3445,7 @@ sub config_to_command { $d = parse_drive('efidisk0', $efidisk); } - my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d); + my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d, $q35); die "uefi base image '$ovmf_code' not found\n" if ! -f $ovmf_code; my ($path, $format); @@ -3511,10 +3523,8 @@ sub config_to_command { } # enable absolute mouse coordinates (needed by vnc) - my $tablet; - if (defined($conf->{tablet})) { - $tablet = $conf->{tablet}; - } else { + my $tablet = $conf->{tablet}; + if (!defined($tablet)) { $tablet = $defaults->{tablet}; $tablet = 0 if $qxlnum; # disable for spice because it is not needed $tablet = 0 if $vga->{type} =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card) @@ -3542,23 +3552,22 @@ sub config_to_command { # serial devices for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) { - if (my $path = $conf->{"serial$i"}) { - if ($path eq 'socket') { - my $socket = "/var/run/qemu-server/${vmid}.serial$i"; - push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server=on,wait=off"; - # On aarch64, serial0 is the UART device. Qemu only allows - # connecting UART devices via the '-serial' command line, as - # the device has a fixed slot on the hardware... - if ($arch eq 'aarch64' && $i == 0) { - push @$devices, '-serial', "chardev:serial$i"; - } else { - push @$devices, '-device', "isa-serial,chardev=serial$i"; - } + my $path = $conf->{"serial$i"} or next; + if ($path eq 'socket') { + my $socket = "/var/run/qemu-server/${vmid}.serial$i"; + push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server=on,wait=off"; + # On aarch64, serial0 is the UART device. Qemu only allows + # connecting UART devices via the '-serial' command line, as + # the device has a fixed slot on the hardware... + if ($arch eq 'aarch64' && $i == 0) { + push @$devices, '-serial', "chardev:serial$i"; } else { - die "no such serial device\n" if ! -c $path; - push @$devices, '-chardev', "tty,id=serial$i,path=$path"; push @$devices, '-device', "isa-serial,chardev=serial$i"; } + } else { + die "no such serial device\n" if ! -c $path; + push @$devices, '-chardev', "tty,id=serial$i,path=$path"; + push @$devices, '-device', "isa-serial,chardev=serial$i"; } } @@ -3742,13 +3751,13 @@ sub config_to_command { # enable balloon by default, unless explicitly disabled if (!defined($conf->{balloon}) || $conf->{balloon}) { - $pciaddr = print_pci_addr("balloon0", $bridges, $arch, $machine_type); + my $pciaddr = print_pci_addr("balloon0", $bridges, $arch, $machine_type); push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr"; } if ($conf->{watchdog}) { my $wdopts = parse_watchdog($conf->{watchdog}); - $pciaddr = print_pci_addr("watchdog", $bridges, $arch, $machine_type); + my $pciaddr = print_pci_addr("watchdog", $bridges, $arch, $machine_type); my $watchdog = $wdopts->{model} || 'i6300esb'; push @$devices, '-device', "$watchdog$pciaddr"; push @$devices, '-watchdog-action', $wdopts->{action} if $wdopts->{action}; @@ -3792,7 +3801,7 @@ sub config_to_command { die "scsi$drive->{index}: machine version 4.1~pve2 or higher is required to use more than 14 SCSI disks\n" if $drive->{index} > 13 && !&$version_guard(4, 1, 2); - $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges, $arch, $machine_type); + my $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges, $arch, $machine_type); my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ? "virtio-scsi-pci" : $scsihw; my $iothread = ''; @@ -3815,7 +3824,7 @@ sub config_to_command { if ($drive->{interface} eq 'sata') { my $controller = int($drive->{index} / $PVE::QemuServer::Drive::MAX_SATA_DISKS); - $pciaddr = print_pci_addr("ahci$controller", $bridges, $arch, $machine_type); + my $pciaddr = print_pci_addr("ahci$controller", $bridges, $arch, $machine_type); push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller}; $ahcicontroller->{$controller}=1; @@ -3880,15 +3889,12 @@ sub config_to_command { # pci.4 is nested in pci.1 $bridges->{1} = 1 if $bridges->{4}; - if (!$q35) { - # add pci bridges - if (min_version($machine_version, 2, 3)) { + if (!$q35) { # add pci bridges + if (min_version($machine_version, 2, 3)) { $bridges->{1} = 1; $bridges->{2} = 1; } - $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/; - } for my $k (sort {$b cmp $a} keys %$bridges) { @@ -3898,11 +3904,10 @@ sub config_to_command { if ($k == 2 && $legacy_igd) { $k_name = "$k-igd"; } - $pciaddr = print_pci_addr("pci.$k_name", undef, $arch, $machine_type); - + my $pciaddr = print_pci_addr("pci.$k_name", undef, $arch, $machine_type); my $devstr = "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr"; - if ($q35) { - # add after -readconfig pve-q35.cfg + + if ($q35) { # add after -readconfig pve-q35.cfg splice @$devices, 2, 0, '-device', $devstr; } else { unshift @$devices, '-device', $devstr if $k > 0; @@ -4033,43 +4038,33 @@ sub vm_deviceplug { qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid, $arch, $machine_type); if ($deviceid eq 'tablet') { - qemu_deviceadd($vmid, print_tabletdevice_full($conf, $arch)); - } elsif ($deviceid eq 'keyboard') { - qemu_deviceadd($vmid, print_keyboarddevice_full($conf, $arch)); - } elsif ($deviceid =~ m/^usb(\d+)$/) { - die "usb hotplug currently not reliable\n"; # since we can't reliably hot unplug all added usb devices and usb # passthrough breaks live migration we disable usb hotplugging for now #qemu_deviceadd($vmid, PVE::QemuServer::USB::print_usbdevice_full($conf, $deviceid, $device)); - } elsif ($deviceid =~ m/^(virtio)(\d+)$/) { - qemu_iothread_add($vmid, $deviceid, $device); - qemu_driveadd($storecfg, $vmid, $device); - my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device, undef, $arch, $machine_type); + qemu_driveadd($storecfg, $vmid, $device); + my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device, undef, $arch, $machine_type); - qemu_deviceadd($vmid, $devicefull); + qemu_deviceadd($vmid, $devicefull); eval { qemu_deviceaddverify($vmid, $deviceid); }; if (my $err = $@) { eval { qemu_drivedel($vmid, $deviceid); }; warn $@ if $@; die $err; } - } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) { - - - my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi"; - my $pciaddr = print_pci_addr($deviceid, undef, $arch, $machine_type); + my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi"; + my $pciaddr = print_pci_addr($deviceid, undef, $arch, $machine_type); my $scsihw_type = $scsihw eq 'virtio-scsi-single' ? "virtio-scsi-pci" : $scsihw; - my $devicefull = "$scsihw_type,id=$deviceid$pciaddr"; + my $devicefull = "$scsihw_type,id=$deviceid$pciaddr"; if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread}) { qemu_iothread_add($vmid, $deviceid, $device); @@ -4080,11 +4075,9 @@ sub vm_deviceplug { $devicefull .= ",num_queues=$device->{queues}"; } - qemu_deviceadd($vmid, $devicefull); - qemu_deviceaddverify($vmid, $deviceid); - + qemu_deviceadd($vmid, $devicefull); + qemu_deviceaddverify($vmid, $deviceid); } elsif ($deviceid =~ m/^(scsi)(\d+)$/) { - qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device, $arch, $machine_type); qemu_driveadd($storecfg, $vmid, $device); @@ -4095,9 +4088,7 @@ sub vm_deviceplug { warn $@ if $@; die $err; } - } elsif ($deviceid =~ m/^(net)(\d+)$/) { - return if !qemu_netdevadd($vmid, $conf, $arch, $device, $deviceid); my $machine_type = PVE::QemuServer::Machine::qemu_machine_pxe($vmid, $conf); @@ -4116,16 +4107,13 @@ sub vm_deviceplug { warn $@ if $@; die $err; } - } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) { - my $bridgeid = $2; my $pciaddr = print_pci_addr($deviceid, undef, $arch, $machine_type); my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr"; qemu_deviceadd($vmid, $devicefull); qemu_deviceaddverify($vmid, $deviceid); - } else { die "can't hotplug device '$deviceid'\n"; } @@ -7553,7 +7541,8 @@ sub get_efivars_size { my ($conf) = @_; my $arch = get_vm_arch($conf); my $efidisk = $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef; - my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk); + my $smm = PVE::QemuServer::Machine::machine_type_is_q35($conf); + my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm); die "uefi vars image '$ovmf_vars' not found\n" if ! -f $ovmf_vars; return -s $ovmf_vars; } @@ -7578,10 +7567,10 @@ sub update_tpmstate_size { $conf->{tpmstate0} = print_drive($disk); } -sub create_efidisk($$$$$$) { - my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk) = @_; +sub create_efidisk($$$$$$$) { + my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk, $smm) = @_; - my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk); + my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm); die "EFI vars default image not found\n" if ! -f $ovmf_vars; my $vars_size_b = -s $ovmf_vars;