All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v17] qapi: introduce 'x-query-x86-cpuid' QMP command.
@ 2022-01-21 16:39 Vladimir Sementsov-Ogievskiy
  2022-01-24 15:05   ` Markus Armbruster
  2022-02-17 15:39 ` Vladimir Sementsov-Ogievskiy
  0 siblings, 2 replies; 6+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2022-01-21 16:39 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, lvivier, thuth, mtosatti, richard.henderson, pbonzini,
	armbru, eblake, wangyanan55, f4bug, marcel.apfelbaum, eduardo,
	vsementsov, valery.vdovin.s, den, Valeriy Vdovin

From: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>

Introducing new QMP command 'query-x86-cpuid'. This command can be
used to get virtualized cpu model info generated by QEMU during VM
initialization in the form of cpuid representation.

Diving into more details about virtual CPU generation: QEMU first
parses '-cpu' command line option. From there it takes the name of the
model as the basis for feature set of the new virtual CPU. After that
it uses trailing '-cpu' options, that state if additional cpu features
should be present on the virtual CPU or excluded from it (tokens
'+'/'-' or '=on'/'=off').
After that QEMU checks if the host's cpu can actually support the
derived feature set and applies host limitations to it.
After this initialization procedure, virtual CPU has it's model and
vendor names, and a working feature set and is ready for
identification instructions such as CPUID.

To learn exactly how virtual CPU is presented to the guest machine via
CPUID instruction, new QMP command can be used. By calling
'query-x86-cpuid' command, one can get a full listing of all CPUID
leaves with subleaves which are supported by the initialized virtual
CPU.

Other than debug, the command is useful in cases when we would like to
utilize QEMU's virtual CPU initialization routines and put the
retrieved values into kernel CPUID overriding mechanics for more
precise control over how various processes perceive its underlying
hardware with container processes as a good example.

The command is specific to x86. It is currenly only implemented for
KVM acceleator.

Output format:
The output is a plain list of leaf/subleaf argument combinations, that
return 4 words in registers EAX, EBX, ECX, EDX.

Use example:
qmp_request: {
  "execute": "x-query-x86-cpuid"
}

qmp_response: {
  "return": [
    {
      "eax": 1073741825,
      "edx": 77,
      "in-eax": 1073741824,
      "ecx": 1447775574,
      "ebx": 1263359563
    },
    {
      "eax": 16777339,
      "edx": 0,
      "in-eax": 1073741825,
      "ecx": 0,
      "ebx": 0
    },
    {
      "eax": 13,
      "edx": 1231384169,
      "in-eax": 0,
      "ecx": 1818588270,
      "ebx": 1970169159
    },
    {
      "eax": 198354,
      "edx": 126614527,
      "in-eax": 1,
      "ecx": 2176328193,
      "ebx": 2048
    },
    ....
    {
      "eax": 12328,
      "edx": 0,
      "in-eax": 2147483656,
      "ecx": 0,
      "ebx": 0
    }
  ]
}

Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---

v17: wrap long lines, add QAPI feature 'unstable' [Markus]

 qapi/machine-target.json   | 50 ++++++++++++++++++++++++++++++++++++++
 softmmu/cpus.c             |  2 +-
 target/i386/kvm/kvm-stub.c |  9 +++++++
 target/i386/kvm/kvm.c      | 44 +++++++++++++++++++++++++++++++++
 tests/qtest/qmp-cmd-test.c |  1 +
 5 files changed, 105 insertions(+), 1 deletion(-)

diff --git a/qapi/machine-target.json b/qapi/machine-target.json
index f5ec4bc172..1568e17e74 100644
--- a/qapi/machine-target.json
+++ b/qapi/machine-target.json
@@ -341,3 +341,53 @@
                    'TARGET_I386',
                    'TARGET_S390X',
                    'TARGET_MIPS' ] } }
