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",
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);
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};
}
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}->@*;
$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);
$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);
}
# 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)
# 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";
}
}
# 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};
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 = '';
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;
# 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) {
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;
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);
$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);
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);
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";
}
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;
}
$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;