[pve-devel] [RFC qemu-server 4/6] Add QEMU CPU flag querying helpers
Stefan Reiter
s.reiter at proxmox.com
Wed Jul 17 15:03:46 CEST 2019
* query_understood_cpu_flags returns all flags that QEMU/KVM knows about
* query_supported_cpu_flags returns all flags that QEMU/KVM can use on
this particular host.
To get supported flags, a temporary VM is started with QEMU, so we can
issue the "query-cpu-model-expansion" QMP command. This is how libvirt
queries supported flags for its "host-passthrough" CPU type.
query_supported_cpu_flags is thus rather slow and shouldn't be called
unnecessarily.
Signed-off-by: Stefan Reiter <s.reiter at proxmox.com>
---
PVE/QemuServer.pm | 79 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 9f29927..9ee9722 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3448,6 +3448,85 @@ sub get_command_for_arch($) {
return $cmd;
}
+sub query_understood_cpu_flags {
+ my $flags = [];
+ my $flag_section = 0;
+
+ run_command(
+ [get_command_for_arch('x86_64'), '-cpu', 'help'],
+ noerr => 1,
+ quiet => 1,
+ outfunc => sub {
+ my ($line) = @_;
+
+ if ($flag_section) {
+ return if $line =~ m/^\s*$/;
+ $line =~ m/^\s*(.+?)\s*$/;
+ ($line = $1) =~ s/-|\./_/g;
+ my @flags_line = split(m/\s+/, $line);
+ @$flags = (@$flags, @flags_line);
+ } elsif ($line =~ m/^\s*Recognized CPUID flags:\s*$/) {
+ $flag_section = 1;
+ }
+ });
+
+ return $flags;
+}
+
+sub query_supported_cpu_flags {
+ my $flags = [];
+
+ my $pidfile = '/var/run/qemu-server/-1.pid';
+
+ # We start a temporary (frozen) VM with vmid -1 to allow us to send a QMP command
+ my $rc = run_command([
+ get_command_for_arch('x86_64'),
+ '-cpu', 'kvm64',
+ '-display', 'none',
+ '-chardev', 'socket,id=qmp,path=/var/run/qemu-server/-1.qmp,server,nowait',
+ '-mon', 'chardev=qmp,mode=control',
+ '-pidfile', $pidfile,
+ '-S',
+ '-daemonize'
+ ], noerr => 1, quiet => 1);
+ return [] if $rc;
+
+ my $qmpclient = PVE::QMPClient->new();
+ $qmpclient->queue_cmd(
+ -1,
+ sub {
+ my ($vmid, $response) = @_;
+
+ return if %{$response->{error}};
+
+ my $props = $response->{return}->{model}->{props};
+ return if !%$props;
+
+ foreach my $prop_raw (keys %$props) {
+ (my $prop = $prop_raw) =~ s/-|\./_/g;
+ push @$flags, $prop if "$props->{$prop_raw}" eq '1';
+ }
+ },
+ 'query-cpu-model-expansion',
+ type => 'full',
+ model => { name => 'host' });
+ $qmpclient->queue_cmd(-1, undef, 'quit');
+ $qmpclient->queue_execute(3, 2);
+
+ # Wait for QEMU to terminate
+ sleep 1;
+
+ if (-e $pidfile) {
+ $rc = run_command([
+ 'pkill', '-F', $pidfile
+ ], noerr => 1, quiet => 1);
+
+ warn 'QEMU instance used for host CPU flag detection could not be killed\n' if $rc;
+ }
+
+ return $flags;
+}
+
sub get_cpu_options {
my ($conf, $arch, $kvm, $machine_type, $kvm_off, $kvmver, $winversion, $gpu_passthrough) = @_;
--
2.20.1
More information about the pve-devel
mailing list