+
+##
+# @CpuidEntry:
+#
+# A single entry of a CPUID response.
+#
+# One entry holds full set of information (leaf) returned to the guest
+# in response to it calling a CPUID instruction with eax, ecx used as
+# the arguments to that instruction. ecx is an optional argument as
+# not all of the leaves support it.
+#
+# @in-eax: CPUID argument in eax
+# @in-ecx: CPUID argument in ecx
+# @eax: CPUID result in eax
+# @ebx: CPUID result in ebx
+# @ecx: CPUID result in ecx
+# @edx: CPUID result in edx
+#
+# Since: 7.0
+##
+{ 'struct': 'CpuidEntry',
+  'data': { 'in-eax' : 'uint32',
+            '*in-ecx' : 'uint32',
+            'eax' : 'uint32',
+            'ebx' : 'uint32',
+            'ecx' : 'uint32',
+            'edx' : 'uint32'
+          },
+  'if': 'TARGET_I386' }
+
+##
+# @x-query-x86-cpuid:
+#
+# Returns raw data from the emulated CPUID table for the first VCPU.
+# The emulated CPUID table defines the response to the CPUID
+# instruction when executed by the guest operating system.
+#
+# Features:
+# @unstable: This command is experimental.
+#
+# Returns: a list of CpuidEntry. Returns error when qemu is configured
+#          with --disable-kvm flag or if qemu is run with any other
+#          accelerator than KVM.
+#
+# Since: 7.0
+##
+{ 'command': 'x-query-x86-cpuid',
+  'returns': [ 'CpuidEntry' ],
+  'if': 'TARGET_I386',
+  'features': [ 'unstable' ] }
diff --git a/softmmu/cpus.c b/softmmu/cpus.c
index 23bca46b07..33045bf45c 100644
--- a/softmmu/cpus.c
+++ b/softmmu/cpus.c
@@ -129,7 +129,7 @@ void hw_error(const char *fmt, ...)
 /*
  * The chosen accelerator is supposed to register this.
  */
-static const AccelOpsClass *cpus_accel;
+const AccelOpsClass *cpus_accel;
 
 void cpu_synchronize_all_states(void)
 {
diff --git a/target/i386/kvm/kvm-stub.c b/target/i386/kvm/kvm-stub.c
index f6e7e4466e..71631e560d 100644
--- a/target/i386/kvm/kvm-stub.c
+++ b/target/i386/kvm/kvm-stub.c
@@ -12,6 +12,7 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include "kvm_i386.h"
+#include "qapi/error.h"
 
 #ifndef __OPTIMIZE__
 bool kvm_has_smm(void)
@@ -44,3 +45,11 @@ bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp)
 {
     abort();
 }
+
+CpuidEntryList *qmp_x_query_x86_cpuid(Error **errp);
+
+CpuidEntryList *qmp_x_query_x86_cpuid(Error **errp)
+{
+    error_setg(errp, "Not implemented in --disable-kvm configuration");
+    return NULL;
+}
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 2c8feb4a6f..eb73869039 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -20,11 +20,13 @@
 
 #include <linux/kvm.h>
 #include "standard-headers/asm-x86/kvm_para.h"
+#include "qapi/qapi-commands-machine-target.h"
 
 #include "cpu.h"
 #include "host-cpu.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/hw_accel.h"
+#include "sysemu/accel-ops.h"
 #include "sysemu/kvm_int.h"
 #include "sysemu/runstate.h"
 #include "kvm_i386.h"
@@ -1565,6 +1567,44 @@ static Error *invtsc_mig_blocker;
 
 #define KVM_MAX_CPUID_ENTRIES  100
 
