use PVE::QMPClient;
use PVE::QemuConfig;
-use PVE::QemuServer::Helpers;
+use PVE::QemuServer::Helpers qw(min_version);
use PVE::QemuServer::Cloudinit;
+use PVE::QemuServer::Machine;
use PVE::QemuServer::Memory;
use PVE::QemuServer::Monitor qw(mon_cmd);
use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port);
],
};
-my $qemu_snap_storage = { rbd => 1 };
-
my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
my $QEMU_FORMAT_RE = qr/raw|cow|qcow|qcow2|qed|vmdk|cloop/;
PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
description => "Specifies the Qemu machine type.",
type => 'string',
- pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\.pxe)?|virt(?:-\d+(\.\d+)+)?)',
+ pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|virt(?:-\d+(\.\d+)+)?(\+pve\d+)?)',
maxLength => 40,
optional => 1,
});
description => "Configure additional enhancements for SPICE.",
optional => 1
},
+ tags => {
+ type => 'string', format => 'pve-tag-list',
+ description => 'Tags of the VM. This is only meta information.',
+ optional => 1,
+ },
};
my $cicustom_fmt = {
};
PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc);
-my $PCIRE = qr/[a-f0-9]{2}:[a-f0-9]{2}(?:\.[a-f0-9])?/;
+my $PCIRE = qr/([a-f0-9]{4}:)?[a-f0-9]{2}:[a-f0-9]{2}(?:\.[a-f0-9])?/;
my $hostpci_fmt = {
host => {
default_key => 1,
return $res;
}
-sub machine_type_is_q35 {
- my ($conf) = @_;
-
- return $conf->{machine} && ($conf->{machine} =~ m/q35/) ? 1 : 0;
-}
-
sub print_tabletdevice_full {
my ($conf, $arch) = @_;
- my $q35 = machine_type_is_q35($conf);
+ my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
# we use uhci for old VMs because tablet driver was buggy in older qemu
my $usbbus;
- if (machine_type_is_q35($conf) || $arch eq 'aarch64') {
+ if (PVE::QemuServer::Machine::machine_type_is_q35($conf) || $arch eq 'aarch64') {
$usbbus = 'ehci';
} else {
$usbbus = 'uhci';
}
# for compatibility only, we prefer scsi-hd (#2408, #2355, #2380)
+ my $version = PVE::QemuServer::Machine::extract_version($machine_type, kvm_user_version());
if ($path =~ m/^iscsi\:\/\// &&
- !qemu_machine_feature_enabled($machine_type, undef, 4, 1)) {
+ !min_version($version, 4, 1)) {
$devicetype = 'generic';
}
}
};
sub print_vga_device {
- my ($conf, $vga, $arch, $kvmver, $machine, $id, $qxlnum, $bridges) = @_;
+ my ($conf, $vga, $arch, $machine_version, $machine, $id, $qxlnum, $bridges) = @_;
my $type = $vga_map->{$vga->{type}};
if ($arch eq 'aarch64' && defined($type) && $type eq 'virtio-vga') {
if (!$conf->{ostype} || $conf->{ostype} =~ m/^(?:l\d\d)|(?:other)$/) {
# set max outputs so linux can have up to 4 qxl displays with one device
- if (qemu_machine_feature_enabled($machine, $kvmver, 4, 1)) {
+ if (min_version($machine_version, 4, 1)) {
$max_outputs = ",max_outputs=4";
}
}
$memory = ",ram_size=67108864,vram_size=33554432";
}
- my $q35 = machine_type_is_q35($conf);
+ my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
my $vgaid = "vga" . ($id // '');
my $pciaddr;
my @idlist = split(/;/, $res->{host});
delete $res->{host};
foreach my $id (@idlist) {
- if ($id =~ m/\./) { # full id 00:00.1
- push @{$res->{pciid}}, {
- id => $id,
- };
- } else { # partial id 00:00
- $res->{pciid} = PVE::SysFSTools::lspci($id);
+ my $devs = PVE::SysFSTools::lspci($id);
+ if (!scalar(@$devs)) {
+ die "no pci device found for '$id'\n";
}
+ push @{$res->{pciid}}, @$devs;
}
return $res;
}
&$cleanup_config($conf->{pending}, 1);
foreach my $snapname (keys %{$conf->{snapshots}}) {
- die "internal error" if $snapname eq 'pending';
+ die "internal error: snapshot name '$snapname' is forbidden" if lc($snapname) eq 'pending';
&$cleanup_config($conf->{snapshots}->{$snapname}, undef, $snapname);
}
description => "The current config lock, if any.",
type => 'string',
optional => 1,
- }
+ },
+ tags => {
+ description => "The current configured tags, if any",
+ type => 'string',
+ optional => 1,
+ },
};
my $last_proc_pid_stat;
$d->{serial} = 1 if conf_has_serial($conf);
$d->{lock} = $conf->{lock} if $conf->{lock};
+ $d->{tags} = $conf->{tags} if defined($conf->{tags});
$res->{$vmid} = $d;
}
return get_host_arch() eq $arch;
}
+sub get_vm_arch {
+ my ($conf) = @_;
+ return $conf->{arch} // get_host_arch();
+}
+
my $default_machines = {
x86_64 => 'pc',
aarch64 => 'virt',
};
-sub get_basic_machine_info {
- my ($conf, $forcemachine) = @_;
+sub get_vm_machine {
+ my ($conf, $forcemachine, $arch, $add_pve_version) = @_;
- my $arch = $conf->{arch} // get_host_arch();
- my $machine = $forcemachine || $conf->{machine} || $default_machines->{$arch};
- return ($arch, $machine);
+ my $machine = $forcemachine || $conf->{machine};
+
+ if (!$machine || $machine =~ m/^(?:pc|q35|virt)$/) {
+ $arch //= 'x86_64';
+ $machine ||= $default_machines->{$arch};
+ $machine .= "+pve$PVE::QemuServer::Machine::PVE_MACHINE_VERSION" if $add_pve_version;
+ }
+
+ return $machine;
}
sub get_ovmf_files($) {
}
sub get_cpu_options {
- my ($conf, $arch, $kvm, $machine_type, $kvm_off, $kvmver, $winversion, $gpu_passthrough) = @_;
+ my ($conf, $arch, $kvm, $kvm_off, $machine_version, $winversion, $gpu_passthrough) = @_;
my $cpuFlags = [];
my $ostype = $conf->{ostype};
push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
- if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3) && $arch eq 'x86_64') {
+ if (min_version($machine_version, 2, 3) && $arch eq 'x86_64') {
push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
}
- add_hyperv_enlightenments($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios}, $gpu_passthrough, $hv_vendor_id) if $kvm;
+ add_hyperv_enlightenments($cpuFlags, $winversion, $machine_version, $conf->{bios}, $gpu_passthrough, $hv_vendor_id) if $kvm;
push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm && $arch eq 'x86_64';
my $winversion = windows_version($ostype);
my $kvm = $conf->{kvm};
- my ($arch, $machine_type) = get_basic_machine_info($conf, $forcemachine);
+ my $arch = get_vm_arch($conf);
my $kvm_binary = get_command_for_arch($arch);
my $kvmver = kvm_user_version($kvm_binary);
+
+ my $add_pve_version = min_version($kvmver, 4, 1);
+
+ my $machine_type = get_vm_machine($conf, $forcemachine, $arch, $add_pve_version);
+ my $machine_version = PVE::QemuServer::Machine::extract_version($machine_type, $kvmver);
$kvm //= 1 if is_native($arch);
if ($kvm) {
die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
- my $q35 = machine_type_is_q35($conf);
+ my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
my $use_old_bios_files = undef;
($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
push @$cmd, '-mon', "chardev=qmp,mode=control";
- if (qemu_machine_feature_enabled($machine_type, $kvmver, 2, 12)) {
+ if (min_version($machine_version, 2, 12)) {
push @$cmd, '-chardev', "socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect=5";
push @$cmd, '-mon', "chardev=qmp-event,mode=control";
}
# load q35 config
if ($q35) {
# we use different pcie-port hardware for qemu >= 4.0 for passthrough
- if (qemu_machine_feature_enabled($machine_type, $kvmver, 4, 0)) {
+ if (min_version($machine_version, 4, 0)) {
push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35-4.0.cfg';
} else {
push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
if (!$vga->{type}) {
if ($arch eq 'aarch64') {
$vga->{type} = 'virtio';
- } elsif (qemu_machine_feature_enabled($machine_type, $kvmver, 2, 9)) {
+ } elsif (min_version($machine_version, 2, 9)) {
$vga->{type} = (!$winversion || $winversion >= 6) ? 'std' : 'cirrus';
} else {
$vga->{type} = ($winversion >= 6) ? 'std' : 'cirrus';
if ($d->{mdev} && scalar(@$pcidevices) == 1) {
my $pci_id = $pcidevices->[0]->{id};
my $uuid = PVE::SysFSTools::generate_mdev_uuid($vmid, $i);
- $sysfspath = "/sys/bus/pci/devices/0000:$pci_id/$uuid";
+ $sysfspath = "/sys/bus/pci/devices/$pci_id/$uuid";
} elsif ($d->{mdev}) {
warn "ignoring mediated device '$id' with multifunction device\n";
}
# usb devices
my $usb_dev_features = {};
- $usb_dev_features->{spice_usb3} = 1 if qemu_machine_feature_enabled($machine_type, $kvmver, 4, 0);
+ $usb_dev_features->{spice_usb3} = 1 if min_version($machine_version, 4, 0);
my @usbdevices = PVE::QemuServer::USB::get_usb_devices($conf, $usbdesc->{format}, $MAX_USB_DEVICES, $usb_dev_features);
push @$devices, @usbdevices if @usbdevices;
die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
if ($allowed_vcpus < $maxcpus);
- if($hotplug_features->{cpu} && qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 7)) {
+ if($hotplug_features->{cpu} && min_version($machine_version, 2, 7)) {
push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
for (my $i = 2; $i <= $vcpus; $i++) {
push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
if ($vga->{type} && $vga->{type} !~ m/^serial\d+$/ && $vga->{type} ne 'none'){
- push @$devices, '-device', print_vga_device($conf, $vga, $arch, $kvmver, $machine_type, undef, $qxlnum, $bridges);
+ push @$devices, '-device', print_vga_device($conf, $vga, $arch, $machine_version, $machine_type, undef, $qxlnum, $bridges);
my $socket = PVE::QemuServer::Helpers::vnc_socket($vmid);
push @$cmd, '-vnc', "unix:$socket,password";
} else {
push @$rtcFlags, 'base=localtime';
}
- push @$cmd, get_cpu_options($conf, $arch, $kvm, $machine_type, $kvm_off, $kvmver, $winversion, $gpu_passthrough);
+ push @$cmd, get_cpu_options($conf, $arch, $kvm, $kvm_off, $machine_version, $winversion, $gpu_passthrough);
PVE::QemuServer::Memory::config($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
if ($qxlnum > 1) {
if ($winversion){
for(my $i = 1; $i < $qxlnum; $i++){
- push @$devices, '-device', print_vga_device($conf, $vga, $arch, $kvmver, $machine_type, $i, $qxlnum, $bridges);
+ push @$devices, '-device', print_vga_device($conf, $vga, $arch, $machine_version, $machine_type, $i, $qxlnum, $bridges);
}
} else {
# assume other OS works like Linux
if (!$q35) {
# add pci bridges
- if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
+ if (min_version($machine_version, 2, 3)) {
$bridges->{1} = 1;
$bridges->{2} = 1;
}
my $statepath = PVE::Storage::path($storecfg, $vmstate);
push @$vollist, $vmstate;
push @$cmd, '-loadstate', $statepath;
+ print "activating and using '$vmstate' as vmstate\n";
}
# add custom args
sub vm_deviceplug {
my ($storecfg, $conf, $vmid, $deviceid, $device, $arch, $machine_type) = @_;
- my $q35 = machine_type_is_q35($conf);
+ my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
my $devices_list = vm_devices_list($vmid);
return 1 if defined($devices_list->{$deviceid});
return undef if !qemu_netdevadd($vmid, $conf, $arch, $device, $deviceid);
- my $machine_type = PVE::QemuServer::qemu_machine_pxe($vmid, $conf);
+ my $machine_type = PVE::QemuServer::Machine::qemu_machine_pxe($vmid, $conf);
my $use_old_bios_files = undef;
($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
sub qemu_cpu_hotplug {
my ($vmid, $conf, $vcpus) = @_;
- my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
+ my $machine_type = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
my $sockets = 1;
$sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
if ($vcpus < $currentvcpus) {
- if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
+ if (PVE::QemuServer::Machine::machine_version($machine_type, 2, 7)) {
for (my $i = $currentvcpus; $i > $vcpus; $i--) {
qemu_devicedel($vmid, "cpu$i");
die "vcpus in running vm does not match its configuration\n"
if scalar(@{$currentrunningvcpus}) != $currentvcpus;
- if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
+ if (PVE::QemuServer::Machine::machine_version($machine_type, 2, 7)) {
for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
my $cpustr = print_cpu_device($conf, $i);
'protection' => 1,
'vmstatestorage' => 1,
'hookscript' => 1,
+ 'tags' => 1,
};
# hotplug changes in [PENDING]
my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
my $defaults = load_defaults();
- my ($arch, $machine_type) = get_basic_machine_info($conf, undef);
+ my $arch = get_vm_arch($conf);
+ my $machine_type = get_vm_machine($conf, undef, $arch);
# commit values which do not have any impact on running VM first
# Note: those option cannot raise errors, we we do not care about
vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
$vmid, $opt, $value, $arch, $machine_type);
} elsif (is_valid_drivename($opt)) {
+ die "skip\n" if $opt eq 'efidisk0';
# some changes can be done without hotplug
my $drive = parse_drive($opt, $value);
if (drive_is_cloudinit($drive)) {
foreach my $pcidevice (@$pcidevices) {
my $pciid = $pcidevice->{id};
- my $info = PVE::SysFSTools::pci_device_info("0000:$pciid");
+ my $info = PVE::SysFSTools::pci_device_info("$pciid");
die "IOMMU not present\n" if !PVE::SysFSTools::check_iommu_support();
die "no pci device info for device '$pciid'\n" if !$info;
property => "guest-stats-polling-interval",
value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
- if ($is_suspended && (my $vmstate = $conf->{vmstate})) {
+ if ($is_suspended) {
print "Resumed VM, removing state\n";
+ if (my $vmstate = $conf->{vmstate}) {
+ PVE::Storage::deactivate_volumes($storecfg, [$vmstate]);
+ PVE::Storage::vdisk_free($storecfg, $vmstate);
+ }
delete $conf->@{qw(lock vmstate runningmachine)};
- PVE::Storage::deactivate_volumes($storecfg, [$vmstate]);
- PVE::Storage::vdisk_free($storecfg, $vmstate);
PVE::QemuConfig->write_config($vmid, $conf);
}
}
}
+my $qemu_snap_storage = {
+ rbd => 1,
+};
sub do_snapshots_with_qemu {
my ($storecfg, $volid) = @_;
my $cachemode;
my $src_path;
my $src_is_iscsi = 0;
- my $src_format = 'raw';
+ my $src_format;
if ($src_storeid) {
PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname);
my $cmd = [];
push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
- push @$cmd, '-l', "snapshot.name=$snapname" if($snapname && $src_format eq "qcow2");
+ push @$cmd, '-l', "snapshot.name=$snapname"
+ if $snapname && $src_format && $src_format eq "qcow2";
push @$cmd, '-t', 'none' if $dst_scfg->{type} eq 'zfspool';
push @$cmd, '-T', $cachemode if defined($cachemode);
if ($src_is_iscsi) {
push @$cmd, '--image-opts';
$src_path = convert_iscsi_path($src_path);
- } else {
+ } elsif ($src_format) {
push @$cmd, '-f', $src_format;
}
} else {
my $kvmver = get_running_qemu_version ($vmid);
- if (!qemu_machine_feature_enabled (undef, $kvmver, 2, 7)) {
+ if (!min_version($kvmver, 2, 7)) {
die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
if $drive->{iothread};
}
return $disk;
}
-# this only works if VM is running
-sub get_current_qemu_machine {
- my ($vmid) = @_;
-
- my $res = mon_cmd($vmid, "query-machines");
-
- my ($current, $default);
- foreach my $e (@$res) {
- $default = $e->{name} if $e->{'is-default'};
- $current = $e->{name} if $e->{'is-current'};
- }
-
- # fallback to the default machine if current is not supported by qemu
- return $current || $default || 'pc';
-}
-
sub get_running_qemu_version {
my ($vmid) = @_;
my $res = mon_cmd($vmid, "query-version");
return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
}
-sub qemu_machine_feature_enabled {
- my ($machine, $kvmver, $version_major, $version_minor) = @_;
-
- my $current_major;
- my $current_minor;
-
- if ($machine && $machine =~ m/^((?:pc(-i440fx|-q35)?|virt)-(\d+)\.(\d+))/) {
-
- $current_major = $3;
- $current_minor = $4;
-
- } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
-
- $current_major = $1;
- $current_minor = $2;
- }
-
- return 1 if version_cmp($current_major, $version_major, $current_minor, $version_minor) >= 0;
-}
-
-# gets in pairs the versions you want to compares, i.e.:
-# ($a-major, $b-major, $a-minor, $b-minor, $a-extra, $b-extra, ...)
-# returns 0 if same, -1 if $a is older than $b, +1 if $a is newer than $b
-sub version_cmp {
- my @versions = @_;
-
- my $size = scalar(@versions);
-
- return 0 if $size == 0;
- die "cannot compare odd count of versions" if $size & 1;
-
- for (my $i = 0; $i < $size; $i += 2) {
- my ($a, $b) = splice(@versions, 0, 2);
- $a //= 0;
- $b //= 0;
-
- return 1 if $a > $b;
- return -1 if $a < $b;
- }
- return 0;
-}
-
-# dies if a) VM not running or not exisiting b) Version query failed
-# So, any defined return value is valid, any invalid state can be caught by eval
-sub runs_at_least_qemu_version {
- my ($vmid, $major, $minor, $extra) = @_;
-
- my $v = mon_cmd($vmid, "query-version");
- die "could not query currently running version for VM $vmid\n" if !defined($v);
- $v = $v->{qemu};
-
- return version_cmp($v->{major}, $major, $v->{minor}, $minor, $v->{micro}, $extra) >= 0;
-}
-
-sub qemu_machine_pxe {
- my ($vmid, $conf) = @_;
-
- my $machine = PVE::QemuServer::get_current_qemu_machine($vmid);
-
- if ($conf->{machine} && $conf->{machine} =~ m/\.pxe$/) {
- $machine .= '.pxe';
- }
-
- return $machine;
-}
-
sub qemu_use_old_bios_files {
my ($machine_type) = @_;
$machine_type = $1;
$use_old_bios_files = 1;
} else {
- my $kvmver = kvm_user_version();
+ my $version = PVE::QemuServer::Machine::extract_version($machine_type, kvm_user_version());
# Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
# load new efi bios files on migration. So this hack is required to allow
# live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
# updrading from proxmox-ve-3.X to proxmox-ve 4.0
- $use_old_bios_files = !qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 4);
+ $use_old_bios_files = !min_version($version, 2, 4);
}
return ($use_old_bios_files, $machine_type);
PVE::Storage::activate_volumes($storecfg, [$volid]);
qemu_img_convert($ovmf_vars, $volid, $vars_size_b, undef, 0);
+ my ($size) = PVE::Storage::volume_size_info($storecfg, $volid, 3);
- return ($volid, $vars_size);
+ return ($volid, $size/1024);
}
sub vm_iothreads_list {
}
sub add_hyperv_enlightenments {
- my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough, $hv_vendor_id) = @_;
+ my ($cpuFlags, $winversion, $machine_version, $bios, $gpu_passthrough, $hv_vendor_id) = @_;
return if $winversion < 6;
return if $bios && $bios eq 'ovmf' && $winversion < 8;
push @$cpuFlags , "hv_vendor_id=$hv_vendor_id";
}
- if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
+ if (min_version($machine_version, 2, 3)) {
push @$cpuFlags , 'hv_spinlocks=0x1fff';
push @$cpuFlags , 'hv_vapic';
push @$cpuFlags , 'hv_time';
push @$cpuFlags , 'hv_spinlocks=0xffff';
}
- if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 6)) {
+ if (min_version($machine_version, 2, 6)) {
push @$cpuFlags , 'hv_reset';
push @$cpuFlags , 'hv_vpindex';
push @$cpuFlags , 'hv_runtime';
if ($winversion >= 7) {
push @$cpuFlags , 'hv_relaxed';
- if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 12)) {
+ if (min_version($machine_version, 2, 12)) {
push @$cpuFlags , 'hv_synic';
push @$cpuFlags , 'hv_stimer';
}
- if (qemu_machine_feature_enabled ($machine_type, $kvmver, 3, 1)) {
+ if (min_version($machine_version, 3, 1)) {
push @$cpuFlags , 'hv_ipi';
}
}