+struct kvm_cpuid2 *cpuid_data_cached;
+
+
+CpuidEntryList *qmp_x_query_x86_cpuid(Error **errp)
+{
+    int i;
+    struct kvm_cpuid_entry2 *kvm_entry;
+    CpuidEntryList *head = NULL, **tail = &head;
+    CpuidEntry *entry;
+
+    if (!kvm_enabled()) {
+        error_setg(errp, "Not implemented for non-kvm accel");
+        return NULL;
+    }
+
+    if (!cpuid_data_cached) {
+        error_setg(errp, "VCPU was not initialized yet");
+        return NULL;
+    }
+
+    for (i = 0; i < cpuid_data_cached->nent; ++i) {
+        kvm_entry = &cpuid_data_cached->entries[i];
+        entry = g_malloc0(sizeof(*entry));
+        entry->in_eax = kvm_entry->function;
+        if (kvm_entry->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX) {
+            entry->in_ecx = kvm_entry->index;
+            entry->has_in_ecx = true;
+        }
+        entry->eax = kvm_entry->eax;
+        entry->ebx = kvm_entry->ebx;
+        entry->ecx = kvm_entry->ecx;
+        entry->edx = kvm_entry->edx;
+        QAPI_LIST_APPEND(tail, entry);
+    }
+
+    return head;
+}
+
 int kvm_arch_init_vcpu(CPUState *cs)
 {
     struct {
@@ -1981,6 +2021,10 @@ int kvm_arch_init_vcpu(CPUState *cs)
     if (r) {
         goto fail;
     }
+    if (!cpuid_data_cached) {
+        cpuid_data_cached = g_malloc0(sizeof(cpuid_data));
+        memcpy(cpuid_data_cached, &cpuid_data, sizeof(cpuid_data));
+    }
 
     if (has_xsave) {
         env->xsave_buf_len = sizeof(struct kvm_xsave);
diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c
index 7f103ea3fd..94d9184a84 100644
--- a/tests/qtest/qmp-cmd-test.c
+++ b/tests/qtest/qmp-cmd-test.c
@@ -54,6 +54,7 @@ static int query_error_class(const char *cmd)
         /* Only valid with accel=tcg */
         { "x-query-jit", ERROR_CLASS_GENERIC_ERROR },
         { "x-query-opcount", ERROR_CLASS_GENERIC_ERROR },
+        { "x-query-x86-cpuid", ERROR_CLASS_GENERIC_ERROR },
         { NULL, -1 }
     };
     int i;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v17] qapi: introduce 'x-query-x86-cpuid' QMP command.
  2022-01-21 16:39 [PATCH v17] qapi: introduce 'x-query-x86-cpuid' QMP command Vladimir Sementsov-Ogievskiy
@ 2022-01-24 15:05   ` Markus Armbruster
  2022-02-17 15:39 ` Vladimir Sementsov-Ogievskiy
  1 sibling, 0 replies; 6+ messages in thread
From: Markus Armbruster @ 2022-01-24 15:05 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy
  Cc: qemu-devel, kvm, lvivier, thuth, mtosatti, richard.henderson,
	pbonzini, eblake, wangyanan55, f4bug, marcel.apfelbaum, eduardo,
	valery.vdovin.s, den, Valeriy Vdovin

Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> writes:

> From: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
>
> Introducing new QMP command 'query-x86-cpuid'. This command can be
> used to get virtualized cpu model info generated by QEMU during VM
> initialization in the form of cpuid representation.
>
> Diving into more details about virtual CPU generation: QEMU first
> parses '-cpu' command line option. From there it takes the name of the
> model as the basis for feature set of the new virtual CPU. After that
> it uses trailing '-cpu' options, that state if additional cpu features
> should be present on the virtual CPU or excluded from it (tokens
> '+'/'-' or '=on'/'=off').
> After that QEMU checks if the host's cpu can actually support the
> derived feature set and applies host limitations to it.
> After this initialization procedure, virtual CPU has it's model and
> vendor names, and a working feature set and is ready for
> identification instructions such as CPUID.
>
> To learn exactly how virtual CPU is presented to the guest machine via
> CPUID instruction, new QMP command can be used. By calling
> 'query-x86-cpuid' command, one can get a full listing of all CPUID
> leaves with subleaves which are supported by the initialized virtual
> CPU.
>
> Other than debug, the command is useful in cases when we would like to
> utilize QEMU's virtual CPU initialization routines and put the
> retrieved values into kernel CPUID overriding mechanics for more
> precise control over how various processes perceive its underlying
> hardware with container processes as a good example.
>
> The command is specific to x86. It is currenly only implemented for
> KVM acceleator.
>
> Output format:
> The output is a plain list of leaf/subleaf argument combinations, that
> return 4 words in registers EAX, EBX, ECX, EDX.
>
> Use example:
> qmp_request: {
>   "execute": "x-query-x86-cpuid"
> }
>
> qmp_response: {
>   "return": [
>     {
>       "eax": 1073741825,
>       "edx": 77,
>       "in-eax": 1073741824,
>       "ecx": 1447775574,
>       "ebx": 1263359563
>     },
>     {
>       "eax": 16777339,
>       "edx": 0,
>       "in-eax": 1073741825,
>       "ecx": 0,
>       "ebx": 0
>     },
>     {
>       "eax": 13,
>       "edx": 1231384169,
>       "in-eax": 0,
>       "ecx": 1818588270,
>       "ebx": 1970169159
>     },
>     {
>       "eax": 198354,
>       "edx": 126614527,
>       "in-eax": 1,
>       "ecx": 2176328193,
>       "ebx": 2048
>     },
>     ....
>     {
>       "eax": 12328,
>       "edx": 0,
>       "in-eax": 2147483656,
>       "ecx": 0,
>       "ebx": 0
>     }
>   ]
> }
>
> Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> ---
>
> v17: wrap long lines, add QAPI feature 'unstable' [Markus]
>
>  qapi/machine-target.json   | 50 ++++++++++++++++++++++++++++++++++++++
>  softmmu/cpus.c             |  2 +-
>  target/i386/kvm/kvm-stub.c |  9 +++++++
>  target/i386/kvm/kvm.c      | 44 +++++++++++++++++++++++++++++++++
>  tests/qtest/qmp-cmd-test.c |  1 +
>  5 files changed, 105 insertions(+), 1 deletion(-)
>
> diff --git a/qapi/machine-target.json b/qapi/machine-target.json
> index f5ec4bc172..1568e17e74 100644
> --- a/qapi/machine-target.json
> +++ b/qapi/machine-target.json
> @@ -341,3 +341,53 @@
>                     'TARGET_I386',
>                     'TARGET_S390X',
>                     'TARGET_MIPS' ] } }
> +
> +##
> +# @CpuidEntry:
> +#
> +# A single entry of a CPUID response.
> +#
> +# One entry holds full set of information (leaf) returned to the guest
> +# in response to it calling a CPUID instruction with eax, ecx used as
> +# the arguments to that instruction. ecx is an optional argument as
> +# not all of the leaves support it.
> +#
> +# @in-eax: CPUID argument in eax
> +# @in-ecx: CPUID argument in ecx
> +# @eax: CPUID result in eax
> +# @ebx: CPUID result in ebx
> +# @ecx: CPUID result in ecx
> +# @edx: CPUID result in edx
> +#
> +# Since: 7.0
> +##
> +{ 'struct': 'CpuidEntry',
> +  'data': { 'in-eax' : 'uint32',
> +            '*in-ecx' : 'uint32',
> +            'eax' : 'uint32',
> +            'ebx' : 'uint32',
> +            'ecx' : 'uint32',
> +            'edx' : 'uint32'
> +          },
> +  'if': 'TARGET_I386' }
> +
> +##
> +# @x-query-x86-cpuid:
> +#
> +# Returns raw data from the emulated CPUID table for the first VCPU.
> +# The emulated CPUID table defines the response to the CPUID
> +# instruction when executed by the guest operating system.
> +#
> +# Features:
> +# @unstable: This command is experimental.
> +#
> +# Returns: a list of CpuidEntry. Returns error when qemu is configured
> +#          with --disable-kvm flag or if qemu is run with any other
> +#          accelerator than KVM.
> +#
> +# Since: 7.0
> +##
> +{ 'command': 'x-query-x86-cpuid',
> +  'returns': [ 'CpuidEntry' ],
> +  'if': 'TARGET_I386',
> +  'features': [ 'unstable' ] }

QAPI schema
Acked-by: Markus Armbruster <armbru@redhat.com>

[...]


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v17] qapi: introduce 'x-query-x86-cpuid' QMP command.
@ 2022-01-24 15:05   ` Markus Armbruster
  0 siblings, 0 replies; 6+ messages in thread
From: Markus Armbruster @ 2022-01-24 15:05 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy
  Cc: lvivier, eduardo, thuth, kvm, valery.vdovin.s, mtosatti,
	richard.henderson, qemu-devel, f4bug, wangyanan55,
	Valeriy Vdovin, den, pbonzini, eblake

Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> writes:

> From: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
>
> Introducing new QMP command 'query-x86-cpuid'. This command can be
> used to get virtualized cpu model info generated by QEMU during VM
> initialization in the form of cpuid representation.
>
> Diving into more details about virtual CPU generation: QEMU first
> parses '-cpu' command line option. From there it takes the name of the
> model as the basis for feature set of the new virtual CPU. After that
> it uses trailing '-cpu' options, that state if additional cpu features
> should be present on the virtual CPU or excluded from it (tokens
> '+'/'-' or '=on'/'=off').
> After that QEMU checks if the host's cpu can actually support the
> derived feature set and applies host limitations to it.
> After this initialization procedure, virtual CPU has it's model and
> vendor names, and a working feature set and is ready for
> identification instructions such as CPUID.
>
> To learn exactly how virtual CPU is presented to the guest machine via
> CPUID instruction, new QMP command can be used. By calling
> 'query-x86-cpuid' command, one can get a full listing of all CPUID
> leaves with subleaves which are supported by the initialized virtual
> CPU.
>
> Other than debug, the command is useful in cases when we would like to
> utilize QEMU's virtual CPU initialization routines and put the
> retrieved values into kernel CPUID overriding mechanics for more
> precise control over how various processes perceive its underlying
> hardware with container processes as a good example.
>
> The command is specific to x86. It is currenly only implemented for
> KVM acceleator.
>
> Output format:
> The output is a plain list of leaf/subleaf argument combinations, that
> return 4 words in registers EAX, EBX, ECX, EDX.
>
> Use example:
> qmp_request: {
>   "execute": "x-query-x86-cpuid"
> }
>
> qmp_response: {
>   "return": [
>     {
>       "eax": 1073741825,
>       "edx": 77,
>       "in-eax": 1073741824,
>       "ecx": 1447775574,
>       "ebx": 1263359563
>     },
>     {
>       "eax": 16777339,
>       "edx": 0,
>       "in-eax": 1073741825,
>       "ecx": 0,
>       "ebx": 0
>     },
>     {
>       "eax": 13,
>       "edx": 1231384169,
>       "in-eax": 0,
>       "ecx": 1818588270,
>       "ebx": 1970169159
>     },
>     {
>       "eax": 198354,
>       "edx": 126614527,
>       "in-eax": 1,
>       "ecx": 2176328193,
>       "ebx": 2048
>     },
>     ....
>     {
>       "eax": 12328,
>       "edx": 0,
>       "in-eax": 2147483656,
>       "ecx": 0,
>       "ebx": 0
>     }
>   ]
> }
>
> Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> ---
>
> v17: wrap long lines, add QAPI feature 'unstable' [Markus]
>
>  qapi/machine-target.json   | 50 ++++++++++++++++++++++++++++++++++++++
>  softmmu/cpus.c             |  2 +-
>  target/i386/kvm/kvm-stub.c |  9 +++++++
>  target/i386/kvm/kvm.c      | 44 +++++++++++++++++++++++++++++++++
>  tests/qtest/qmp-cmd-test.c |  1 +
>  5 files changed, 105 insertions(+), 1 deletion(-)
>
> diff --git a/qapi/machine-target.json b/qapi/machine-target.json
> index f5ec4bc172..1568e17e74 100644
> --- a/qapi/machine-target.json
> +++ b/qapi/machine-target.json
> @@ -341,3 +341,53 @@
>                     'TARGET_I386',
>                     'TARGET_S390X',
>                     'TARGET_MIPS' ] } }
> +
> +##
> +# @CpuidEntry:
> +#
> +# A single entry of a CPUID response.
> +#
> +# One entry holds full set of information (leaf) returned to the guest
> +# in response to it calling a CPUID instruction with eax, ecx used as
> +# the arguments to that instruction. ecx is an optional argument as
> +# not all of the leaves support it.
> +#
> +# @in-eax: CPUID argument in eax
> +# @in-ecx: CPUID argument in ecx
> +# @eax: CPUID result in eax
> +# @ebx: CPUID result in ebx
> +# @ecx: CPUID result in ecx
> +# @edx: CPUID result in edx
> +#
> +# Since: 7.0
> +##
> +{ 'struct': 'CpuidEntry',
> +  'data': { 'in-eax' : 'uint32',
> +            '*in-ecx' : 'uint32',
> +            'eax' : 'uint32',
> +            'ebx' : 'uint32',
> +            'ecx' : 'uint32',
> +            'edx' : 'uint32'
> +          },
> +  'if': 'TARGET_I386' }
> +
> +##
> +# @x-query-x86-cpuid:
> +#
> +# Returns raw data from the emulated CPUID table for the first VCPU.
> +# The emulated CPUID table defines the response to the CPUID
> +# instruction when executed by the guest operating system.
> +#
> +# Features:
> +# @unstable: This command is experimental.
> +#
> +# Returns: a list of CpuidEntry. Returns error when qemu is configured
> +#          with --disable-kvm flag or if qemu is run with any other
> +#          accelerator than KVM.
> +#
> +# Since: 7.0
> +##
> +{ 'command': 'x-query-x86-cpuid',
> +  'returns': [ 'CpuidEntry' ],
> +  'if': 'TARGET_I386',
> +  'features': [ 'unstable' ] }

QAPI schema
Acked-by: Markus Armbruster <armbru@redhat.com>

[...]



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v17] qapi: introduce 'x-query-x86-cpuid' QMP command.
  2022-01-21 16:39 [PATCH v17] qapi: introduce 'x-query-x86-cpuid' QMP command Vladimir Sementsov-Ogievskiy
  2022-01-24 15:05   ` Markus Armbruster
@ 2022-02-17 15:39 ` Vladimir Sementsov-Ogievskiy
  2022-02-17 16:08     ` Markus Armbruster
  1 sibling, 1 reply; 6+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2022-02-17 15:39 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, lvivier, thuth, mtosatti, richard.henderson, pbonzini,
	armbru, eblake, wangyanan55, f4bug, marcel.apfelbaum, eduardo,
	valery.vdovin.s, den, Valeriy Vdovin

Ping :) Any hope that we will merge it one day?)

21.01.2022 19:39, Vladimir Sementsov-Ogievskiy wrote:
> From: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
> 
> Introducing new QMP command 'query-x86-cpuid'. This command can be
> used to get virtualized cpu model info generated by QEMU during VM
> initialization in the form of cpuid representation.
> 
> Diving into more details about virtual CPU generation: QEMU first
> parses '-cpu' command line option. From there it takes the name of the
> model as the basis for feature set of the new virtual CPU. After that
> it uses trailing '-cpu' options, that state if additional cpu features
> should be present on the virtual CPU or excluded from it (tokens
> '+'/'-' or '=on'/'=off').
> After that QEMU checks if the host's cpu can actually support the
> derived feature set and applies host limitations to it.
> After this initialization procedure, virtual CPU has it's model and
> vendor names, and a working feature set and is ready for
> identification instructions such as CPUID.
> 
> To learn exactly how virtual CPU is presented to the guest machine via
> CPUID instruction, new QMP command can be used. By calling
> 'query-x86-cpuid' command, one can get a full listing of all CPUID
> leaves with subleaves which are supported by the initialized virtual
> CPU.
> 
> Other than debug, the command is useful in cases when we would like to
> utilize QEMU's virtual CPU initialization routines and put the
> retrieved values into kernel CPUID overriding mechanics for more
> precise control over how various processes perceive its underlying
> hardware with container processes as a good example.
> 
> The command is specific to x86. It is currenly only implemented for
> KVM acceleator.
> 
> Output format:
> The output is a plain list of leaf/subleaf argument combinations, that
> return 4 words in registers EAX, EBX, ECX, EDX.
> 
> Use example:
> qmp_request: {
>    "execute": "x-query-x86-cpuid"
> }
> 
> qmp_response: {
>    "return": [
>      {
>        "eax": 1073741825,
>        "edx": 77,
>        "in-eax": 1073741824,
>        "ecx": 1447775574,
>        "ebx": 1263359563
>      },
>      {
>        "eax": 16777339,
>        "edx": 0,
>        "in-eax": 1073741825,
>        "ecx": 0,
>        "ebx": 0
>      },
>      {
>        "eax": 13,
>        "edx": 1231384169,
>        "in-eax": 0,
>        "ecx": 1818588270,
>        "ebx": 1970169159
>      },
>      {
>        "eax": 198354,
>        "edx": 126614527,
>        "in-eax": 1,
>        "ecx": 2176328193,
>        "ebx": 2048
>      },
>      ....
>      {
>        "eax": 12328,
>        "edx": 0,
>        "in-eax": 2147483656,
>        "ecx": 0,
>        "ebx": 0
>      }
>    ]
> }
> 
> Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> ---
> 
> v17: wrap long lines, add QAPI feature 'unstable' [Markus]
> 
>   qapi/machine-target.json   | 50 ++++++++++++++++++++++++++++++++++++++
>   softmmu/cpus.c             |  2 +-
>   target/i386/kvm/kvm-stub.c |  9 +++++++
>   target/i386/kvm/kvm.c      | 44 +++++++++++++++++++++++++++++++++
>   tests/qtest/qmp-cmd-test.c |  1 +
>   5 files changed, 105 insertions(+), 1 deletion(-)
> 
> diff --git a/qapi/machine-target.json b/qapi/machine-target.json
> index f5ec4bc172..1568e17e74 100644
> --- a/qapi/machine-target.json
> +++ b/qapi/machine-target.json
> @@ -341,3 +341,53 @@
>                      'TARGET_I386',
>                      'TARGET_S390X',
>                      'TARGET_MIPS' ] } }
> +
> +##
> +# @CpuidEntry:
> +#
> +# A single entry of a CPUID response.
> +#
> +# One entry holds full set of information (leaf) returned to the guest
> +# in response to it calling a CPUID instruction with eax, ecx used as
> +# the arguments to that instruction. ecx is an optional argument as
> +# not all of the leaves support it.
> +#
> +# @in-eax: CPUID argument in eax
> +# @in-ecx: CPUID argument in ecx
> +# @eax: CPUID result in eax
> +# @ebx: CPUID result in ebx
> +# @ecx: CPUID result in ecx
> +# @edx: CPUID result in edx
> +#
> +# Since: 7.0
> +##
> +{ 'struct': 'CpuidEntry',
> +  'data': { 'in-eax' : 'uint32',
> +            '*in-ecx' : 'uint32',
> +            'eax' : 'uint32',
> +            'ebx' : 'uint32',
> +            'ecx' : 'uint32',
> +            'edx' : 'uint32'
> +          },
> +  'if': 'TARGET_I386' }
> +
> +##
> +# @x-query-x86-cpuid:
> +#
> +# Returns raw data from the emulated CPUID table for the first VCPU.
> +# The emulated CPUID table defines the response to the CPUID
> +# instruction when executed by the guest operating system.
> +#
> +# Features:
> +# @unstable: This command is experimental.
> +#
> +# Returns: a list of CpuidEntry. Returns error when qemu is configured
> +#          with --disable-kvm flag or if qemu is run with any other
> +#          accelerator than KVM.
> +#
> +# Since: 7.0
> +##
> +{ 'command': 'x-query-x86-cpuid',
> +  'returns': [ 'CpuidEntry' ],
> +  'if': 'TARGET_I386',
> +  'features': [ 'unstable' ] }
> diff --git a/softmmu/cpus.c b/softmmu/cpus.c
> index 23bca46b07..33045bf45c 100644
> --- a/softmmu/cpus.c
> +++ b/softmmu/cpus.c
> @@ -129,7 +129,7 @@ void hw_error(const char *fmt, ...)
>   /*
>    * The chosen accelerator is supposed to register this.
>    */
> -static const AccelOpsClass *cpus_accel;
> +const AccelOpsClass *cpus_accel;
>   
>   void cpu_synchronize_all_states(void)
>   {
> diff --git a/target/i386/kvm/kvm-stub.c b/target/i386/kvm/kvm-stub.c
> index f6e7e4466e..71631e560d 100644
> --- a/target/i386/kvm/kvm-stub.c
> +++ b/target/i386/kvm/kvm-stub.c
> @@ -12,6 +12,7 @@
>   #include "qemu/osdep.h"
>   #include "cpu.h"
>   #include "kvm_i386.h"
> +#include "qapi/error.h"
>   
>   #ifndef __OPTIMIZE__
>   bool kvm_has_smm(void)
> @@ -44,3 +45,11 @@ bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp)
>   {
>       abort();
>   }
> +
> +CpuidEntryList *qmp_x_query_x86_cpuid(Error **errp);
> +
> +CpuidEntryList *qmp_x_query_x86_cpuid(Error **errp)
> +{
> +    error_setg(errp, "Not implemented in --disable-kvm configuration");
> +    return NULL;
> +}
> diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
> index 2c8feb4a6f..eb73869039 100644
> --- a/target/i386/kvm/kvm.c
> +++ b/target/i386/kvm/kvm.c
> @@ -20,11 +20,13 @@
>   
>   #include <linux/kvm.h>
>   #include "standard-headers/asm-x86/kvm_para.h"
> +#include "qapi/qapi-commands-machine-target.h"
>   
>   #include "cpu.h"
>   #include "host-cpu.h"
>   #include "sysemu/sysemu.h"
>   #include "sysemu/hw_accel.h"
> +#include "sysemu/accel-ops.h"
>   #include "sysemu/kvm_int.h"
>   #include "sysemu/runstate.h"
>   #include "kvm_i386.h"
> @@ -1565,6 +1567,44 @@ static Error *invtsc_mig_blocker;
>   
>   #define KVM_MAX_CPUID_ENTRIES  100
>   
> +struct kvm_cpuid2 *cpuid_data_cached;
> +
> +
> +CpuidEntryList *qmp_x_query_x86_cpuid(Error **errp)
> +{
> +    int i;
> +    struct kvm_cpuid_entry2 *kvm_entry;
> +    CpuidEntryList *head = NULL, **tail = &head;
> +    CpuidEntry *entry;
> +
> +    if (!kvm_enabled()) {
> +        error_setg(errp, "Not implemented for non-kvm accel");
> +        return NULL;
> +    }
> +
> +    if (!cpuid_data_cached) {
> +        error_setg(errp, "VCPU was not initialized yet");
> +        return NULL;
> +    }
> +
> +    for (i = 0; i < cpuid_data_cached->nent; ++i) {
> +        kvm_entry = &cpuid_data_cached->entries[i];
> +        entry = g_malloc0(sizeof(*entry));
> +        entry->in_eax = kvm_entry->function;
> +        if (kvm_entry->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX) {
> +            entry->in_ecx = kvm_entry->index;
> +            entry->has_in_ecx = true;
> +        }
> +        entry->eax = kvm_entry->eax;
> +        entry->ebx = kvm_entry->ebx;
> +        entry->ecx = kvm_entry->ecx;
> +        entry->edx = kvm_entry->edx;
> +        QAPI_LIST_APPEND(tail, entry);
> +    }
> +
> +    return head;
> +}
> +
>   int kvm_arch_init_vcpu(CPUState *cs)
>   {
>       struct {
> @@ -1981,6 +2021,10 @@ int kvm_arch_init_vcpu(CPUState *cs)
>       if (r) {
>           goto fail;
>       }
> +    if (!cpuid_data_cached) {
> +        cpuid_data_cached = g_malloc0(sizeof(cpuid_data));
> +        memcpy(cpuid_data_cached, &cpuid_data, sizeof(cpuid_data));
> +    }
>   
>       if (has_xsave) {
>           env->xsave_buf_len = sizeof(struct kvm_xsave);
> diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c
> index 7f103ea3fd..94d9184a84 100644
> --- a/tests/qtest/qmp-cmd-test.c
> +++ b/tests/qtest/qmp-cmd-test.c
> @@ -54,6 +54,7 @@ static int query_error_class(const char *cmd)
>           /* Only valid with accel=tcg */
>           { "x-query-jit", ERROR_CLASS_GENERIC_ERROR },
>           { "x-query-opcount", ERROR_CLASS_GENERIC_ERROR },
> +        { "x-query-x86-cpuid", ERROR_CLASS_GENERIC_ERROR },
>           { NULL, -1 }
>       };
>       int i;
> 


-- 
Best regards,
Vladimir

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v17] qapi: introduce 'x-query-x86-cpuid' QMP command.
  2022-02-17 15:39 ` Vladimir Sementsov-Ogievskiy
@ 2022-02-17 16:08     ` Markus Armbruster
  0 siblings, 0 replies; 6+ messages in thread
From: Markus Armbruster @ 2022-02-17 16:08 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy
  Cc: qemu-devel, kvm, lvivier, thuth, mtosatti, richard.henderson,
	pbonzini, armbru, eblake, wangyanan55, f4bug, marcel.apfelbaum,
	eduardo, valery.vdovin.s, den, Valeriy Vdovin

Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> writes:

> Ping :) Any hope that we will merge it one day?)

Up to the x86 CPU maintainers: Paolo & Marcelo.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v17] qapi: introduce 'x-query-x86-cpuid' QMP command.
@ 2022-02-17 16:08     ` Markus Armbruster
  0 siblings, 0 replies; 6+ messages in thread
From: Markus Armbruster @ 2022-02-17 16:08 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy
  Cc: lvivier, eduardo, thuth, kvm, valery.vdovin.s, mtosatti,
	richard.henderson, qemu-devel, armbru, wangyanan55,
	Valeriy Vdovin, den, pbonzini, eblake, f4bug

Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> writes:

> Ping :) Any hope that we will merge it one day?)

Up to the x86 CPU maintainers: Paolo & Marcelo.



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-02-17 16:11 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-21 16:39 [PATCH v17] qapi: introduce 'x-query-x86-cpuid' QMP command Vladimir Sementsov-Ogievskiy
2022-01-24 15:05 ` Markus Armbruster
2022-01-24 15:05   ` Markus Armbruster
2022-02-17 15:39 ` Vladimir Sementsov-Ogievskiy
2022-02-17 16:08   ` Markus Armbruster
2022-02-17 16:08     ` Markus Armbruster

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.