[libvirt] [PATCH 00/36] CPU driver enhancements and MSR features

In addition to usual CPUID bits, some CPU features started to be reported in IA32_ARCH_CAPABILITIES MSR. This series adds support for such CPU features. However, the last patch which actually adds definitions for some MSR features to the cpu_map should not be pushed yet as the QEMU interface for MSR features is not complete yet. If a domain with some MSR features enabled would be started, all of them would be marked as disabled in the live domain configuration (even though they were actually enabled by QEMU) and they would disappear during migration. Jiri Denemark (36): domaincapstest: Test QEMU 3.1.0 cputest: Add data for Intel(R) Xeon(R) Platinum 8268 CPU cpu_map: Add Cascadelake-Server CPU model cpu_x86: Do not cache microcode version cpu_x86: Require <cpuid> within <feature> in CPU map cpu_x86: Introduce virCPUx86DataItem container struct cpu_x86: Rename virCPUx86Vendor.cpuid cpu_x86: Rename virCPUx86DataItem variables cpu_x86: Rename x86DataCpuidNext function cpu_x86: Rename x86DataCpuid cpu_x86: Rename virCPUx86CPUIDSorter cpu_x86: Rename virCPUx86DataAddCPUIDInt cpu_x86: Rename virCPUx86DataAddCPUID cpu_x86: Rename virCPUx86VendorToCPUID cpu_x86: Simplify x86DataAdd cpu_x86: Introduce virCPUx86DataCmp cpu_x86: Make x86cpuidSetBits more general cpu_x86: Make x86cpuidClearBits more general cpu_x86: Make x86cpuidAndBits more general cpu_x86: Make x86cpuidMatchMasked more general cpu_x86: Make x86cpuidMatch more general cpu_x86: Store virCPUx86DataItem content in union cpu_x86: Add support for storing MSR features in CPU map cpu_x86: Move *CheckFeature functions cputest: Drop support for old QEMU from cpu-parse.sh cputest: Generalize function names in cpu-cpuid.py cputest: Fix comparison in checkCPUIDFeature in cpu-cpuid.py cputest: Rename in_e[ac]x as e[ac]x_in in cpu-cpuid.py cputest: Prepare cpu-cpuid.py for MSR features cputest: Generalize feature parsing in cpu-cpuid.py cputest: Add support for MSR features to cpu-gather.sh cputest: Add support for MSR features to cpu-parse.sh cputest: Add support for MSR features to cpu-cpuid.py vircpuhost: Add support for reading MSRs cpu_x86: Read CPU features from IA32_ARCH_CAPABILITIES MSR cpu_map: Introduce IA32_ARCH_CAPABILITIES MSR features src/cpu/cpu_x86.c | 807 ++++++++++++------ src/cpu/cpu_x86.h | 4 +- src/cpu/cpu_x86_data.h | 27 +- src/cpu_map/index.xml | 1 + src/cpu_map/x86_Cascadelake-Server.xml | 82 ++ src/cpu_map/x86_features.xml | 17 + src/libvirt_private.syms | 3 +- src/libxl/libxl_capabilities.c | 9 +- src/qemu/qemu_monitor_json.c | 7 +- src/util/virhostcpu.c | 80 ++ src/util/virhostcpu.h | 3 + tests/cputest.c | 1 + tests/cputestdata/cpu-cpuid.py | 414 +++------ tests/cputestdata/cpu-gather.sh | 49 +- tests/cputestdata/cpu-parse.sh | 12 +- .../x86_64-cpuid-Core-i7-7600U-enabled.xml | 1 + .../x86_64-cpuid-Core-i7-7600U-json.xml | 1 + ...6_64-cpuid-Xeon-Platinum-8268-disabled.xml | 7 + ...86_64-cpuid-Xeon-Platinum-8268-enabled.xml | 9 + .../x86_64-cpuid-Xeon-Platinum-8268-guest.xml | 35 + .../x86_64-cpuid-Xeon-Platinum-8268-host.xml | 36 + .../x86_64-cpuid-Xeon-Platinum-8268-json.xml | 13 + .../x86_64-cpuid-Xeon-Platinum-8268.json | 702 +++++++++++++++ .../x86_64-cpuid-Xeon-Platinum-8268.sig | 4 + .../x86_64-cpuid-Xeon-Platinum-8268.xml | 55 ++ .../qemu_3.1.0.x86_64.xml | 155 ++++ .../qemu_4.0.0.x86_64.xml | 2 + tests/domaincapstest.c | 4 + 28 files changed, 1954 insertions(+), 586 deletions(-) create mode 100644 src/cpu_map/x86_Cascadelake-Server.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.json create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.sig create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml create mode 100644 tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml -- 2.21.0

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- .../qemu_3.1.0.x86_64.xml | 153 ++++++++++++++++++ tests/domaincapstest.c | 4 + 2 files changed, 157 insertions(+) create mode 100644 tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml diff --git a/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml b/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml new file mode 100644 index 0000000000..f3a33aee98 --- /dev/null +++ b/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml @@ -0,0 +1,153 @@ +<domainCapabilities> + <path>/usr/bin/qemu-system-x86_64</path> + <domain>kvm</domain> + <machine>pc-i440fx-3.1</machine> + <arch>x86_64</arch> + <vcpu max='255'/> + <iothreads supported='yes'/> + <os supported='yes'> + <loader supported='yes'> + <value>/usr/share/AAVMF/AAVMF_CODE.fd</value> + <value>/usr/share/AAVMF/AAVMF32_CODE.fd</value> + <value>/usr/share/OVMF/OVMF_CODE.fd</value> + <enum name='type'> + <value>rom</value> + <value>pflash</value> + </enum> + <enum name='readonly'> + <value>yes</value> + <value>no</value> + </enum> + </loader> + </os> + <cpu> + <mode name='host-passthrough' supported='yes'/> + <mode name='host-model' supported='yes'> + <model fallback='forbid'>Skylake-Client-IBRS</model> + <vendor>Intel</vendor> + <feature policy='require' name='ss'/> + <feature policy='require' name='vmx'/> + <feature policy='require' name='hypervisor'/> + <feature policy='require' name='tsc_adjust'/> + <feature policy='require' name='clflushopt'/> + <feature policy='require' name='umip'/> + <feature policy='require' name='arch-capabilities'/> + <feature policy='require' name='xsaves'/> + <feature policy='require' name='pdpe1gb'/> + <feature policy='require' name='invtsc'/> + </mode> + <mode name='custom' supported='yes'> + <model usable='yes'>qemu64</model> + <model usable='yes'>qemu32</model> + <model usable='no'>phenom</model> + <model usable='yes'>pentium3</model> + <model usable='yes'>pentium2</model> + <model usable='yes'>pentium</model> + <model usable='yes'>n270</model> + <model usable='yes'>kvm64</model> + <model usable='yes'>kvm32</model> + <model usable='yes'>coreduo</model> + <model usable='yes'>core2duo</model> + <model usable='no'>athlon</model> + <model usable='yes'>Westmere-IBRS</model> + <model usable='yes'>Westmere</model> + <model usable='no'>Skylake-Server-IBRS</model> + <model usable='no'>Skylake-Server</model> + <model usable='yes'>Skylake-Client-IBRS</model> + <model usable='yes'>Skylake-Client</model> + <model usable='yes'>SandyBridge-IBRS</model> + <model usable='yes'>SandyBridge</model> + <model usable='yes'>Penryn</model> + <model usable='no'>Opteron_G5</model> + <model usable='no'>Opteron_G4</model> + <model usable='no'>Opteron_G3</model> + <model usable='yes'>Opteron_G2</model> + <model usable='yes'>Opteron_G1</model> + <model usable='yes'>Nehalem-IBRS</model> + <model usable='yes'>Nehalem</model> + <model usable='yes'>IvyBridge-IBRS</model> + <model usable='yes'>IvyBridge</model> + <model usable='no'>Icelake-Server</model> + <model usable='no'>Icelake-Client</model> + <model usable='yes'>Haswell-noTSX-IBRS</model> + <model usable='yes'>Haswell-noTSX</model> + <model usable='yes'>Haswell-IBRS</model> + <model usable='yes'>Haswell</model> + <model usable='no'>EPYC-IBPB</model> + <model usable='no'>EPYC</model> + <model usable='yes'>Conroe</model> + <model usable='yes'>Broadwell-noTSX-IBRS</model> + <model usable='yes'>Broadwell-noTSX</model> + <model usable='yes'>Broadwell-IBRS</model> + <model usable='yes'>Broadwell</model> + <model usable='yes'>486</model> + </mode> + </cpu> + <devices> + <disk supported='yes'> + <enum name='diskDevice'> + <value>disk</value> + <value>cdrom</value> + <value>floppy</value> + <value>lun</value> + </enum> + <enum name='bus'> + <value>ide</value> + <value>fdc</value> + <value>scsi</value> + <value>virtio</value> + <value>usb</value> + <value>sata</value> + </enum> + <enum name='model'> + <value>virtio</value> + <value>virtio-transitional</value> + <value>virtio-non-transitional</value> + </enum> + </disk> + <graphics supported='yes'> + <enum name='type'> + <value>sdl</value> + <value>vnc</value> + <value>spice</value> + </enum> + </graphics> + <video supported='yes'> + <enum name='modelType'> + <value>vga</value> + <value>cirrus</value> + <value>vmvga</value> + <value>qxl</value> + <value>virtio</value> + </enum> + </video> + <hostdev supported='yes'> + <enum name='mode'> + <value>subsystem</value> + </enum> + <enum name='startupPolicy'> + <value>default</value> + <value>mandatory</value> + <value>requisite</value> + <value>optional</value> + </enum> + <enum name='subsysType'> + <value>usb</value> + <value>pci</value> + <value>scsi</value> + </enum> + <enum name='capsType'/> + <enum name='pciBackend'> + <value>default</value> + <value>kvm</value> + <value>vfio</value> + </enum> + </hostdev> + </devices> + <features> + <gic supported='no'/> + <vmcoreinfo supported='yes'/> + <genid supported='yes'/> + <sev supported='no'/> + </features> +</domainCapabilities> diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index 2cccfbc8e2..77c5fcfb73 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -432,6 +432,10 @@ mymain(void) "/usr/bin/qemu-system-s390x", NULL, "s390x", VIR_DOMAIN_VIRT_KVM); + DO_TEST_QEMU("3.1.0", "caps_3.1.0", + "/usr/bin/qemu-system-x86_64", NULL, + "x86_64", VIR_DOMAIN_VIRT_KVM); + DO_TEST_QEMU("4.0.0", "caps_4.0.0", "/usr/bin/qemu-system-x86_64", NULL, "x86_64", VIR_DOMAIN_VIRT_KVM); -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:05AM +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- .../qemu_3.1.0.x86_64.xml | 153 ++++++++++++++++++ tests/domaincapstest.c | 4 + 2 files changed, 157 insertions(+) create mode 100644 tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 1 + ...6_64-cpuid-Xeon-Platinum-8268-disabled.xml | 7 + ...86_64-cpuid-Xeon-Platinum-8268-enabled.xml | 8 + .../x86_64-cpuid-Xeon-Platinum-8268-guest.xml | 35 + .../x86_64-cpuid-Xeon-Platinum-8268-host.xml | 36 + .../x86_64-cpuid-Xeon-Platinum-8268-json.xml | 13 + .../x86_64-cpuid-Xeon-Platinum-8268.json | 702 ++++++++++++++++++ .../x86_64-cpuid-Xeon-Platinum-8268.sig | 4 + .../x86_64-cpuid-Xeon-Platinum-8268.xml | 54 ++ 9 files changed, 860 insertions(+) create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.json create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.sig create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml diff --git a/tests/cputest.c b/tests/cputest.c index 9a618c2242..1ade8091b2 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -1286,6 +1286,7 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7540", JSON_MODELS); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-5115", JSON_MODELS); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-6148", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Platinum-8268", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-W3520", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-X5460", JSON_NONE); diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-disabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-disabled.xml new file mode 100644 index 0000000000..32522eb9af --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-disabled.xml @@ -0,0 +1,7 @@ +<!-- Features disabled by QEMU --> +<cpudata arch='x86'> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0804c1fc' edx='0xb0600000'/> + <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x02001000' ecx='0x00000010' edx='0x28000000'/> + <cpuid eax_in='0x0000000f' ecx_in='0x01' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000006'/> + <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/> +</cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml new file mode 100644 index 0000000000..434ac1956a --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml @@ -0,0 +1,8 @@ +<!-- Features enabled by QEMU --> +<cpudata arch='x86'> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0xf7fa3203' edx='0x0f8bfbff'/> + <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0xd19f4fbb' ecx='0x0000080c' edx='0x84000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/> +</cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml new file mode 100644 index 0000000000..6991b40af8 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml @@ -0,0 +1,35 @@ +<cpu mode='custom' match='exact'> + <model fallback='forbid'>Skylake-Server-IBRS</model> + <vendor>Intel</vendor> + <feature policy='require' name='ds'/> + <feature policy='require' name='acpi'/> + <feature policy='require' name='ss'/> + <feature policy='require' name='ht'/> + <feature policy='require' name='tm'/> + <feature policy='require' name='pbe'/> + <feature policy='require' name='dtes64'/> + <feature policy='require' name='monitor'/> + <feature policy='require' name='ds_cpl'/> + <feature policy='require' name='vmx'/> + <feature policy='require' name='smx'/> + <feature policy='require' name='est'/> + <feature policy='require' name='tm2'/> + <feature policy='require' name='xtpr'/> + <feature policy='require' name='pdcm'/> + <feature policy='require' name='dca'/> + <feature policy='require' name='osxsave'/> + <feature policy='require' name='tsc_adjust'/> + <feature policy='require' name='cmt'/> + <feature policy='require' name='clflushopt'/> + <feature policy='require' name='intel-pt'/> + <feature policy='require' name='pku'/> + <feature policy='require' name='ospke'/> + <feature policy='require' name='avx512vnni'/> + <feature policy='require' name='stibp'/> + <feature policy='require' name='arch-capabilities'/> + <feature policy='require' name='ssbd'/> + <feature policy='require' name='xsaves'/> + <feature policy='require' name='mbm_total'/> + <feature policy='require' name='mbm_local'/> + <feature policy='require' name='invtsc'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml new file mode 100644 index 0000000000..90ac6edb14 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml @@ -0,0 +1,36 @@ +<cpu> + <arch>x86_64</arch> + <model>Skylake-Server-IBRS</model> + <vendor>Intel</vendor> + <feature name='ds'/> + <feature name='acpi'/> + <feature name='ss'/> + <feature name='ht'/> + <feature name='tm'/> + <feature name='pbe'/> + <feature name='dtes64'/> + <feature name='monitor'/> + <feature name='ds_cpl'/> + <feature name='vmx'/> + <feature name='smx'/> + <feature name='est'/> + <feature name='tm2'/> + <feature name='xtpr'/> + <feature name='pdcm'/> + <feature name='dca'/> + <feature name='osxsave'/> + <feature name='tsc_adjust'/> + <feature name='cmt'/> + <feature name='clflushopt'/> + <feature name='intel-pt'/> + <feature name='pku'/> + <feature name='ospke'/> + <feature name='avx512vnni'/> + <feature name='stibp'/> + <feature name='arch-capabilities'/> + <feature name='ssbd'/> + <feature name='xsaves'/> + <feature name='mbm_total'/> + <feature name='mbm_local'/> + <feature name='invtsc'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml new file mode 100644 index 0000000000..12431de213 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml @@ -0,0 +1,13 @@ +<cpu mode='custom' match='exact'> + <model fallback='forbid'>Skylake-Server-IBRS</model> + <vendor>Intel</vendor> + <feature policy='require' name='ss'/> + <feature policy='require' name='hypervisor'/> + <feature policy='require' name='tsc_adjust'/> + <feature policy='require' name='clflushopt'/> + <feature policy='require' name='umip'/> + <feature policy='require' name='pku'/> + <feature policy='require' name='avx512vnni'/> + <feature policy='require' name='ssbd'/> + <feature policy='require' name='xsaves'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.json b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.json new file mode 100644 index 0000000000..71451f893d --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.json @@ -0,0 +1,702 @@ +{ + "return": { + "model": { + "name": "base", + "props": { + "phys-bits": 0, + "core-id": -1, + "xlevel": 2147483656, + "cmov": true, + "ia64": false, + "ssb-no": false, + "aes": true, + "mmx": true, + "rdpid": false, + "arat": true, + "gfni": false, + "ibrs-all": true, + "pause-filter": false, + "xsavec": true, + "intel-pt": false, + "hv-frequencies": false, + "tsc-frequency": 0, + "xd": true, + "hv-vendor-id": "", + "kvm-asyncpf": true, + "kvm_asyncpf": true, + "perfctr_core": false, + "perfctr-core": false, + "mpx": true, + "pbe": false, + "decodeassists": false, + "avx512cd": true, + "sse4_1": true, + "sse4.1": true, + "sse4-1": true, + "family": 6, + "legacy-cache": true, + "vmware-cpuid-freq": true, + "wbnoinvd": false, + "avx512f": true, + "msr": true, + "mce": true, + "mca": true, + "hv-runtime": false, + "xcrypt": false, + "thread-id": -1, + "min-level": 13, + "xgetbv1": true, + "cid": false, + "hv-relaxed": false, + "hv-crash": false, + "ds": false, + "fxsr": true, + "xsaveopt": true, + "xtpr": false, + "hv-evmcs": false, + "avx512vl": true, + "avx512-vpopcntdq": false, + "phe": false, + "extapic": false, + "3dnowprefetch": true, + "avx512vbmi2": false, + "cr8legacy": false, + "cpuid-0xb": true, + "xcrypt-en": false, + "kvm_pv_eoi": true, + "apic-id": 4294967295, + "rsba": false, + "pn": false, + "dca": false, + "vendor": "GenuineIntel", + "hv-ipi": false, + "pku": true, + "smx": false, + "cmp_legacy": false, + "cmp-legacy": false, + "node-id": -1, + "avx512-4fmaps": false, + "vmcb_clean": false, + "vmcb-clean": false, + "3dnowext": false, + "amd-no-ssb": false, + "hle": true, + "npt": false, + "rdctl-no": true, + "memory": "/machine/unattached/system[0]", + "clwb": true, + "lbrv": false, + "adx": true, + "ss": true, + "pni": true, + "svm_lock": false, + "svm-lock": false, + "pfthreshold": false, + "smep": true, + "smap": true, + "x2apic": true, + "avx512vbmi": false, + "avx512vnni": true, + "hv-stimer": false, + "x-hv-synic-kvm-only": true, + "i64": true, + "flushbyasid": false, + "f16c": true, + "ace2-en": false, + "pat": true, + "pae": true, + "sse": true, + "phe-en": false, + "kvm_nopiodelay": true, + "kvm-nopiodelay": true, + "tm": false, + "kvmclock-stable-bit": true, + "hypervisor": true, + "socket-id": -1, + "pcommit": false, + "syscall": true, + "level": 13, + "avx512dq": true, + "x-migrate-smi-count": false, + "svm": false, + "full-cpuid-auto-level": true, + "hv-reset": false, + "invtsc": false, + "sse3": true, + "sse2": true, + "ssbd": true, + "est": false, + "avx512ifma": false, + "tm2": false, + "kvm-pv-ipi": true, + "kvm-pv-eoi": true, + "cx8": true, + "cldemote": false, + "hv-reenlightenment": false, + "kvm_mmu": false, + "kvm-mmu": false, + "sse4_2": true, + "sse4.2": true, + "sse4-2": true, + "pge": true, + "fill-mtrr-mask": true, + "avx512bitalg": false, + "nodeid_msr": false, + "pdcm": false, + "movbe": true, + "model": 85, + "nrip_save": false, + "nrip-save": false, + "kvm_pv_unhalt": true, + "ssse3": true, + "sse4a": false, + "invpcid": true, + "pdpe1gb": true, + "tsc-deadline": true, + "skip-l1dfl-vmentry": true, + "fma": true, + "cx16": true, + "de": true, + "enforce": false, + "stepping": 6, + "xsave": true, + "clflush": true, + "skinit": false, + "tsc": true, + "tce": false, + "fpu": true, + "ibs": false, + "ds_cpl": false, + "ds-cpl": false, + "host-phys-bits": true, + "fma4": false, + "la57": false, + "osvw": false, + "check": true, + "hv-spinlocks": -1, + "pmu": false, + "pmm": false, + "apic": true, + "spec-ctrl": true, + "min-xlevel2": 0, + "tsc-adjust": true, + "tsc_adjust": true, + "kvm-steal-time": true, + "kvm_steal_time": true, + "kvmclock": true, + "l3-cache": true, + "lwp": false, + "amd-ssbd": false, + "ibpb": false, + "xop": false, + "avx": true, + "ace2": false, + "avx512bw": true, + "acpi": false, + "hv-vapic": false, + "fsgsbase": true, + "ht": false, + "nx": true, + "pclmulqdq": true, + "mmxext": false, + "vaes": false, + "popcnt": true, + "xsaves": true, + "tcg-cpuid": true, + "lm": true, + "umip": true, + "pse": true, + "avx2": true, + "sep": true, + "pclmuldq": true, + "virt-ssbd": false, + "x-hv-max-vps": -1, + "nodeid-msr": false, + "kvm": true, + "misalignsse": false, + "min-xlevel": 2147483656, + "kvm-pv-unhalt": true, + "bmi2": true, + "bmi1": true, + "realized": false, + "tsc_scale": false, + "tsc-scale": false, + "topoext": false, + "hv-vpindex": false, + "xlevel2": 0, + "clflushopt": true, + "kvm-no-smi-migration": false, + "monitor": false, + "avx512er": false, + "pmm-en": false, + "pcid": true, + "arch-capabilities": false, + "3dnow": false, + "erms": true, + "lahf-lm": true, + "lahf_lm": true, + "vpclmulqdq": false, + "fxsr-opt": false, + "hv-synic": false, + "xstore": false, + "fxsr_opt": false, + "kvm-hint-dedicated": false, + "rtm": true, + "lmce": true, + "hv-time": false, + "perfctr-nb": false, + "perfctr_nb": false, + "ffxsr": false, + "hv-tlbflush": false, + "rdrand": true, + "rdseed": true, + "avx512-4vnniw": false, + "vmx": false, + "vme": true, + "dtes64": false, + "mtrr": true, + "rdtscp": true, + "pse36": true, + "kvm-pv-tlb-flush": true, + "tbm": false, + "wdt": false, + "pause_filter": false, + "sha-ni": false, + "model-id": "Intel(R) Xeon(R) Platinum 8268 CPU @ 2.90GHz", + "abm": true, + "avx512pf": false, + "xstore-en": false + } + } + }, + "id": "model-expansion" +} + +{ + "return": [ + { + "name": "max", + "typename": "max-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": false + }, + { + "name": "host", + "typename": "host-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": false + }, + { + "name": "base", + "typename": "base-x86_64-cpu", + "unavailable-features": [], + "static": true, + "migration-safe": true + }, + { + "name": "qemu64", + "typename": "qemu64-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "qemu32", + "typename": "qemu32-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "phenom", + "typename": "phenom-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "fxsr-opt", + "3dnowext", + "3dnow", + "sse4a", + "npt" + ], + "static": false, + "migration-safe": true + }, + { + "name": "pentium3", + "typename": "pentium3-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "pentium2", + "typename": "pentium2-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "pentium", + "typename": "pentium-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "n270", + "typename": "n270-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "kvm64", + "typename": "kvm64-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "kvm32", + "typename": "kvm32-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "cpu64-rhel6", + "typename": "cpu64-rhel6-x86_64-cpu", + "unavailable-features": [ + "sse4a" + ], + "static": false, + "migration-safe": true + }, + { + "name": "coreduo", + "typename": "coreduo-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "core2duo", + "typename": "core2duo-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "athlon", + "typename": "athlon-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "3dnowext", + "3dnow" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Westmere-IBRS", + "typename": "Westmere-IBRS-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Westmere", + "typename": "Westmere-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Skylake-Server-IBRS", + "typename": "Skylake-Server-IBRS-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Skylake-Server", + "typename": "Skylake-Server-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Skylake-Client-IBRS", + "typename": "Skylake-Client-IBRS-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Skylake-Client", + "typename": "Skylake-Client-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "SandyBridge-IBRS", + "typename": "SandyBridge-IBRS-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "SandyBridge", + "typename": "SandyBridge-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Penryn", + "typename": "Penryn-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Opteron_G5", + "typename": "Opteron_G5-x86_64-cpu", + "unavailable-features": [ + "sse4a", + "misalignsse", + "xop", + "fma4", + "tbm" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Opteron_G4", + "typename": "Opteron_G4-x86_64-cpu", + "unavailable-features": [ + "sse4a", + "misalignsse", + "xop", + "fma4" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Opteron_G3", + "typename": "Opteron_G3-x86_64-cpu", + "unavailable-features": [ + "sse4a", + "misalignsse" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Opteron_G2", + "typename": "Opteron_G2-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Opteron_G1", + "typename": "Opteron_G1-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Nehalem-IBRS", + "typename": "Nehalem-IBRS-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Nehalem", + "typename": "Nehalem-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "KnightsMill", + "typename": "KnightsMill-x86_64-cpu", + "unavailable-features": [ + "avx512pf", + "avx512er", + "avx512-vpopcntdq", + "avx512-4vnniw", + "avx512-4fmaps" + ], + "static": false, + "migration-safe": true + }, + { + "name": "IvyBridge-IBRS", + "typename": "IvyBridge-IBRS-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "IvyBridge", + "typename": "IvyBridge-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Icelake-Server", + "typename": "Icelake-Server-x86_64-cpu", + "unavailable-features": [ + "avx512vbmi", + "", + "avx512vbmi2", + "gfni", + "vaes", + "vpclmulqdq", + "avx512bitalg", + "avx512-vpopcntdq", + "la57", + "wbnoinvd" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Icelake-Client", + "typename": "Icelake-Client-x86_64-cpu", + "unavailable-features": [ + "avx512vbmi", + "", + "avx512vbmi2", + "gfni", + "vaes", + "vpclmulqdq", + "avx512bitalg", + "avx512-vpopcntdq", + "wbnoinvd" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Haswell-noTSX-IBRS", + "typename": "Haswell-noTSX-IBRS-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Haswell-noTSX", + "typename": "Haswell-noTSX-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Haswell-IBRS", + "typename": "Haswell-IBRS-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Haswell", + "typename": "Haswell-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "EPYC-IBPB", + "typename": "EPYC-IBPB-x86_64-cpu", + "unavailable-features": [ + "sha-ni", + "mmxext", + "fxsr-opt", + "cr8legacy", + "sse4a", + "misalignsse", + "osvw", + "ibpb" + ], + "static": false, + "migration-safe": true + }, + { + "name": "EPYC", + "typename": "EPYC-x86_64-cpu", + "unavailable-features": [ + "sha-ni", + "mmxext", + "fxsr-opt", + "cr8legacy", + "sse4a", + "misalignsse", + "osvw" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Conroe", + "typename": "Conroe-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Cascadelake-Server", + "typename": "Cascadelake-Server-x86_64-cpu", + "unavailable-features": [ + "" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Broadwell-noTSX-IBRS", + "typename": "Broadwell-noTSX-IBRS-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Broadwell-noTSX", + "typename": "Broadwell-noTSX-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Broadwell-IBRS", + "typename": "Broadwell-IBRS-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "Broadwell", + "typename": "Broadwell-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + }, + { + "name": "486", + "typename": "486-x86_64-cpu", + "unavailable-features": [], + "static": false, + "migration-safe": true + } + ], + "id": "definitions" +} diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.sig b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.sig new file mode 100644 index 0000000000..018161ff52 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.sig @@ -0,0 +1,4 @@ +050656 +family: 6 (0x06) +model: 85 (0x55) +stepping: 6 (0x06) diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml new file mode 100644 index 0000000000..75472d44fe --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml @@ -0,0 +1,54 @@ +<!-- Intel(R) Xeon(R) Platinum 8268 CPU @ 2.90GHz --> +<cpudata arch='x86'> + <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x00000016' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00050656' ebx='0x44400800' ecx='0x7ffefbff' edx='0xbfebfbff'/> + <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76036301' ebx='0x00f0b5ff' ecx='0x00000000' edx='0x00c30000'/> + <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x7c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x7c004122' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x7c004143' ebx='0x03c0003f' ecx='0x000003ff' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x7c0fc163' ebx='0x0280003f' ecx='0x0000cfff' edx='0x00000005'/> + <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x00002020'/> + <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000077' ebx='0x00000002' ecx='0x00000009' edx='0x00000000'/> + <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0xd39ffffb' ecx='0x00000818' edx='0xbc000400'/> + <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300404' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/> + <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000044'/> + <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000006' ebx='0x00000030' ecx='0x00000201' edx='0x00000044'/> + <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x000002ff' ebx='0x00000a88' ecx='0x00000a88' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000a08' ecx='0x00000100' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x02' eax='0x00000100' ebx='0x00000240' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x03' eax='0x00000040' ebx='0x000003c0' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x04' eax='0x00000040' ebx='0x00000400' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x05' eax='0x00000040' ebx='0x00000440' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x06' eax='0x00000200' ebx='0x00000480' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x07' eax='0x00000400' ebx='0x00000680' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x08' eax='0x00000080' ebx='0x00000000' ecx='0x00000001' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x09' eax='0x00000008' ebx='0x00000a80' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000e' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000f' ecx_in='0x00' eax='0x00000000' ebx='0x000000cf' ecx='0x00000000' edx='0x00000002'/> + <cpuid eax_in='0x0000000f' ecx_in='0x01' eax='0x00000000' ebx='0x0001a000' ecx='0x000000cf' edx='0x00000007'/> + <cpuid eax_in='0x00000010' ecx_in='0x00' eax='0x00000000' ebx='0x0000000a' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000010' ecx_in='0x01' eax='0x0000000a' ebx='0x00000600' ecx='0x00000004' edx='0x0000000f'/> + <cpuid eax_in='0x00000010' ecx_in='0x03' eax='0x00000059' ebx='0x00000000' ecx='0x00000004' edx='0x00000007'/> + <cpuid eax_in='0x00000011' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000012' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000013' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000014' ecx_in='0x00' eax='0x00000001' ebx='0x0000000f' ecx='0x00000007' edx='0x00000000'/> + <cpuid eax_in='0x00000014' ecx_in='0x01' eax='0x02490002' ebx='0x003f3fff' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000015' ecx_in='0x00' eax='0x00000002' ebx='0x000000e8' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000016' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/> + <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/> + <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x65746e49' ebx='0x2952286c' ecx='0x6f655820' edx='0x2952286e'/> + <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x616c5020' ebx='0x756e6974' ecx='0x3238206d' edx='0x43203836'/> + <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x40205550' ebx='0x392e3220' ecx='0x7a484730' edx='0x00000000'/> + <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/> + <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/> + <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x0000302e' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/> + <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/> +</cpudata> -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:06AM +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 1 + ...6_64-cpuid-Xeon-Platinum-8268-disabled.xml | 7 + ...86_64-cpuid-Xeon-Platinum-8268-enabled.xml | 8 + .../x86_64-cpuid-Xeon-Platinum-8268-guest.xml | 35 + .../x86_64-cpuid-Xeon-Platinum-8268-host.xml | 36 + .../x86_64-cpuid-Xeon-Platinum-8268-json.xml | 13 + .../x86_64-cpuid-Xeon-Platinum-8268.json | 702 ++++++++++++++++++ .../x86_64-cpuid-Xeon-Platinum-8268.sig | 4 + .../x86_64-cpuid-Xeon-Platinum-8268.xml | 54 ++ 9 files changed, 860 insertions(+) create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.json create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.sig create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Introduced in QEMU 3.1.0 by commit c7a88b52f62b30c04158eeb07f73e3f72221b6a8 Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu_map/index.xml | 1 + src/cpu_map/x86_Cascadelake-Server.xml | 82 +++++++++++++++++++ .../x86_64-cpuid-Xeon-Platinum-8268-guest.xml | 5 +- .../x86_64-cpuid-Xeon-Platinum-8268-host.xml | 5 +- .../x86_64-cpuid-Xeon-Platinum-8268-json.xml | 5 +- .../qemu_3.1.0.x86_64.xml | 1 + .../qemu_4.0.0.x86_64.xml | 1 + 7 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 src/cpu_map/x86_Cascadelake-Server.xml diff --git a/src/cpu_map/index.xml b/src/cpu_map/index.xml index dccda3919d..d1f4827934 100644 --- a/src/cpu_map/index.xml +++ b/src/cpu_map/index.xml @@ -46,6 +46,7 @@ <include filename="x86_Skylake-Client-IBRS.xml"/> <include filename="x86_Skylake-Server.xml"/> <include filename="x86_Skylake-Server-IBRS.xml"/> + <include filename="x86_Cascadelake-Server.xml"/> <include filename="x86_Icelake-Client.xml"/> <include filename="x86_Icelake-Server.xml"/> diff --git a/src/cpu_map/x86_Cascadelake-Server.xml b/src/cpu_map/x86_Cascadelake-Server.xml new file mode 100644 index 0000000000..7c7fc92c40 --- /dev/null +++ b/src/cpu_map/x86_Cascadelake-Server.xml @@ -0,0 +1,82 @@ +<cpus> + <model name='Cascadelake-Server'> + <signature family='6' model='85'/> <!-- 050654 --> + <vendor name='Intel'/> + <feature name='3dnowprefetch'/> + <feature name='abm'/> + <feature name='adx'/> + <feature name='aes'/> + <feature name='apic'/> + <feature name='arat'/> + <feature name='avx'/> + <feature name='avx2'/> + <feature name='avx512bw'/> + <feature name='avx512cd'/> + <feature name='avx512dq'/> + <feature name='avx512f'/> + <feature name='avx512vl'/> + <feature name='avx512vnni'/> + <feature name='bmi1'/> + <feature name='bmi2'/> + <feature name='clflush'/> + <feature name='clflushopt'/> + <feature name='clwb'/> + <feature name='cmov'/> + <feature name='cx16'/> + <feature name='cx8'/> + <feature name='de'/> + <feature name='erms'/> + <feature name='f16c'/> + <feature name='fma'/> + <feature name='fpu'/> + <feature name='fsgsbase'/> + <feature name='fxsr'/> + <feature name='hle'/> + <feature name='invpcid'/> + <feature name='lahf_lm'/> + <feature name='lm'/> + <feature name='mca'/> + <feature name='mce'/> + <feature name='mmx'/> + <feature name='movbe'/> + <feature name='mpx'/> + <feature name='msr'/> + <feature name='mtrr'/> + <feature name='nx'/> + <!-- 'ospke' is a dynamic feature and cannot be enabled manually + see QEMU's commit 9ccb9784b57 for more details --> + <feature name='pae'/> + <feature name='pat'/> + <feature name='pcid'/> + <feature name='pclmuldq'/> + <feature name='pdpe1gb'/> + <feature name='pge'/> + <feature name='pni'/> + <feature name='popcnt'/> + <feature name='pse'/> + <feature name='pse36'/> + <feature name='rdrand'/> + <feature name='rdseed'/> + <feature name='rdtscp'/> + <feature name='rtm'/> + <feature name='sep'/> + <feature name='smap'/> + <feature name='smep'/> + <feature name='spec-ctrl'/> + <feature name='ssbd'/> + <feature name='sse'/> + <feature name='sse2'/> + <feature name='sse4.1'/> + <feature name='sse4.2'/> + <feature name='ssse3'/> + <feature name='syscall'/> + <feature name='tsc'/> + <feature name='tsc-deadline'/> + <feature name='vme'/> + <feature name='x2apic'/> + <feature name='xgetbv1'/> + <feature name='xsave'/> + <feature name='xsavec'/> + <feature name='xsaveopt'/> + </model> +</cpus> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml index 6991b40af8..cc1fc90c45 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml @@ -1,5 +1,5 @@ <cpu mode='custom' match='exact'> - <model fallback='forbid'>Skylake-Server-IBRS</model> + <model fallback='forbid'>Cascadelake-Server</model> <vendor>Intel</vendor> <feature policy='require' name='ds'/> <feature policy='require' name='acpi'/> @@ -20,14 +20,11 @@ <feature policy='require' name='osxsave'/> <feature policy='require' name='tsc_adjust'/> <feature policy='require' name='cmt'/> - <feature policy='require' name='clflushopt'/> <feature policy='require' name='intel-pt'/> <feature policy='require' name='pku'/> <feature policy='require' name='ospke'/> - <feature policy='require' name='avx512vnni'/> <feature policy='require' name='stibp'/> <feature policy='require' name='arch-capabilities'/> - <feature policy='require' name='ssbd'/> <feature policy='require' name='xsaves'/> <feature policy='require' name='mbm_total'/> <feature policy='require' name='mbm_local'/> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml index 90ac6edb14..dfabdc57c7 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml @@ -1,6 +1,6 @@ <cpu> <arch>x86_64</arch> - <model>Skylake-Server-IBRS</model> + <model>Cascadelake-Server</model> <vendor>Intel</vendor> <feature name='ds'/> <feature name='acpi'/> @@ -21,14 +21,11 @@ <feature name='osxsave'/> <feature name='tsc_adjust'/> <feature name='cmt'/> - <feature name='clflushopt'/> <feature name='intel-pt'/> <feature name='pku'/> <feature name='ospke'/> - <feature name='avx512vnni'/> <feature name='stibp'/> <feature name='arch-capabilities'/> - <feature name='ssbd'/> <feature name='xsaves'/> <feature name='mbm_total'/> <feature name='mbm_local'/> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml index 12431de213..b7d12dced7 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml @@ -1,13 +1,10 @@ <cpu mode='custom' match='exact'> - <model fallback='forbid'>Skylake-Server-IBRS</model> + <model fallback='forbid'>Cascadelake-Server</model> <vendor>Intel</vendor> <feature policy='require' name='ss'/> <feature policy='require' name='hypervisor'/> <feature policy='require' name='tsc_adjust'/> - <feature policy='require' name='clflushopt'/> <feature policy='require' name='umip'/> <feature policy='require' name='pku'/> - <feature policy='require' name='avx512vnni'/> - <feature policy='require' name='ssbd'/> <feature policy='require' name='xsaves'/> </cpu> diff --git a/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml b/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml index f3a33aee98..f49da218e2 100644 --- a/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml +++ b/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml @@ -76,6 +76,7 @@ <model usable='no'>EPYC-IBPB</model> <model usable='no'>EPYC</model> <model usable='yes'>Conroe</model> + <model usable='no'>Cascadelake-Server</model> <model usable='yes'>Broadwell-noTSX-IBRS</model> <model usable='yes'>Broadwell-noTSX</model> <model usable='yes'>Broadwell-IBRS</model> diff --git a/tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml b/tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml index df66be9e29..84c33437a2 100644 --- a/tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml +++ b/tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml @@ -76,6 +76,7 @@ <model usable='no'>EPYC-IBPB</model> <model usable='no'>EPYC</model> <model usable='yes'>Conroe</model> + <model usable='no'>Cascadelake-Server</model> <model usable='yes'>Broadwell-noTSX-IBRS</model> <model usable='yes'>Broadwell-noTSX</model> <model usable='yes'>Broadwell-IBRS</model> -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:07AM +0200, Jiri Denemark wrote:
Introduced in QEMU 3.1.0 by commit c7a88b52f62b30c04158eeb07f73e3f72221b6a8
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu_map/index.xml | 1 + src/cpu_map/x86_Cascadelake-Server.xml | 82 +++++++++++++++++++ .../x86_64-cpuid-Xeon-Platinum-8268-guest.xml | 5 +- .../x86_64-cpuid-Xeon-Platinum-8268-host.xml | 5 +- .../x86_64-cpuid-Xeon-Platinum-8268-json.xml | 5 +- .../qemu_3.1.0.x86_64.xml | 1 + .../qemu_4.0.0.x86_64.xml | 1 + 7 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 src/cpu_map/x86_Cascadelake-Server.xml
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The microcode version checks are used to invalidate cached CPU data we get from QEMU. To minimize /proc/cpuinfo parsing the microcode version was only read when libvirtd started and cached for the daemon's lifetime. However, the CPU microcode can change anytime (updating the microcode package can automatically upload it to the CPU) and we need to stop caching it to avoid using stale CPU model data. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index add889c9a8..3b87386270 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -166,7 +166,6 @@ struct _virCPUx86Map { }; static virCPUx86MapPtr cpuMap; -static unsigned int microcodeVersion; int virCPUx86DriverOnceInit(void); VIR_ONCE_GLOBAL_INIT(virCPUx86Driver); @@ -1424,8 +1423,6 @@ virCPUx86DriverOnceInit(void) if (!(cpuMap = virCPUx86LoadMap())) return -1; - microcodeVersion = virHostCPUGetMicrocodeVersion(); - return 0; } @@ -2507,7 +2504,7 @@ virCPUx86GetHost(virCPUDefPtr cpu, goto cleanup; ret = x86DecodeCPUData(cpu, cpuData, models); - cpu->microcodeVersion = microcodeVersion; + cpu->microcodeVersion = virHostCPUGetMicrocodeVersion(); cleanup: virCPUx86DataFree(cpuData); -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:08AM +0200, Jiri Denemark wrote:
The microcode version checks are used to invalidate cached CPU data we get from QEMU. To minimize /proc/cpuinfo parsing the microcode version was only read when libvirtd started and cached for the daemon's lifetime. However, the CPU microcode can change anytime (updating the microcode package can automatically upload it to the CPU) and we need to stop caching it to avoid using stale CPU model data.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

A feature with no cpuid element is invalid and it should not be silently treated as a feature with all CPUID bits set to zero. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 3b87386270..3a8e3dd37f 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -924,6 +924,13 @@ x86FeatureParse(xmlXPathContextPtr ctxt, if (n < 0) goto cleanup; + if (n == 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Missing cpuid for feature %s"), + feature->name); + goto cleanup; + } + for (i = 0; i < n; i++) { ctxt->node = nodes[i]; if (x86ParseCPUID(ctxt, &cpuid) < 0) { -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:09AM +0200, Jiri Denemark wrote:
A feature with no cpuid element is invalid and it should not be silently treated as a feature with all CPUID bits set to zero.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 7 +++++++ 1 file changed, 7 insertions(+)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

On Mon, Apr 08, 2019 at 14:31:53 +0200, Ján Tomko wrote:
On Mon, Apr 08, 2019 at 10:42:09AM +0200, Jiri Denemark wrote:
A feature with no cpuid element is invalid and it should not be silently treated as a feature with all CPUID bits set to zero.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 7 +++++++ 1 file changed, 7 insertions(+)
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Hmm, I realized I didn't do a good job in ordering the first few patches in this series as patches 1, 4, and 5 are quite unrelated to the refactoring and MSR features. I'll just push them while waiting for reviews for the rest of the series. Thanks, Jirka.

The following patches introduce CPU features read from MSR in addition to those queried via CPUID instruction. Let's introduce a container struct which will be able to describe either feature type. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 312 ++++++++++++++++++--------------- src/cpu/cpu_x86.h | 2 +- src/cpu/cpu_x86_data.h | 9 +- src/libxl/libxl_capabilities.c | 8 +- src/qemu/qemu_monitor_json.c | 6 +- 5 files changed, 183 insertions(+), 154 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 3a8e3dd37f..c7937d55fd 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -45,7 +45,7 @@ typedef struct _virCPUx86Vendor virCPUx86Vendor; typedef virCPUx86Vendor *virCPUx86VendorPtr; struct _virCPUx86Vendor { char *name; - virCPUx86CPUID cpuid; + virCPUx86DataItem cpuid; }; typedef struct _virCPUx86Feature virCPUx86Feature; @@ -57,17 +57,19 @@ struct _virCPUx86Feature { }; +#define CPUID(...) { .cpuid = {__VA_ARGS__} } + #define KVM_FEATURE_DEF(Name, Eax_in, Eax) \ - static virCPUx86CPUID Name ## _cpuid[] = { \ - { .eax_in = Eax_in, .eax = Eax }, \ + static virCPUx86DataItem Name ## _data[] = { \ + CPUID(.eax_in = Eax_in, .eax = Eax), \ } #define KVM_FEATURE(Name) \ { \ .name = (char *) Name, \ .data = { \ - .len = ARRAY_CARDINALITY(Name ## _cpuid), \ - .data = Name ## _cpuid \ + .len = ARRAY_CARDINALITY(Name ## _data), \ + .items = Name ## _data, \ } \ } @@ -288,17 +290,17 @@ x86FeatureFindInternal(const char *name) static int virCPUx86CPUIDSorter(const void *a, const void *b) { - virCPUx86CPUID *da = (virCPUx86CPUID *) a; - virCPUx86CPUID *db = (virCPUx86CPUID *) b; + virCPUx86DataItemPtr da = (virCPUx86DataItemPtr) a; + virCPUx86DataItemPtr db = (virCPUx86DataItemPtr) b; - if (da->eax_in > db->eax_in) + if (da->cpuid.eax_in > db->cpuid.eax_in) return 1; - else if (da->eax_in < db->eax_in) + else if (da->cpuid.eax_in < db->cpuid.eax_in) return -1; - if (da->ecx_in > db->ecx_in) + if (da->cpuid.ecx_in > db->cpuid.ecx_in) return 1; - else if (da->ecx_in < db->ecx_in) + else if (da->cpuid.ecx_in < db->cpuid.ecx_in) return -1; return 0; @@ -306,7 +308,7 @@ virCPUx86CPUIDSorter(const void *a, const void *b) /* skips all zero CPUID leaves */ -static virCPUx86CPUID * +static virCPUx86DataItemPtr x86DataCpuidNext(virCPUx86DataIteratorPtr iterator) { const virCPUx86Data *data = iterator->data; @@ -315,24 +317,26 @@ x86DataCpuidNext(virCPUx86DataIteratorPtr iterator) return NULL; while (++iterator->pos < data->len) { - if (!x86cpuidMatch(data->data + iterator->pos, &cpuidNull)) - return data->data + iterator->pos; + virCPUx86DataItemPtr item = data->items + iterator->pos; + + if (!x86cpuidMatch(&item->cpuid, &cpuidNull)) + return item; } return NULL; } -static virCPUx86CPUID * +static virCPUx86DataItemPtr x86DataCpuid(const virCPUx86Data *data, - const virCPUx86CPUID *cpuid) + const virCPUx86DataItem *cpuid) { size_t i; for (i = 0; i < data->len; i++) { - if (data->data[i].eax_in == cpuid->eax_in && - data->data[i].ecx_in == cpuid->ecx_in) - return data->data + i; + if (data->items[i].cpuid.eax_in == cpuid->cpuid.eax_in && + data->items[i].cpuid.ecx_in == cpuid->cpuid.ecx_in) + return data->items + i; } return NULL; @@ -344,7 +348,7 @@ virCPUx86DataClear(virCPUx86Data *data) if (!data) return; - VIR_FREE(data->data); + VIR_FREE(data->items); } @@ -364,12 +368,12 @@ x86DataCopy(virCPUx86Data *dst, const virCPUx86Data *src) { size_t i; - if (VIR_ALLOC_N(dst->data, src->len) < 0) + if (VIR_ALLOC_N(dst->items, src->len) < 0) return -1; dst->len = src->len; for (i = 0; i < src->len; i++) - dst->data[i] = src->data[i]; + dst->items[i] = src->items[i]; return 0; } @@ -377,19 +381,19 @@ x86DataCopy(virCPUx86Data *dst, const virCPUx86Data *src) static int virCPUx86DataAddCPUIDInt(virCPUx86Data *data, - const virCPUx86CPUID *cpuid) + const virCPUx86DataItem *cpuid) { - virCPUx86CPUID *existing; + virCPUx86DataItemPtr existing; if ((existing = x86DataCpuid(data, cpuid))) { - x86cpuidSetBits(existing, cpuid); + x86cpuidSetBits(&existing->cpuid, &cpuid->cpuid); } else { - if (VIR_APPEND_ELEMENT_COPY(data->data, data->len, - *((virCPUx86CPUID *)cpuid)) < 0) + if (VIR_APPEND_ELEMENT_COPY(data->items, data->len, + *((virCPUx86DataItemPtr)cpuid)) < 0) return -1; - qsort(data->data, data->len, - sizeof(virCPUx86CPUID), virCPUx86CPUIDSorter); + qsort(data->items, data->len, + sizeof(virCPUx86DataItem), virCPUx86CPUIDSorter); } return 0; @@ -401,14 +405,14 @@ x86DataAdd(virCPUx86Data *data1, const virCPUx86Data *data2) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data2); - virCPUx86CPUID *cpuid1; - virCPUx86CPUID *cpuid2; + virCPUx86DataItemPtr cpuid1; + virCPUx86DataItemPtr cpuid2; while ((cpuid2 = x86DataCpuidNext(&iter))) { cpuid1 = x86DataCpuid(data1, cpuid2); if (cpuid1) { - x86cpuidSetBits(cpuid1, cpuid2); + x86cpuidSetBits(&cpuid1->cpuid, &cpuid2->cpuid); } else { if (virCPUx86DataAddCPUIDInt(data1, cpuid2) < 0) return -1; @@ -424,12 +428,12 @@ x86DataSubtract(virCPUx86Data *data1, const virCPUx86Data *data2) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1); - virCPUx86CPUID *cpuid1; - virCPUx86CPUID *cpuid2; + virCPUx86DataItemPtr cpuid1; + virCPUx86DataItemPtr cpuid2; while ((cpuid1 = x86DataCpuidNext(&iter))) { - cpuid2 = x86DataCpuid(data2, cpuid1); - x86cpuidClearBits(cpuid1, cpuid2); + if ((cpuid2 = x86DataCpuid(data2, cpuid1))) + x86cpuidClearBits(&cpuid1->cpuid, &cpuid2->cpuid); } } @@ -439,15 +443,15 @@ x86DataIntersect(virCPUx86Data *data1, const virCPUx86Data *data2) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1); - virCPUx86CPUID *cpuid1; - virCPUx86CPUID *cpuid2; + virCPUx86DataItemPtr cpuid1; + virCPUx86DataItemPtr cpuid2; while ((cpuid1 = x86DataCpuidNext(&iter))) { cpuid2 = x86DataCpuid(data2, cpuid1); if (cpuid2) - x86cpuidAndBits(cpuid1, cpuid2); + x86cpuidAndBits(&cpuid1->cpuid, &cpuid2->cpuid); else - x86cpuidClearBits(cpuid1, cpuid1); + x86cpuidClearBits(&cpuid1->cpuid, &cpuid1->cpuid); } } @@ -466,12 +470,12 @@ x86DataIsSubset(const virCPUx86Data *data, const virCPUx86Data *subset) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit((virCPUx86Data *)subset); - const virCPUx86CPUID *cpuid; - const virCPUx86CPUID *cpuidSubset; + const virCPUx86DataItem *cpuid; + const virCPUx86DataItem *cpuidSubset; while ((cpuidSubset = x86DataCpuidNext(&iter))) { if (!(cpuid = x86DataCpuid(data, cpuidSubset)) || - !x86cpuidMatchMasked(cpuid, cpuidSubset)) + !x86cpuidMatchMasked(&cpuid->cpuid, &cpuidSubset->cpuid)) return false; } @@ -506,14 +510,14 @@ static virCPUx86VendorPtr x86DataToVendor(const virCPUx86Data *data, virCPUx86MapPtr map) { - virCPUx86CPUID *cpuid; + virCPUx86DataItemPtr cpuid; size_t i; for (i = 0; i < map->nvendors; i++) { virCPUx86VendorPtr vendor = map->vendors[i]; if ((cpuid = x86DataCpuid(data, &vendor->cpuid)) && - x86cpuidMatchMasked(cpuid, &vendor->cpuid)) { - x86cpuidClearBits(cpuid, &vendor->cpuid); + x86cpuidMatchMasked(&cpuid->cpuid, &vendor->cpuid.cpuid)) { + x86cpuidClearBits(&cpuid->cpuid, &vendor->cpuid.cpuid); return vendor; } } @@ -524,8 +528,10 @@ x86DataToVendor(const virCPUx86Data *data, static int virCPUx86VendorToCPUID(const char *vendor, - virCPUx86CPUID *cpuid) + virCPUx86DataItemPtr data) { + virCPUx86CPUIDPtr cpuid = &data->cpuid; + if (strlen(vendor) != VENDOR_STRING_LENGTH) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid CPU vendor string '%s'"), vendor); @@ -598,14 +604,16 @@ x86DataToSignatureFull(const virCPUx86Data *data, unsigned int *model, unsigned int *stepping) { - virCPUx86CPUID leaf1 = { .eax_in = 0x1 }; - virCPUx86CPUID *cpuid; + virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1); + virCPUx86DataItemPtr item; + virCPUx86CPUIDPtr cpuid; *family = *model = *stepping = 0; - if (!(cpuid = x86DataCpuid(data, &leaf1))) + if (!(item = x86DataCpuid(data, &leaf1))) return; + cpuid = &item->cpuid; *family = ((cpuid->eax >> 20) & 0xff) + ((cpuid->eax >> 8) & 0xf); *model = ((cpuid->eax >> 12) & 0xf0) + ((cpuid->eax >> 4) & 0xf); *stepping = cpuid->eax & 0xf; @@ -618,13 +626,13 @@ x86DataToSignatureFull(const virCPUx86Data *data, static uint32_t x86DataToSignature(const virCPUx86Data *data) { - virCPUx86CPUID leaf1 = { .eax_in = 0x1 }; - virCPUx86CPUID *cpuid; + virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1); + virCPUx86DataItemPtr cpuid; if (!(cpuid = x86DataCpuid(data, &leaf1))) return 0; - return cpuid->eax & SIGNATURE_MASK; + return cpuid->cpuid.eax & SIGNATURE_MASK; } @@ -632,7 +640,7 @@ static int x86DataAddSignature(virCPUx86Data *data, uint32_t signature) { - virCPUx86CPUID cpuid = { .eax_in = 0x1, .eax = signature }; + virCPUx86DataItem cpuid = CPUID(.eax_in = 0x1, .eax = signature); return virCPUx86DataAddCPUIDInt(data, &cpuid); } @@ -857,13 +865,14 @@ x86FeatureNames(virCPUx86MapPtr map, static int x86ParseCPUID(xmlXPathContextPtr ctxt, - virCPUx86CPUID *cpuid) + virCPUx86DataItemPtr item) { + virCPUx86CPUIDPtr cpuid; unsigned long eax_in, ecx_in; unsigned long eax, ebx, ecx, edx; int ret_eax_in, ret_ecx_in, ret_eax, ret_ebx, ret_ecx, ret_edx; - memset(cpuid, 0, sizeof(*cpuid)); + memset(item, 0, sizeof(*item)); eax_in = ecx_in = 0; eax = ebx = ecx = edx = 0; @@ -878,6 +887,7 @@ x86ParseCPUID(xmlXPathContextPtr ctxt, ret_eax == -2 || ret_ebx == -2 || ret_ecx == -2 || ret_edx == -2) return -1; + cpuid = &item->cpuid; cpuid->eax_in = eax_in; cpuid->ecx_in = ecx_in; cpuid->eax = eax; @@ -896,7 +906,7 @@ x86FeatureParse(xmlXPathContextPtr ctxt, virCPUx86MapPtr map = data; xmlNodePtr *nodes = NULL; virCPUx86FeaturePtr feature; - virCPUx86CPUID cpuid; + virCPUx86DataItem cpuid; size_t i; int n; char *str = NULL; @@ -1139,16 +1149,16 @@ x86ModelCompare(virCPUx86ModelPtr model1, virCPUx86CompareResult result = EQUAL; virCPUx86DataIterator iter1 = virCPUx86DataIteratorInit(&model1->data); virCPUx86DataIterator iter2 = virCPUx86DataIteratorInit(&model2->data); - virCPUx86CPUID *cpuid1; - virCPUx86CPUID *cpuid2; + virCPUx86DataItemPtr cpuid1; + virCPUx86DataItemPtr cpuid2; while ((cpuid1 = x86DataCpuidNext(&iter1))) { virCPUx86CompareResult match = SUPERSET; if ((cpuid2 = x86DataCpuid(&model2->data, cpuid1))) { - if (x86cpuidMatch(cpuid1, cpuid2)) + if (x86cpuidMatch(&cpuid1->cpuid, &cpuid2->cpuid)) continue; - else if (!x86cpuidMatchMasked(cpuid1, cpuid2)) + else if (!x86cpuidMatchMasked(&cpuid1->cpuid, &cpuid2->cpuid)) match = SUBSET; } @@ -1162,9 +1172,9 @@ x86ModelCompare(virCPUx86ModelPtr model1, virCPUx86CompareResult match = SUBSET; if ((cpuid1 = x86DataCpuid(&model1->data, cpuid2))) { - if (x86cpuidMatch(cpuid2, cpuid1)) + if (x86cpuidMatch(&cpuid2->cpuid, &cpuid1->cpuid)) continue; - else if (!x86cpuidMatchMasked(cpuid2, cpuid1)) + else if (!x86cpuidMatchMasked(&cpuid2->cpuid, &cpuid1->cpuid)) match = SUPERSET; } @@ -1448,11 +1458,12 @@ static char * virCPUx86DataFormat(const virCPUData *data) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit(&data->data.x86); - virCPUx86CPUID *cpuid; + virCPUx86DataItemPtr item; virBuffer buf = VIR_BUFFER_INITIALIZER; virBufferAddLit(&buf, "<cpudata arch='x86'>\n"); - while ((cpuid = x86DataCpuidNext(&iter))) { + while ((item = x86DataCpuidNext(&iter))) { + virCPUx86CPUIDPtr cpuid = &item->cpuid; virBufferAsprintf(&buf, " <cpuid eax_in='0x%08x' ecx_in='0x%08x'" " eax='0x%08x' ebx='0x%08x'" @@ -1474,7 +1485,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt) { xmlNodePtr *nodes = NULL; virCPUDataPtr cpuData = NULL; - virCPUx86CPUID cpuid; + virCPUx86DataItem cpuid; size_t i; int n; @@ -2060,7 +2071,7 @@ x86EncodePolicy(virCPUx86Data *data, *data = model->data; model->data.len = 0; - model->data.data = NULL; + model->data.items = NULL; x86ModelFree(model); return 0; @@ -2214,17 +2225,18 @@ cpuidCall(virCPUx86CPUID *cpuid) */ static int cpuidSetLeaf4(virCPUDataPtr data, - virCPUx86CPUID *subLeaf0) + virCPUx86DataItemPtr subLeaf0) { - virCPUx86CPUID cpuid = *subLeaf0; + virCPUx86DataItem item = *subLeaf0; + virCPUx86CPUIDPtr cpuid = &item.cpuid; if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) return -1; - while (cpuid.eax & 0x1f) { - cpuid.ecx_in++; - cpuidCall(&cpuid); - if (virCPUx86DataAddCPUID(data, &cpuid) < 0) + while (cpuid->eax & 0x1f) { + cpuid->ecx_in++; + cpuidCall(cpuid); + if (virCPUx86DataAddCPUID(data, &item) < 0) return -1; } return 0; @@ -2237,18 +2249,19 @@ cpuidSetLeaf4(virCPUDataPtr data, */ static int cpuidSetLeaf7(virCPUDataPtr data, - virCPUx86CPUID *subLeaf0) + virCPUx86DataItemPtr subLeaf0) { - virCPUx86CPUID cpuid = { .eax_in = 0x7 }; + virCPUx86DataItem item = CPUID(.eax_in = 0x7); + virCPUx86CPUIDPtr cpuid = &item.cpuid; uint32_t sub; if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) return -1; - for (sub = 1; sub <= subLeaf0->eax; sub++) { - cpuid.ecx_in = sub; - cpuidCall(&cpuid); - if (virCPUx86DataAddCPUID(data, &cpuid) < 0) + for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) { + cpuid->ecx_in = sub; + cpuidCall(cpuid); + if (virCPUx86DataAddCPUID(data, &item) < 0) return -1; } return 0; @@ -2264,15 +2277,16 @@ cpuidSetLeaf7(virCPUDataPtr data, */ static int cpuidSetLeafB(virCPUDataPtr data, - virCPUx86CPUID *subLeaf0) + virCPUx86DataItemPtr subLeaf0) { - virCPUx86CPUID cpuid = *subLeaf0; + virCPUx86DataItem item = *subLeaf0; + virCPUx86CPUIDPtr cpuid = &item.cpuid; - while (cpuid.ecx & 0xff00) { - if (virCPUx86DataAddCPUID(data, &cpuid) < 0) + while (cpuid->ecx & 0xff00) { + if (virCPUx86DataAddCPUID(data, &item) < 0) return -1; - cpuid.ecx_in++; - cpuidCall(&cpuid); + cpuid->ecx_in++; + cpuidCall(cpuid); } return 0; } @@ -2288,9 +2302,10 @@ cpuidSetLeafB(virCPUDataPtr data, */ static int cpuidSetLeafD(virCPUDataPtr data, - virCPUx86CPUID *subLeaf0) + virCPUx86DataItemPtr subLeaf0) { - virCPUx86CPUID cpuid = { .eax_in = 0xd }; + virCPUx86DataItem item = CPUID(.eax_in = 0xd); + virCPUx86CPUIDPtr cpuid = &item.cpuid; virCPUx86CPUID sub0; virCPUx86CPUID sub1; uint32_t sub; @@ -2298,13 +2313,13 @@ cpuidSetLeafD(virCPUDataPtr data, if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) return -1; - cpuid.ecx_in = 1; - cpuidCall(&cpuid); - if (virCPUx86DataAddCPUID(data, &cpuid) < 0) + cpuid->ecx_in = 1; + cpuidCall(cpuid); + if (virCPUx86DataAddCPUID(data, &item) < 0) return -1; - sub0 = *subLeaf0; - sub1 = cpuid; + sub0 = subLeaf0->cpuid; + sub1 = *cpuid; for (sub = 2; sub < 64; sub++) { if (sub < 32 && !(sub0.eax & (1 << sub)) && @@ -2315,9 +2330,9 @@ cpuidSetLeafD(virCPUDataPtr data, !(sub1.edx & (1 << (sub - 32)))) continue; - cpuid.ecx_in = sub; - cpuidCall(&cpuid); - if (virCPUx86DataAddCPUID(data, &cpuid) < 0) + cpuid->ecx_in = sub; + cpuidCall(cpuid); + if (virCPUx86DataAddCPUID(data, &item) < 0) return -1; } return 0; @@ -2335,10 +2350,11 @@ cpuidSetLeafD(virCPUDataPtr data, */ static int cpuidSetLeafResID(virCPUDataPtr data, - virCPUx86CPUID *subLeaf0, + virCPUx86DataItemPtr subLeaf0, uint32_t res) { - virCPUx86CPUID cpuid = { .eax_in = subLeaf0->eax_in }; + virCPUx86DataItem item = CPUID(.eax_in = subLeaf0->cpuid.eax_in); + virCPUx86CPUIDPtr cpuid = &item.cpuid; uint32_t sub; if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) @@ -2347,9 +2363,9 @@ cpuidSetLeafResID(virCPUDataPtr data, for (sub = 1; sub < 32; sub++) { if (!(res & (1 << sub))) continue; - cpuid.ecx_in = sub; - cpuidCall(&cpuid); - if (virCPUx86DataAddCPUID(data, &cpuid) < 0) + cpuid->ecx_in = sub; + cpuidCall(cpuid); + if (virCPUx86DataAddCPUID(data, &item) < 0) return -1; } return 0; @@ -2363,31 +2379,32 @@ cpuidSetLeafResID(virCPUDataPtr data, */ static int cpuidSetLeaf12(virCPUDataPtr data, - virCPUx86CPUID *subLeaf0) + virCPUx86DataItemPtr subLeaf0) { - virCPUx86CPUID cpuid = { .eax_in = 0x7 }; - virCPUx86CPUID *cpuid7; + virCPUx86DataItem item = CPUID(.eax_in = 0x7); + virCPUx86CPUIDPtr cpuid = &item.cpuid; + virCPUx86DataItemPtr cpuid7; - if (!(cpuid7 = x86DataCpuid(&data->data.x86, &cpuid)) || - !(cpuid7->ebx & (1 << 2))) + if (!(cpuid7 = x86DataCpuid(&data->data.x86, &item)) || + !(cpuid7->cpuid.ebx & (1 << 2))) return 0; if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) return -1; - cpuid.eax_in = 0x12; - cpuid.ecx_in = 1; - cpuidCall(&cpuid); - if (virCPUx86DataAddCPUID(data, &cpuid) < 0) + cpuid->eax_in = 0x12; + cpuid->ecx_in = 1; + cpuidCall(cpuid); + if (virCPUx86DataAddCPUID(data, &item) < 0) return -1; - cpuid.ecx_in = 2; - cpuidCall(&cpuid); - while (cpuid.eax & 0xf) { - if (virCPUx86DataAddCPUID(data, &cpuid) < 0) + cpuid->ecx_in = 2; + cpuidCall(cpuid); + while (cpuid->eax & 0xf) { + if (virCPUx86DataAddCPUID(data, &item) < 0) return -1; - cpuid.ecx_in++; - cpuidCall(&cpuid); + cpuid->ecx_in++; + cpuidCall(cpuid); } return 0; } @@ -2399,18 +2416,19 @@ cpuidSetLeaf12(virCPUDataPtr data, */ static int cpuidSetLeaf14(virCPUDataPtr data, - virCPUx86CPUID *subLeaf0) + virCPUx86DataItemPtr subLeaf0) { - virCPUx86CPUID cpuid = { .eax_in = 0x14 }; + virCPUx86DataItem item = CPUID(.eax_in = 0x14); + virCPUx86CPUIDPtr cpuid = &item.cpuid; uint32_t sub; if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) return -1; - for (sub = 1; sub <= subLeaf0->eax; sub++) { - cpuid.ecx_in = sub; - cpuidCall(&cpuid); - if (virCPUx86DataAddCPUID(data, &cpuid) < 0) + for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) { + cpuid->ecx_in = sub; + cpuidCall(cpuid); + if (virCPUx86DataAddCPUID(data, &item) < 0) return -1; } return 0; @@ -2424,21 +2442,22 @@ cpuidSetLeaf14(virCPUDataPtr data, */ static int cpuidSetLeaf17(virCPUDataPtr data, - virCPUx86CPUID *subLeaf0) + virCPUx86DataItemPtr subLeaf0) { - virCPUx86CPUID cpuid = { .eax_in = 0x17 }; + virCPUx86DataItem item = CPUID(.eax_in = 0x17); + virCPUx86CPUIDPtr cpuid = &item.cpuid; uint32_t sub; - if (subLeaf0->eax < 3) + if (subLeaf0->cpuid.eax < 3) return 0; if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) return -1; - for (sub = 1; sub <= subLeaf0->eax; sub++) { - cpuid.ecx_in = sub; - cpuidCall(&cpuid); - if (virCPUx86DataAddCPUID(data, &cpuid) < 0) + for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) { + cpuid->ecx_in = sub; + cpuidCall(cpuid); + if (virCPUx86DataAddCPUID(data, &item) < 0) return -1; } return 0; @@ -2451,39 +2470,40 @@ cpuidSet(uint32_t base, virCPUDataPtr data) int rc; uint32_t max; uint32_t leaf; - virCPUx86CPUID cpuid = { .eax_in = base }; + virCPUx86DataItem item = CPUID(.eax_in = base); + virCPUx86CPUIDPtr cpuid = &item.cpuid; - cpuidCall(&cpuid); - max = cpuid.eax; + cpuidCall(cpuid); + max = cpuid->eax; for (leaf = base; leaf <= max; leaf++) { - cpuid.eax_in = leaf; - cpuid.ecx_in = 0; - cpuidCall(&cpuid); + cpuid->eax_in = leaf; + cpuid->ecx_in = 0; + cpuidCall(cpuid); /* Handle CPUID leaves that depend on previously queried bits or * which provide additional sub leaves for ecx_in > 0 */ if (leaf == 0x4) - rc = cpuidSetLeaf4(data, &cpuid); + rc = cpuidSetLeaf4(data, &item); else if (leaf == 0x7) - rc = cpuidSetLeaf7(data, &cpuid); + rc = cpuidSetLeaf7(data, &item); else if (leaf == 0xb) - rc = cpuidSetLeafB(data, &cpuid); + rc = cpuidSetLeafB(data, &item); else if (leaf == 0xd) - rc = cpuidSetLeafD(data, &cpuid); + rc = cpuidSetLeafD(data, &item); else if (leaf == 0xf) - rc = cpuidSetLeafResID(data, &cpuid, cpuid.edx); + rc = cpuidSetLeafResID(data, &item, cpuid->edx); else if (leaf == 0x10) - rc = cpuidSetLeafResID(data, &cpuid, cpuid.ebx); + rc = cpuidSetLeafResID(data, &item, cpuid->ebx); else if (leaf == 0x12) - rc = cpuidSetLeaf12(data, &cpuid); + rc = cpuidSetLeaf12(data, &item); else if (leaf == 0x14) - rc = cpuidSetLeaf14(data, &cpuid); + rc = cpuidSetLeaf14(data, &item); else if (leaf == 0x17) - rc = cpuidSetLeaf17(data, &cpuid); + rc = cpuidSetLeaf17(data, &item); else - rc = virCPUx86DataAddCPUID(data, &cpuid); + rc = virCPUx86DataAddCPUID(data, &item); if (rc < 0) return -1; @@ -3059,7 +3079,7 @@ virCPUx86ValidateFeatures(virCPUDefPtr cpu) int virCPUx86DataAddCPUID(virCPUDataPtr cpuData, - const virCPUx86CPUID *cpuid) + const virCPUx86DataItem *cpuid) { return virCPUx86DataAddCPUIDInt(&cpuData->data.x86, cpuid); } @@ -3093,7 +3113,7 @@ int virCPUx86DataSetVendor(virCPUDataPtr cpuData, const char *vendor) { - virCPUx86CPUID cpuid = { 0 }; + virCPUx86DataItem cpuid = CPUID(0); if (virCPUx86VendorToCPUID(vendor, &cpuid) < 0) return -1; diff --git a/src/cpu/cpu_x86.h b/src/cpu/cpu_x86.h index 78714c0d67..166d4703aa 100644 --- a/src/cpu/cpu_x86.h +++ b/src/cpu/cpu_x86.h @@ -27,7 +27,7 @@ extern struct cpuArchDriver cpuDriverX86; int virCPUx86DataAddCPUID(virCPUDataPtr cpuData, - const virCPUx86CPUID *cpuid); + const virCPUx86DataItem *cpuid); int virCPUx86DataSetSignature(virCPUDataPtr cpuData, unsigned int family, diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h index f3cc3952ed..0e63dd9245 100644 --- a/src/cpu/cpu_x86_data.h +++ b/src/cpu/cpu_x86_data.h @@ -23,6 +23,7 @@ typedef struct _virCPUx86CPUID virCPUx86CPUID; +typedef virCPUx86CPUID *virCPUx86CPUIDPtr; struct _virCPUx86CPUID { uint32_t eax_in; uint32_t ecx_in; @@ -68,10 +69,16 @@ struct _virCPUx86CPUID { # define VIR_CPU_X86_DATA_INIT { 0 } +typedef struct _virCPUx86DataItem virCPUx86DataItem; +typedef virCPUx86DataItem *virCPUx86DataItemPtr; +struct _virCPUx86DataItem { + virCPUx86CPUID cpuid; +}; + typedef struct _virCPUx86Data virCPUx86Data; struct _virCPUx86Data { size_t len; - virCPUx86CPUID *data; + virCPUx86DataItem *items; }; #endif /* LIBVIRT_CPU_X86_DATA_H */ diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c index 19f90ba181..c19d05326d 100644 --- a/src/libxl/libxl_capabilities.c +++ b/src/libxl/libxl_capabilities.c @@ -66,13 +66,15 @@ struct guest_arch { static int libxlCapsAddCPUID(virCPUDataPtr data, virCPUx86CPUID *cpuid, ssize_t ncaps) { + virCPUx86DataItem item = { 0 }; size_t i; for (i = 0; i < ncaps; i++) { - virCPUx86CPUID *c = &cpuid[i]; + item.cpuid = cpuid[i]; - if (virCPUx86DataAddCPUID(data, c) < 0) { - VIR_DEBUG("Failed to add CPUID(%x,%x)", c->eax_in, c->ecx_in); + if (virCPUx86DataAddCPUID(data, &item) < 0) { + VIR_DEBUG("Failed to add CPUID(%x,%x)", + cpuid[i].eax_in, cpuid[i].ecx_in); return -1; } } diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 8e6c3ccd63..bee1b33f2a 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7186,7 +7186,7 @@ static virCPUDataPtr qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data) { virCPUDataPtr cpudata = NULL; - virCPUx86CPUID cpuid; + virCPUx86DataItem item = { 0 }; size_t i; if (!(cpudata = virCPUDataNew(VIR_ARCH_X86_64))) @@ -7194,8 +7194,8 @@ qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data) for (i = 0; i < virJSONValueArraySize(data); i++) { if (qemuMonitorJSONParseCPUx86FeatureWord(virJSONValueArrayGet(data, i), - &cpuid) < 0 || - virCPUx86DataAddCPUID(cpudata, &cpuid) < 0) + &item.cpuid) < 0 || + virCPUx86DataAddCPUID(cpudata, &item) < 0) goto error; } -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:10AM +0200, Jiri Denemark wrote:
The following patches introduce CPU features read from MSR in addition to those queried via CPUID instruction. Let's introduce a container struct which will be able to describe either feature type.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 312 ++++++++++++++++++--------------- src/cpu/cpu_x86.h | 2 +- src/cpu/cpu_x86_data.h | 9 +- src/libxl/libxl_capabilities.c | 8 +- src/qemu/qemu_monitor_json.c | 6 +- 5 files changed, 183 insertions(+), 154 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Although vendor string is always reported by CPUID, the container struct is used for consistency and thus "cpuid" name is not a good fit anymore. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index c7937d55fd..8a10c237e9 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -45,7 +45,7 @@ typedef struct _virCPUx86Vendor virCPUx86Vendor; typedef virCPUx86Vendor *virCPUx86VendorPtr; struct _virCPUx86Vendor { char *name; - virCPUx86DataItem cpuid; + virCPUx86DataItem data; }; typedef struct _virCPUx86Feature virCPUx86Feature; @@ -515,9 +515,9 @@ x86DataToVendor(const virCPUx86Data *data, for (i = 0; i < map->nvendors; i++) { virCPUx86VendorPtr vendor = map->vendors[i]; - if ((cpuid = x86DataCpuid(data, &vendor->cpuid)) && - x86cpuidMatchMasked(&cpuid->cpuid, &vendor->cpuid.cpuid)) { - x86cpuidClearBits(&cpuid->cpuid, &vendor->cpuid.cpuid); + if ((cpuid = x86DataCpuid(data, &vendor->data)) && + x86cpuidMatchMasked(&cpuid->cpuid, &vendor->data.cpuid)) { + x86cpuidClearBits(&cpuid->cpuid, &vendor->data.cpuid); return vendor; } } @@ -760,7 +760,7 @@ x86VendorParse(xmlXPathContextPtr ctxt, goto cleanup; } - if (virCPUx86VendorToCPUID(string, &vendor->cpuid) < 0) + if (virCPUx86VendorToCPUID(string, &vendor->data) < 0) goto cleanup; if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0) @@ -1666,7 +1666,7 @@ x86Compute(virCPUDefPtr host, if (cpu->vendor && host_model->vendor && virCPUx86DataAddCPUIDInt(&guest_model->data, - &host_model->vendor->cpuid) < 0) + &host_model->vendor->data) < 0) goto error; if (host_model->signatures && @@ -2154,7 +2154,7 @@ x86Encode(virArch arch, if (!(data_vendor = virCPUDataNew(arch))) goto error; - if (v && virCPUx86DataAddCPUID(data_vendor, &v->cpuid) < 0) + if (v && virCPUx86DataAddCPUID(data_vendor, &v->data) < 0) goto error; } @@ -2651,7 +2651,7 @@ virCPUx86Baseline(virCPUDefPtr *cpus, } if (vendor && - virCPUx86DataAddCPUIDInt(&base_model->data, &vendor->cpuid) < 0) + virCPUx86DataAddCPUIDInt(&base_model->data, &vendor->data) < 0) goto error; if (x86Decode(cpu, &base_model->data, models, modelName, migratable) < 0) @@ -2950,7 +2950,7 @@ virCPUx86Translate(virCPUDefPtr cpu, goto cleanup; if (model->vendor && - virCPUx86DataAddCPUIDInt(&model->data, &model->vendor->cpuid) < 0) + virCPUx86DataAddCPUIDInt(&model->data, &model->vendor->data) < 0) goto cleanup; if (model->signatures && -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:11AM +0200, Jiri Denemark wrote:
Although vendor string is always reported by CPUID, the container struct is used for consistency and thus "cpuid" name is not a good fit anymore.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 128 +++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 8a10c237e9..6c77b7ce13 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -329,13 +329,13 @@ x86DataCpuidNext(virCPUx86DataIteratorPtr iterator) static virCPUx86DataItemPtr x86DataCpuid(const virCPUx86Data *data, - const virCPUx86DataItem *cpuid) + const virCPUx86DataItem *item) { size_t i; for (i = 0; i < data->len; i++) { - if (data->items[i].cpuid.eax_in == cpuid->cpuid.eax_in && - data->items[i].cpuid.ecx_in == cpuid->cpuid.ecx_in) + if (data->items[i].cpuid.eax_in == item->cpuid.eax_in && + data->items[i].cpuid.ecx_in == item->cpuid.ecx_in) return data->items + i; } @@ -381,15 +381,15 @@ x86DataCopy(virCPUx86Data *dst, const virCPUx86Data *src) static int virCPUx86DataAddCPUIDInt(virCPUx86Data *data, - const virCPUx86DataItem *cpuid) + const virCPUx86DataItem *item) { virCPUx86DataItemPtr existing; - if ((existing = x86DataCpuid(data, cpuid))) { - x86cpuidSetBits(&existing->cpuid, &cpuid->cpuid); + if ((existing = x86DataCpuid(data, item))) { + x86cpuidSetBits(&existing->cpuid, &item->cpuid); } else { if (VIR_APPEND_ELEMENT_COPY(data->items, data->len, - *((virCPUx86DataItemPtr)cpuid)) < 0) + *((virCPUx86DataItemPtr)item)) < 0) return -1; qsort(data->items, data->len, @@ -405,16 +405,16 @@ x86DataAdd(virCPUx86Data *data1, const virCPUx86Data *data2) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data2); - virCPUx86DataItemPtr cpuid1; - virCPUx86DataItemPtr cpuid2; + virCPUx86DataItemPtr item1; + virCPUx86DataItemPtr item2; - while ((cpuid2 = x86DataCpuidNext(&iter))) { - cpuid1 = x86DataCpuid(data1, cpuid2); + while ((item2 = x86DataCpuidNext(&iter))) { + item1 = x86DataCpuid(data1, item2); - if (cpuid1) { - x86cpuidSetBits(&cpuid1->cpuid, &cpuid2->cpuid); + if (item1) { + x86cpuidSetBits(&item1->cpuid, &item2->cpuid); } else { - if (virCPUx86DataAddCPUIDInt(data1, cpuid2) < 0) + if (virCPUx86DataAddCPUIDInt(data1, item2) < 0) return -1; } } @@ -428,12 +428,12 @@ x86DataSubtract(virCPUx86Data *data1, const virCPUx86Data *data2) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1); - virCPUx86DataItemPtr cpuid1; - virCPUx86DataItemPtr cpuid2; + virCPUx86DataItemPtr item1; + virCPUx86DataItemPtr item2; - while ((cpuid1 = x86DataCpuidNext(&iter))) { - if ((cpuid2 = x86DataCpuid(data2, cpuid1))) - x86cpuidClearBits(&cpuid1->cpuid, &cpuid2->cpuid); + while ((item1 = x86DataCpuidNext(&iter))) { + if ((item2 = x86DataCpuid(data2, item1))) + x86cpuidClearBits(&item1->cpuid, &item2->cpuid); } } @@ -443,15 +443,15 @@ x86DataIntersect(virCPUx86Data *data1, const virCPUx86Data *data2) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1); - virCPUx86DataItemPtr cpuid1; - virCPUx86DataItemPtr cpuid2; + virCPUx86DataItemPtr item1; + virCPUx86DataItemPtr item2; - while ((cpuid1 = x86DataCpuidNext(&iter))) { - cpuid2 = x86DataCpuid(data2, cpuid1); - if (cpuid2) - x86cpuidAndBits(&cpuid1->cpuid, &cpuid2->cpuid); + while ((item1 = x86DataCpuidNext(&iter))) { + item2 = x86DataCpuid(data2, item1); + if (item2) + x86cpuidAndBits(&item1->cpuid, &item2->cpuid); else - x86cpuidClearBits(&cpuid1->cpuid, &cpuid1->cpuid); + x86cpuidClearBits(&item1->cpuid, &item1->cpuid); } } @@ -470,12 +470,12 @@ x86DataIsSubset(const virCPUx86Data *data, const virCPUx86Data *subset) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit((virCPUx86Data *)subset); - const virCPUx86DataItem *cpuid; - const virCPUx86DataItem *cpuidSubset; + const virCPUx86DataItem *item; + const virCPUx86DataItem *itemSubset; - while ((cpuidSubset = x86DataCpuidNext(&iter))) { - if (!(cpuid = x86DataCpuid(data, cpuidSubset)) || - !x86cpuidMatchMasked(&cpuid->cpuid, &cpuidSubset->cpuid)) + while ((itemSubset = x86DataCpuidNext(&iter))) { + if (!(item = x86DataCpuid(data, itemSubset)) || + !x86cpuidMatchMasked(&item->cpuid, &itemSubset->cpuid)) return false; } @@ -510,14 +510,14 @@ static virCPUx86VendorPtr x86DataToVendor(const virCPUx86Data *data, virCPUx86MapPtr map) { - virCPUx86DataItemPtr cpuid; + virCPUx86DataItemPtr item; size_t i; for (i = 0; i < map->nvendors; i++) { virCPUx86VendorPtr vendor = map->vendors[i]; - if ((cpuid = x86DataCpuid(data, &vendor->data)) && - x86cpuidMatchMasked(&cpuid->cpuid, &vendor->data.cpuid)) { - x86cpuidClearBits(&cpuid->cpuid, &vendor->data.cpuid); + if ((item = x86DataCpuid(data, &vendor->data)) && + x86cpuidMatchMasked(&item->cpuid, &vendor->data.cpuid)) { + x86cpuidClearBits(&item->cpuid, &vendor->data.cpuid); return vendor; } } @@ -627,12 +627,12 @@ static uint32_t x86DataToSignature(const virCPUx86Data *data) { virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1); - virCPUx86DataItemPtr cpuid; + virCPUx86DataItemPtr item; - if (!(cpuid = x86DataCpuid(data, &leaf1))) + if (!(item = x86DataCpuid(data, &leaf1))) return 0; - return cpuid->cpuid.eax & SIGNATURE_MASK; + return item->cpuid.eax & SIGNATURE_MASK; } @@ -640,9 +640,9 @@ static int x86DataAddSignature(virCPUx86Data *data, uint32_t signature) { - virCPUx86DataItem cpuid = CPUID(.eax_in = 0x1, .eax = signature); + virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1, .eax = signature); - return virCPUx86DataAddCPUIDInt(data, &cpuid); + return virCPUx86DataAddCPUIDInt(data, &leaf1); } @@ -906,7 +906,7 @@ x86FeatureParse(xmlXPathContextPtr ctxt, virCPUx86MapPtr map = data; xmlNodePtr *nodes = NULL; virCPUx86FeaturePtr feature; - virCPUx86DataItem cpuid; + virCPUx86DataItem item; size_t i; int n; char *str = NULL; @@ -943,13 +943,13 @@ x86FeatureParse(xmlXPathContextPtr ctxt, for (i = 0; i < n; i++) { ctxt->node = nodes[i]; - if (x86ParseCPUID(ctxt, &cpuid) < 0) { + if (x86ParseCPUID(ctxt, &item) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid cpuid[%zu] in %s feature"), i, feature->name); goto cleanup; } - if (virCPUx86DataAddCPUIDInt(&feature->data, &cpuid)) + if (virCPUx86DataAddCPUIDInt(&feature->data, &item)) goto cleanup; } @@ -1149,16 +1149,16 @@ x86ModelCompare(virCPUx86ModelPtr model1, virCPUx86CompareResult result = EQUAL; virCPUx86DataIterator iter1 = virCPUx86DataIteratorInit(&model1->data); virCPUx86DataIterator iter2 = virCPUx86DataIteratorInit(&model2->data); - virCPUx86DataItemPtr cpuid1; - virCPUx86DataItemPtr cpuid2; + virCPUx86DataItemPtr item1; + virCPUx86DataItemPtr item2; - while ((cpuid1 = x86DataCpuidNext(&iter1))) { + while ((item1 = x86DataCpuidNext(&iter1))) { virCPUx86CompareResult match = SUPERSET; - if ((cpuid2 = x86DataCpuid(&model2->data, cpuid1))) { - if (x86cpuidMatch(&cpuid1->cpuid, &cpuid2->cpuid)) + if ((item2 = x86DataCpuid(&model2->data, item1))) { + if (x86cpuidMatch(&item1->cpuid, &item2->cpuid)) continue; - else if (!x86cpuidMatchMasked(&cpuid1->cpuid, &cpuid2->cpuid)) + else if (!x86cpuidMatchMasked(&item1->cpuid, &item2->cpuid)) match = SUBSET; } @@ -1168,13 +1168,13 @@ x86ModelCompare(virCPUx86ModelPtr model1, return UNRELATED; } - while ((cpuid2 = x86DataCpuidNext(&iter2))) { + while ((item2 = x86DataCpuidNext(&iter2))) { virCPUx86CompareResult match = SUBSET; - if ((cpuid1 = x86DataCpuid(&model1->data, cpuid2))) { - if (x86cpuidMatch(&cpuid2->cpuid, &cpuid1->cpuid)) + if ((item1 = x86DataCpuid(&model1->data, item2))) { + if (x86cpuidMatch(&item2->cpuid, &item1->cpuid)) continue; - else if (!x86cpuidMatchMasked(&cpuid2->cpuid, &cpuid1->cpuid)) + else if (!x86cpuidMatchMasked(&item2->cpuid, &item1->cpuid)) match = SUPERSET; } @@ -1485,7 +1485,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt) { xmlNodePtr *nodes = NULL; virCPUDataPtr cpuData = NULL; - virCPUx86DataItem cpuid; + virCPUx86DataItem item; size_t i; int n; @@ -1501,12 +1501,12 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt) for (i = 0; i < n; i++) { ctxt->node = nodes[i]; - if (x86ParseCPUID(ctxt, &cpuid) < 0) { + if (x86ParseCPUID(ctxt, &item) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to parse cpuid[%zu]"), i); goto error; } - if (virCPUx86DataAddCPUID(cpuData, &cpuid) < 0) + if (virCPUx86DataAddCPUID(cpuData, &item) < 0) goto error; } @@ -2383,10 +2383,10 @@ cpuidSetLeaf12(virCPUDataPtr data, { virCPUx86DataItem item = CPUID(.eax_in = 0x7); virCPUx86CPUIDPtr cpuid = &item.cpuid; - virCPUx86DataItemPtr cpuid7; + virCPUx86DataItemPtr leaf7; - if (!(cpuid7 = x86DataCpuid(&data->data.x86, &item)) || - !(cpuid7->cpuid.ebx & (1 << 2))) + if (!(leaf7 = x86DataCpuid(&data->data.x86, &item)) || + !(leaf7->cpuid.ebx & (1 << 2))) return 0; if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) @@ -3079,9 +3079,9 @@ virCPUx86ValidateFeatures(virCPUDefPtr cpu) int virCPUx86DataAddCPUID(virCPUDataPtr cpuData, - const virCPUx86DataItem *cpuid) + const virCPUx86DataItem *item) { - return virCPUx86DataAddCPUIDInt(&cpuData->data.x86, cpuid); + return virCPUx86DataAddCPUIDInt(&cpuData->data.x86, item); } @@ -3113,12 +3113,12 @@ int virCPUx86DataSetVendor(virCPUDataPtr cpuData, const char *vendor) { - virCPUx86DataItem cpuid = CPUID(0); + virCPUx86DataItem item = CPUID(0); - if (virCPUx86VendorToCPUID(vendor, &cpuid) < 0) + if (virCPUx86VendorToCPUID(vendor, &item) < 0) return -1; - return virCPUx86DataAddCPUID(cpuData, &cpuid); + return virCPUx86DataAddCPUID(cpuData, &item); } -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:12AM +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 128 +++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 64 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The function is now called virCPUx86DataNext to reflect its purpose: it is an iterator over CPU data (both CPUID and MSR in the near future). Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 6c77b7ce13..5c2f7900a3 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -309,7 +309,7 @@ virCPUx86CPUIDSorter(const void *a, const void *b) /* skips all zero CPUID leaves */ static virCPUx86DataItemPtr -x86DataCpuidNext(virCPUx86DataIteratorPtr iterator) +virCPUx86DataNext(virCPUx86DataIteratorPtr iterator) { const virCPUx86Data *data = iterator->data; @@ -408,7 +408,7 @@ x86DataAdd(virCPUx86Data *data1, virCPUx86DataItemPtr item1; virCPUx86DataItemPtr item2; - while ((item2 = x86DataCpuidNext(&iter))) { + while ((item2 = virCPUx86DataNext(&iter))) { item1 = x86DataCpuid(data1, item2); if (item1) { @@ -431,7 +431,7 @@ x86DataSubtract(virCPUx86Data *data1, virCPUx86DataItemPtr item1; virCPUx86DataItemPtr item2; - while ((item1 = x86DataCpuidNext(&iter))) { + while ((item1 = virCPUx86DataNext(&iter))) { if ((item2 = x86DataCpuid(data2, item1))) x86cpuidClearBits(&item1->cpuid, &item2->cpuid); } @@ -446,7 +446,7 @@ x86DataIntersect(virCPUx86Data *data1, virCPUx86DataItemPtr item1; virCPUx86DataItemPtr item2; - while ((item1 = x86DataCpuidNext(&iter))) { + while ((item1 = virCPUx86DataNext(&iter))) { item2 = x86DataCpuid(data2, item1); if (item2) x86cpuidAndBits(&item1->cpuid, &item2->cpuid); @@ -461,7 +461,7 @@ x86DataIsEmpty(virCPUx86Data *data) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data); - return !x86DataCpuidNext(&iter); + return !virCPUx86DataNext(&iter); } @@ -473,7 +473,7 @@ x86DataIsSubset(const virCPUx86Data *data, const virCPUx86DataItem *item; const virCPUx86DataItem *itemSubset; - while ((itemSubset = x86DataCpuidNext(&iter))) { + while ((itemSubset = virCPUx86DataNext(&iter))) { if (!(item = x86DataCpuid(data, itemSubset)) || !x86cpuidMatchMasked(&item->cpuid, &itemSubset->cpuid)) return false; @@ -1152,7 +1152,7 @@ x86ModelCompare(virCPUx86ModelPtr model1, virCPUx86DataItemPtr item1; virCPUx86DataItemPtr item2; - while ((item1 = x86DataCpuidNext(&iter1))) { + while ((item1 = virCPUx86DataNext(&iter1))) { virCPUx86CompareResult match = SUPERSET; if ((item2 = x86DataCpuid(&model2->data, item1))) { @@ -1168,7 +1168,7 @@ x86ModelCompare(virCPUx86ModelPtr model1, return UNRELATED; } - while ((item2 = x86DataCpuidNext(&iter2))) { + while ((item2 = virCPUx86DataNext(&iter2))) { virCPUx86CompareResult match = SUBSET; if ((item1 = x86DataCpuid(&model1->data, item2))) { @@ -1462,7 +1462,7 @@ virCPUx86DataFormat(const virCPUData *data) virBuffer buf = VIR_BUFFER_INITIALIZER; virBufferAddLit(&buf, "<cpudata arch='x86'>\n"); - while ((item = x86DataCpuidNext(&iter))) { + while ((item = virCPUx86DataNext(&iter))) { virCPUx86CPUIDPtr cpuid = &item->cpuid; virBufferAsprintf(&buf, " <cpuid eax_in='0x%08x' ecx_in='0x%08x'" -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:13AM +0200, Jiri Denemark wrote:
The function is now called virCPUx86DataNext to reflect its purpose: it is an iterator over CPU data (both CPUID and MSR in the near future).
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

It is now called virCPUx86DataGet. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 5c2f7900a3..ad5e23843f 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -328,8 +328,8 @@ virCPUx86DataNext(virCPUx86DataIteratorPtr iterator) static virCPUx86DataItemPtr -x86DataCpuid(const virCPUx86Data *data, - const virCPUx86DataItem *item) +virCPUx86DataGet(const virCPUx86Data *data, + const virCPUx86DataItem *item) { size_t i; @@ -385,7 +385,7 @@ virCPUx86DataAddCPUIDInt(virCPUx86Data *data, { virCPUx86DataItemPtr existing; - if ((existing = x86DataCpuid(data, item))) { + if ((existing = virCPUx86DataGet(data, item))) { x86cpuidSetBits(&existing->cpuid, &item->cpuid); } else { if (VIR_APPEND_ELEMENT_COPY(data->items, data->len, @@ -409,7 +409,7 @@ x86DataAdd(virCPUx86Data *data1, virCPUx86DataItemPtr item2; while ((item2 = virCPUx86DataNext(&iter))) { - item1 = x86DataCpuid(data1, item2); + item1 = virCPUx86DataGet(data1, item2); if (item1) { x86cpuidSetBits(&item1->cpuid, &item2->cpuid); @@ -432,7 +432,7 @@ x86DataSubtract(virCPUx86Data *data1, virCPUx86DataItemPtr item2; while ((item1 = virCPUx86DataNext(&iter))) { - if ((item2 = x86DataCpuid(data2, item1))) + if ((item2 = virCPUx86DataGet(data2, item1))) x86cpuidClearBits(&item1->cpuid, &item2->cpuid); } } @@ -447,7 +447,7 @@ x86DataIntersect(virCPUx86Data *data1, virCPUx86DataItemPtr item2; while ((item1 = virCPUx86DataNext(&iter))) { - item2 = x86DataCpuid(data2, item1); + item2 = virCPUx86DataGet(data2, item1); if (item2) x86cpuidAndBits(&item1->cpuid, &item2->cpuid); else @@ -474,7 +474,7 @@ x86DataIsSubset(const virCPUx86Data *data, const virCPUx86DataItem *itemSubset; while ((itemSubset = virCPUx86DataNext(&iter))) { - if (!(item = x86DataCpuid(data, itemSubset)) || + if (!(item = virCPUx86DataGet(data, itemSubset)) || !x86cpuidMatchMasked(&item->cpuid, &itemSubset->cpuid)) return false; } @@ -515,7 +515,7 @@ x86DataToVendor(const virCPUx86Data *data, for (i = 0; i < map->nvendors; i++) { virCPUx86VendorPtr vendor = map->vendors[i]; - if ((item = x86DataCpuid(data, &vendor->data)) && + if ((item = virCPUx86DataGet(data, &vendor->data)) && x86cpuidMatchMasked(&item->cpuid, &vendor->data.cpuid)) { x86cpuidClearBits(&item->cpuid, &vendor->data.cpuid); return vendor; @@ -610,7 +610,7 @@ x86DataToSignatureFull(const virCPUx86Data *data, *family = *model = *stepping = 0; - if (!(item = x86DataCpuid(data, &leaf1))) + if (!(item = virCPUx86DataGet(data, &leaf1))) return; cpuid = &item->cpuid; @@ -629,7 +629,7 @@ x86DataToSignature(const virCPUx86Data *data) virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1); virCPUx86DataItemPtr item; - if (!(item = x86DataCpuid(data, &leaf1))) + if (!(item = virCPUx86DataGet(data, &leaf1))) return 0; return item->cpuid.eax & SIGNATURE_MASK; @@ -1155,7 +1155,7 @@ x86ModelCompare(virCPUx86ModelPtr model1, while ((item1 = virCPUx86DataNext(&iter1))) { virCPUx86CompareResult match = SUPERSET; - if ((item2 = x86DataCpuid(&model2->data, item1))) { + if ((item2 = virCPUx86DataGet(&model2->data, item1))) { if (x86cpuidMatch(&item1->cpuid, &item2->cpuid)) continue; else if (!x86cpuidMatchMasked(&item1->cpuid, &item2->cpuid)) @@ -1171,7 +1171,7 @@ x86ModelCompare(virCPUx86ModelPtr model1, while ((item2 = virCPUx86DataNext(&iter2))) { virCPUx86CompareResult match = SUBSET; - if ((item1 = x86DataCpuid(&model1->data, item2))) { + if ((item1 = virCPUx86DataGet(&model1->data, item2))) { if (x86cpuidMatch(&item2->cpuid, &item1->cpuid)) continue; else if (!x86cpuidMatchMasked(&item2->cpuid, &item1->cpuid)) @@ -2385,7 +2385,7 @@ cpuidSetLeaf12(virCPUDataPtr data, virCPUx86CPUIDPtr cpuid = &item.cpuid; virCPUx86DataItemPtr leaf7; - if (!(leaf7 = x86DataCpuid(&data->data.x86, &item)) || + if (!(leaf7 = virCPUx86DataGet(&data->data.x86, &item)) || !(leaf7->cpuid.ebx & (1 << 2))) return 0; -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:14AM +0200, Jiri Denemark wrote:
It is now called virCPUx86DataGet.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

It is called virCPUx86DataSorter since the function will work on any CPU data type. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index ad5e23843f..b354339852 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -288,7 +288,7 @@ x86FeatureFindInternal(const char *name) static int -virCPUx86CPUIDSorter(const void *a, const void *b) +virCPUx86DataSorter(const void *a, const void *b) { virCPUx86DataItemPtr da = (virCPUx86DataItemPtr) a; virCPUx86DataItemPtr db = (virCPUx86DataItemPtr) b; @@ -393,7 +393,7 @@ virCPUx86DataAddCPUIDInt(virCPUx86Data *data, return -1; qsort(data->items, data->len, - sizeof(virCPUx86DataItem), virCPUx86CPUIDSorter); + sizeof(virCPUx86DataItem), virCPUx86DataSorter); } return 0; -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:15AM +0200, Jiri Denemark wrote:
It is called virCPUx86DataSorter since the function will work on any CPU data type.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The new name is virCPUx86DataAddItem. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index b354339852..21f58a8c3f 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -380,8 +380,8 @@ x86DataCopy(virCPUx86Data *dst, const virCPUx86Data *src) static int -virCPUx86DataAddCPUIDInt(virCPUx86Data *data, - const virCPUx86DataItem *item) +virCPUx86DataAddItem(virCPUx86Data *data, + const virCPUx86DataItem *item) { virCPUx86DataItemPtr existing; @@ -414,7 +414,7 @@ x86DataAdd(virCPUx86Data *data1, if (item1) { x86cpuidSetBits(&item1->cpuid, &item2->cpuid); } else { - if (virCPUx86DataAddCPUIDInt(data1, item2) < 0) + if (virCPUx86DataAddItem(data1, item2) < 0) return -1; } } @@ -642,7 +642,7 @@ x86DataAddSignature(virCPUx86Data *data, { virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1, .eax = signature); - return virCPUx86DataAddCPUIDInt(data, &leaf1); + return virCPUx86DataAddItem(data, &leaf1); } @@ -949,7 +949,7 @@ x86FeatureParse(xmlXPathContextPtr ctxt, i, feature->name); goto cleanup; } - if (virCPUx86DataAddCPUIDInt(&feature->data, &item)) + if (virCPUx86DataAddItem(&feature->data, &item)) goto cleanup; } @@ -1665,8 +1665,8 @@ x86Compute(virCPUDefPtr host, goto error; if (cpu->vendor && host_model->vendor && - virCPUx86DataAddCPUIDInt(&guest_model->data, - &host_model->vendor->data) < 0) + virCPUx86DataAddItem(&guest_model->data, + &host_model->vendor->data) < 0) goto error; if (host_model->signatures && @@ -2651,7 +2651,7 @@ virCPUx86Baseline(virCPUDefPtr *cpus, } if (vendor && - virCPUx86DataAddCPUIDInt(&base_model->data, &vendor->data) < 0) + virCPUx86DataAddItem(&base_model->data, &vendor->data) < 0) goto error; if (x86Decode(cpu, &base_model->data, models, modelName, migratable) < 0) @@ -2950,7 +2950,7 @@ virCPUx86Translate(virCPUDefPtr cpu, goto cleanup; if (model->vendor && - virCPUx86DataAddCPUIDInt(&model->data, &model->vendor->data) < 0) + virCPUx86DataAddItem(&model->data, &model->vendor->data) < 0) goto cleanup; if (model->signatures && @@ -3081,7 +3081,7 @@ int virCPUx86DataAddCPUID(virCPUDataPtr cpuData, const virCPUx86DataItem *item) { - return virCPUx86DataAddCPUIDInt(&cpuData->data.x86, item); + return virCPUx86DataAddItem(&cpuData->data.x86, item); } -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:16AM +0200, Jiri Denemark wrote:
The new name is virCPUx86DataAddItem.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

It's called virCPUx86DataAdd now. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 46 +++++++++++++++++----------------- src/cpu/cpu_x86.h | 4 +-- src/libvirt_private.syms | 2 +- src/libxl/libxl_capabilities.c | 2 +- src/qemu/qemu_monitor_json.c | 2 +- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 21f58a8c3f..492839496e 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -1506,7 +1506,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt) _("failed to parse cpuid[%zu]"), i); goto error; } - if (virCPUx86DataAddCPUID(cpuData, &item) < 0) + if (virCPUx86DataAdd(cpuData, &item) < 0) goto error; } @@ -2154,7 +2154,7 @@ x86Encode(virArch arch, if (!(data_vendor = virCPUDataNew(arch))) goto error; - if (v && virCPUx86DataAddCPUID(data_vendor, &v->data) < 0) + if (v && virCPUx86DataAdd(data_vendor, &v->data) < 0) goto error; } @@ -2230,13 +2230,13 @@ cpuidSetLeaf4(virCPUDataPtr data, virCPUx86DataItem item = *subLeaf0; virCPUx86CPUIDPtr cpuid = &item.cpuid; - if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) + if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; while (cpuid->eax & 0x1f) { cpuid->ecx_in++; cpuidCall(cpuid); - if (virCPUx86DataAddCPUID(data, &item) < 0) + if (virCPUx86DataAdd(data, &item) < 0) return -1; } return 0; @@ -2255,13 +2255,13 @@ cpuidSetLeaf7(virCPUDataPtr data, virCPUx86CPUIDPtr cpuid = &item.cpuid; uint32_t sub; - if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) + if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) { cpuid->ecx_in = sub; cpuidCall(cpuid); - if (virCPUx86DataAddCPUID(data, &item) < 0) + if (virCPUx86DataAdd(data, &item) < 0) return -1; } return 0; @@ -2283,7 +2283,7 @@ cpuidSetLeafB(virCPUDataPtr data, virCPUx86CPUIDPtr cpuid = &item.cpuid; while (cpuid->ecx & 0xff00) { - if (virCPUx86DataAddCPUID(data, &item) < 0) + if (virCPUx86DataAdd(data, &item) < 0) return -1; cpuid->ecx_in++; cpuidCall(cpuid); @@ -2310,12 +2310,12 @@ cpuidSetLeafD(virCPUDataPtr data, virCPUx86CPUID sub1; uint32_t sub; - if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) + if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; cpuid->ecx_in = 1; cpuidCall(cpuid); - if (virCPUx86DataAddCPUID(data, &item) < 0) + if (virCPUx86DataAdd(data, &item) < 0) return -1; sub0 = subLeaf0->cpuid; @@ -2332,7 +2332,7 @@ cpuidSetLeafD(virCPUDataPtr data, cpuid->ecx_in = sub; cpuidCall(cpuid); - if (virCPUx86DataAddCPUID(data, &item) < 0) + if (virCPUx86DataAdd(data, &item) < 0) return -1; } return 0; @@ -2357,7 +2357,7 @@ cpuidSetLeafResID(virCPUDataPtr data, virCPUx86CPUIDPtr cpuid = &item.cpuid; uint32_t sub; - if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) + if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; for (sub = 1; sub < 32; sub++) { @@ -2365,7 +2365,7 @@ cpuidSetLeafResID(virCPUDataPtr data, continue; cpuid->ecx_in = sub; cpuidCall(cpuid); - if (virCPUx86DataAddCPUID(data, &item) < 0) + if (virCPUx86DataAdd(data, &item) < 0) return -1; } return 0; @@ -2389,19 +2389,19 @@ cpuidSetLeaf12(virCPUDataPtr data, !(leaf7->cpuid.ebx & (1 << 2))) return 0; - if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) + if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; cpuid->eax_in = 0x12; cpuid->ecx_in = 1; cpuidCall(cpuid); - if (virCPUx86DataAddCPUID(data, &item) < 0) + if (virCPUx86DataAdd(data, &item) < 0) return -1; cpuid->ecx_in = 2; cpuidCall(cpuid); while (cpuid->eax & 0xf) { - if (virCPUx86DataAddCPUID(data, &item) < 0) + if (virCPUx86DataAdd(data, &item) < 0) return -1; cpuid->ecx_in++; cpuidCall(cpuid); @@ -2422,13 +2422,13 @@ cpuidSetLeaf14(virCPUDataPtr data, virCPUx86CPUIDPtr cpuid = &item.cpuid; uint32_t sub; - if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) + if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) { cpuid->ecx_in = sub; cpuidCall(cpuid); - if (virCPUx86DataAddCPUID(data, &item) < 0) + if (virCPUx86DataAdd(data, &item) < 0) return -1; } return 0; @@ -2451,13 +2451,13 @@ cpuidSetLeaf17(virCPUDataPtr data, if (subLeaf0->cpuid.eax < 3) return 0; - if (virCPUx86DataAddCPUID(data, subLeaf0) < 0) + if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) { cpuid->ecx_in = sub; cpuidCall(cpuid); - if (virCPUx86DataAddCPUID(data, &item) < 0) + if (virCPUx86DataAdd(data, &item) < 0) return -1; } return 0; @@ -2503,7 +2503,7 @@ cpuidSet(uint32_t base, virCPUDataPtr data) else if (leaf == 0x17) rc = cpuidSetLeaf17(data, &item); else - rc = virCPUx86DataAddCPUID(data, &item); + rc = virCPUx86DataAdd(data, &item); if (rc < 0) return -1; @@ -3078,8 +3078,8 @@ virCPUx86ValidateFeatures(virCPUDefPtr cpu) int -virCPUx86DataAddCPUID(virCPUDataPtr cpuData, - const virCPUx86DataItem *item) +virCPUx86DataAdd(virCPUDataPtr cpuData, + const virCPUx86DataItem *item) { return virCPUx86DataAddItem(&cpuData->data.x86, item); } @@ -3118,7 +3118,7 @@ virCPUx86DataSetVendor(virCPUDataPtr cpuData, if (virCPUx86VendorToCPUID(vendor, &item) < 0) return -1; - return virCPUx86DataAddCPUID(cpuData, &item); + return virCPUx86DataAdd(cpuData, &item); } diff --git a/src/cpu/cpu_x86.h b/src/cpu/cpu_x86.h index 166d4703aa..cd44cbe4f3 100644 --- a/src/cpu/cpu_x86.h +++ b/src/cpu/cpu_x86.h @@ -26,8 +26,8 @@ extern struct cpuArchDriver cpuDriverX86; -int virCPUx86DataAddCPUID(virCPUDataPtr cpuData, - const virCPUx86DataItem *cpuid); +int virCPUx86DataAdd(virCPUDataPtr cpuData, + const virCPUx86DataItem *cpuid); int virCPUx86DataSetSignature(virCPUDataPtr cpuData, unsigned int family, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 212adf53c1..132ee3cae9 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1238,7 +1238,7 @@ virCPUValidateFeatures; # cpu/cpu_x86.h -virCPUx86DataAddCPUID; +virCPUx86DataAdd; virCPUx86DataAddFeature; virCPUx86DataGetSignature; virCPUx86DataSetSignature; diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c index c19d05326d..7ab556af3c 100644 --- a/src/libxl/libxl_capabilities.c +++ b/src/libxl/libxl_capabilities.c @@ -72,7 +72,7 @@ libxlCapsAddCPUID(virCPUDataPtr data, virCPUx86CPUID *cpuid, ssize_t ncaps) for (i = 0; i < ncaps; i++) { item.cpuid = cpuid[i]; - if (virCPUx86DataAddCPUID(data, &item) < 0) { + if (virCPUx86DataAdd(data, &item) < 0) { VIR_DEBUG("Failed to add CPUID(%x,%x)", cpuid[i].eax_in, cpuid[i].ecx_in); return -1; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index bee1b33f2a..a9ba6cf4f6 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7195,7 +7195,7 @@ qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data) for (i = 0; i < virJSONValueArraySize(data); i++) { if (qemuMonitorJSONParseCPUx86FeatureWord(virJSONValueArrayGet(data, i), &item.cpuid) < 0 || - virCPUx86DataAddCPUID(cpudata, &item) < 0) + virCPUx86DataAdd(cpudata, &item) < 0) goto error; } -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:17AM +0200, Jiri Denemark wrote:
It's called virCPUx86DataAdd now.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 46 +++++++++++++++++----------------- src/cpu/cpu_x86.h | 4 +-- src/libvirt_private.syms | 2 +- src/libxl/libxl_capabilities.c | 2 +- src/qemu/qemu_monitor_json.c | 2 +- 5 files changed, 28 insertions(+), 28 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Renamed as virCPUx86VendorToData. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 492839496e..121c88ad43 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -527,8 +527,8 @@ x86DataToVendor(const virCPUx86Data *data, static int -virCPUx86VendorToCPUID(const char *vendor, - virCPUx86DataItemPtr data) +virCPUx86VendorToData(const char *vendor, + virCPUx86DataItemPtr data) { virCPUx86CPUIDPtr cpuid = &data->cpuid; @@ -760,7 +760,7 @@ x86VendorParse(xmlXPathContextPtr ctxt, goto cleanup; } - if (virCPUx86VendorToCPUID(string, &vendor->data) < 0) + if (virCPUx86VendorToData(string, &vendor->data) < 0) goto cleanup; if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0) @@ -3115,7 +3115,7 @@ virCPUx86DataSetVendor(virCPUDataPtr cpuData, { virCPUx86DataItem item = CPUID(0); - if (virCPUx86VendorToCPUID(vendor, &item) < 0) + if (virCPUx86VendorToData(vendor, &item) < 0) return -1; return virCPUx86DataAdd(cpuData, &item); -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:18AM +0200, Jiri Denemark wrote:
Renamed as virCPUx86VendorToData.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The while loop just copied half of virCPUx86DataAddItem. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 121c88ad43..41067617df 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -405,18 +405,11 @@ x86DataAdd(virCPUx86Data *data1, const virCPUx86Data *data2) { virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data2); - virCPUx86DataItemPtr item1; - virCPUx86DataItemPtr item2; + virCPUx86DataItemPtr item; - while ((item2 = virCPUx86DataNext(&iter))) { - item1 = virCPUx86DataGet(data1, item2); - - if (item1) { - x86cpuidSetBits(&item1->cpuid, &item2->cpuid); - } else { - if (virCPUx86DataAddItem(data1, item2) < 0) - return -1; - } + while ((item = virCPUx86DataNext(&iter))) { + if (virCPUx86DataAddItem(data1, item) < 0) + return -1; } return 0; -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:19AM +0200, Jiri Denemark wrote:
The while loop just copied half of virCPUx86DataAddItem.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

virCPUx86DataSorter already compares two virCPUx86DataItem structs. Let's add a tiny wrapper around it called virCPUx86DataCmp and use it instead of open coded comparisons. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 41067617df..74d157d780 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -306,6 +306,13 @@ virCPUx86DataSorter(const void *a, const void *b) return 0; } +static int +virCPUx86DataItemCmp(const virCPUx86DataItem *item1, + const virCPUx86DataItem *item2) +{ + return virCPUx86DataSorter(item1, item2); +} + /* skips all zero CPUID leaves */ static virCPUx86DataItemPtr @@ -334,9 +341,9 @@ virCPUx86DataGet(const virCPUx86Data *data, size_t i; for (i = 0; i < data->len; i++) { - if (data->items[i].cpuid.eax_in == item->cpuid.eax_in && - data->items[i].cpuid.ecx_in == item->cpuid.ecx_in) - return data->items + i; + virCPUx86DataItemPtr di = data->items + i; + if (virCPUx86DataItemCmp(di, item) == 0) + return di; } return NULL; -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:20AM +0200, Jiri Denemark wrote:
virCPUx86DataSorter already compares two virCPUx86DataItem structs. Let's add a tiny wrapper around it called virCPUx86DataCmp and use it instead of open coded comparisons.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The function is renamed as virCPUx86DataItemSetBits and it works on virCPUx86DataItem now. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 74d157d780..f713f02929 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -216,16 +216,16 @@ x86cpuidMatchMasked(const virCPUx86CPUID *cpuid, static void -x86cpuidSetBits(virCPUx86CPUID *cpuid, - const virCPUx86CPUID *mask) +virCPUx86DataItemSetBits(virCPUx86DataItemPtr item, + const virCPUx86DataItem *mask) { if (!mask) return; - cpuid->eax |= mask->eax; - cpuid->ebx |= mask->ebx; - cpuid->ecx |= mask->ecx; - cpuid->edx |= mask->edx; + item->cpuid.eax |= mask->cpuid.eax; + item->cpuid.ebx |= mask->cpuid.ebx; + item->cpuid.ecx |= mask->cpuid.ecx; + item->cpuid.edx |= mask->cpuid.edx; } @@ -393,7 +393,7 @@ virCPUx86DataAddItem(virCPUx86Data *data, virCPUx86DataItemPtr existing; if ((existing = virCPUx86DataGet(data, item))) { - x86cpuidSetBits(&existing->cpuid, &item->cpuid); + virCPUx86DataItemSetBits(existing, item); } else { if (VIR_APPEND_ELEMENT_COPY(data->items, data->len, *((virCPUx86DataItemPtr)item)) < 0) -- 2.21.0

[/me salutes] On Mon, Apr 08, 2019 at 10:42:21AM +0200, Jiri Denemark wrote:
The function is renamed as virCPUx86DataItemSetBits and it works on virCPUx86DataItem now.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The parameters changed from virCPUx86CPUID to virCPUx86DataItem and the function is now called virCPUx86DataItemClearBits. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index f713f02929..dcdd0b60b0 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -230,16 +230,16 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item, static void -x86cpuidClearBits(virCPUx86CPUID *cpuid, - const virCPUx86CPUID *mask) +virCPUx86DataItemClearBits(virCPUx86DataItemPtr item, + const virCPUx86DataItem *mask) { if (!mask) return; - cpuid->eax &= ~mask->eax; - cpuid->ebx &= ~mask->ebx; - cpuid->ecx &= ~mask->ecx; - cpuid->edx &= ~mask->edx; + item->cpuid.eax &= ~mask->cpuid.eax; + item->cpuid.ebx &= ~mask->cpuid.ebx; + item->cpuid.ecx &= ~mask->cpuid.ecx; + item->cpuid.edx &= ~mask->cpuid.edx; } @@ -432,8 +432,8 @@ x86DataSubtract(virCPUx86Data *data1, virCPUx86DataItemPtr item2; while ((item1 = virCPUx86DataNext(&iter))) { - if ((item2 = virCPUx86DataGet(data2, item1))) - x86cpuidClearBits(&item1->cpuid, &item2->cpuid); + item2 = virCPUx86DataGet(data2, item1); + virCPUx86DataItemClearBits(item1, item2); } } @@ -451,7 +451,7 @@ x86DataIntersect(virCPUx86Data *data1, if (item2) x86cpuidAndBits(&item1->cpuid, &item2->cpuid); else - x86cpuidClearBits(&item1->cpuid, &item1->cpuid); + virCPUx86DataItemClearBits(item1, item1); } } @@ -517,7 +517,7 @@ x86DataToVendor(const virCPUx86Data *data, virCPUx86VendorPtr vendor = map->vendors[i]; if ((item = virCPUx86DataGet(data, &vendor->data)) && x86cpuidMatchMasked(&item->cpuid, &vendor->data.cpuid)) { - x86cpuidClearBits(&item->cpuid, &vendor->data.cpuid); + virCPUx86DataItemClearBits(item, &vendor->data); return vendor; } } -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:22AM +0200, Jiri Denemark wrote:
The parameters changed from virCPUx86CPUID to virCPUx86DataItem and the function is now called virCPUx86DataItemClearBits.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The function now works on virCPUx86DataItem and it's renamed as virCPUx86DataItemAndBits. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index dcdd0b60b0..57bdffc3af 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -244,16 +244,16 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item, static void -x86cpuidAndBits(virCPUx86CPUID *cpuid, - const virCPUx86CPUID *mask) +virCPUx86DataItemAndBits(virCPUx86DataItemPtr item, + const virCPUx86DataItem *mask) { if (!mask) return; - cpuid->eax &= mask->eax; - cpuid->ebx &= mask->ebx; - cpuid->ecx &= mask->ecx; - cpuid->edx &= mask->edx; + item->cpuid.eax &= mask->cpuid.eax; + item->cpuid.ebx &= mask->cpuid.ebx; + item->cpuid.ecx &= mask->cpuid.ecx; + item->cpuid.edx &= mask->cpuid.edx; } @@ -449,7 +449,7 @@ x86DataIntersect(virCPUx86Data *data1, while ((item1 = virCPUx86DataNext(&iter))) { item2 = virCPUx86DataGet(data2, item1); if (item2) - x86cpuidAndBits(&item1->cpuid, &item2->cpuid); + virCPUx86DataItemAndBits(item1, item2); else virCPUx86DataItemClearBits(item1, item1); } -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:23AM +0200, Jiri Denemark wrote:
The function now works on virCPUx86DataItem and it's renamed as virCPUx86DataItemAndBits.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The function is renamed as virCPUx86DataItemMatchMasked to reflect the change in parameter types. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 57bdffc3af..b88cd83aed 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -205,13 +205,13 @@ x86cpuidMatch(const virCPUx86CPUID *cpuid1, static bool -x86cpuidMatchMasked(const virCPUx86CPUID *cpuid, - const virCPUx86CPUID *mask) +virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item, + const virCPUx86DataItem *mask) { - return ((cpuid->eax & mask->eax) == mask->eax && - (cpuid->ebx & mask->ebx) == mask->ebx && - (cpuid->ecx & mask->ecx) == mask->ecx && - (cpuid->edx & mask->edx) == mask->edx); + return ((item->cpuid.eax & mask->cpuid.eax) == mask->cpuid.eax && + (item->cpuid.ebx & mask->cpuid.ebx) == mask->cpuid.ebx && + (item->cpuid.ecx & mask->cpuid.ecx) == mask->cpuid.ecx && + (item->cpuid.edx & mask->cpuid.edx) == mask->cpuid.edx); } @@ -475,7 +475,7 @@ x86DataIsSubset(const virCPUx86Data *data, while ((itemSubset = virCPUx86DataNext(&iter))) { if (!(item = virCPUx86DataGet(data, itemSubset)) || - !x86cpuidMatchMasked(&item->cpuid, &itemSubset->cpuid)) + !virCPUx86DataItemMatchMasked(item, itemSubset)) return false; } @@ -516,7 +516,7 @@ x86DataToVendor(const virCPUx86Data *data, for (i = 0; i < map->nvendors; i++) { virCPUx86VendorPtr vendor = map->vendors[i]; if ((item = virCPUx86DataGet(data, &vendor->data)) && - x86cpuidMatchMasked(&item->cpuid, &vendor->data.cpuid)) { + virCPUx86DataItemMatchMasked(item, &vendor->data)) { virCPUx86DataItemClearBits(item, &vendor->data); return vendor; } @@ -1158,7 +1158,7 @@ x86ModelCompare(virCPUx86ModelPtr model1, if ((item2 = virCPUx86DataGet(&model2->data, item1))) { if (x86cpuidMatch(&item1->cpuid, &item2->cpuid)) continue; - else if (!x86cpuidMatchMasked(&item1->cpuid, &item2->cpuid)) + else if (!virCPUx86DataItemMatchMasked(item1, item2)) match = SUBSET; } @@ -1174,7 +1174,7 @@ x86ModelCompare(virCPUx86ModelPtr model1, if ((item1 = virCPUx86DataGet(&model1->data, item2))) { if (x86cpuidMatch(&item2->cpuid, &item1->cpuid)) continue; - else if (!x86cpuidMatchMasked(&item2->cpuid, &item1->cpuid)) + else if (!virCPUx86DataItemMatchMasked(item2, item1)) match = SUPERSET; } -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:24AM +0200, Jiri Denemark wrote:
The function is renamed as virCPUx86DataItemMatchMasked to reflect the change in parameter types.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The function now works on virtCPUx86DataItem and it's called virCPUx86DataItemMatch. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index b88cd83aed..62a7914160 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -37,8 +37,6 @@ VIR_LOG_INIT("cpu.cpu_x86"); #define VENDOR_STRING_LENGTH 12 -static const virCPUx86CPUID cpuidNull = { 0 }; - static const virArch archs[] = { VIR_ARCH_I686, VIR_ARCH_X86_64 }; typedef struct _virCPUx86Vendor virCPUx86Vendor; @@ -194,13 +192,13 @@ struct _virCPUx86DataIterator { static bool -x86cpuidMatch(const virCPUx86CPUID *cpuid1, - const virCPUx86CPUID *cpuid2) +virCPUx86DataItemMatch(const virCPUx86DataItem *item1, + const virCPUx86DataItem *item2) { - return (cpuid1->eax == cpuid2->eax && - cpuid1->ebx == cpuid2->ebx && - cpuid1->ecx == cpuid2->ecx && - cpuid1->edx == cpuid2->edx); + return (item1->cpuid.eax == item2->cpuid.eax && + item1->cpuid.ebx == item2->cpuid.ebx && + item1->cpuid.ecx == item2->cpuid.ecx && + item1->cpuid.edx == item2->cpuid.edx); } @@ -319,6 +317,7 @@ static virCPUx86DataItemPtr virCPUx86DataNext(virCPUx86DataIteratorPtr iterator) { const virCPUx86Data *data = iterator->data; + virCPUx86DataItem zero = { 0 }; if (!data) return NULL; @@ -326,7 +325,7 @@ virCPUx86DataNext(virCPUx86DataIteratorPtr iterator) while (++iterator->pos < data->len) { virCPUx86DataItemPtr item = data->items + iterator->pos; - if (!x86cpuidMatch(&item->cpuid, &cpuidNull)) + if (!virCPUx86DataItemMatch(item, &zero)) return item; } @@ -1156,7 +1155,7 @@ x86ModelCompare(virCPUx86ModelPtr model1, virCPUx86CompareResult match = SUPERSET; if ((item2 = virCPUx86DataGet(&model2->data, item1))) { - if (x86cpuidMatch(&item1->cpuid, &item2->cpuid)) + if (virCPUx86DataItemMatch(item1, item2)) continue; else if (!virCPUx86DataItemMatchMasked(item1, item2)) match = SUBSET; @@ -1172,7 +1171,7 @@ x86ModelCompare(virCPUx86ModelPtr model1, virCPUx86CompareResult match = SUBSET; if ((item1 = virCPUx86DataGet(&model1->data, item2))) { - if (x86cpuidMatch(&item2->cpuid, &item1->cpuid)) + if (virCPUx86DataItemMatch(item2, item1)) continue; else if (!virCPUx86DataItemMatchMasked(item2, item1)) match = SUPERSET; -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:25AM +0200, Jiri Denemark wrote:
The function now works on virtCPUx86DataItem and it's called
s/virt/vir/
virCPUx86DataItemMatch.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The structure can only be used for CPUID data now. Adding a type indicator and moving the data into a union will let us store alternative data types. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 202 ++++++++++++++++++++++++--------- src/cpu/cpu_x86_data.h | 10 +- src/libxl/libxl_capabilities.c | 3 +- src/qemu/qemu_monitor_json.c | 3 +- 4 files changed, 160 insertions(+), 58 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 62a7914160..192e067d38 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -55,7 +55,9 @@ struct _virCPUx86Feature { }; -#define CPUID(...) { .cpuid = {__VA_ARGS__} } +#define CPUID(...) \ + { .type = VIR_CPU_X86_DATA_CPUID, \ + .data = { .cpuid = {__VA_ARGS__} } } #define KVM_FEATURE_DEF(Name, Eax_in, Eax) \ static virCPUx86DataItem Name ## _data[] = { \ @@ -195,10 +197,22 @@ static bool virCPUx86DataItemMatch(const virCPUx86DataItem *item1, const virCPUx86DataItem *item2) { - return (item1->cpuid.eax == item2->cpuid.eax && - item1->cpuid.ebx == item2->cpuid.ebx && - item1->cpuid.ecx == item2->cpuid.ecx && - item1->cpuid.edx == item2->cpuid.edx); + const virCPUx86CPUID *cpuid1; + const virCPUx86CPUID *cpuid2; + + switch (item1->type) { + case VIR_CPU_X86_DATA_CPUID: + cpuid1 = &item1->data.cpuid; + cpuid2 = &item2->data.cpuid; + return (cpuid1->eax == cpuid2->eax && + cpuid1->ebx == cpuid2->ebx && + cpuid1->ecx == cpuid2->ecx && + cpuid1->edx == cpuid2->edx); + + case VIR_CPU_X86_DATA_NONE: + default: + return false; + } } @@ -206,10 +220,22 @@ static bool virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item, const virCPUx86DataItem *mask) { - return ((item->cpuid.eax & mask->cpuid.eax) == mask->cpuid.eax && - (item->cpuid.ebx & mask->cpuid.ebx) == mask->cpuid.ebx && - (item->cpuid.ecx & mask->cpuid.ecx) == mask->cpuid.ecx && - (item->cpuid.edx & mask->cpuid.edx) == mask->cpuid.edx); + const virCPUx86CPUID *cpuid; + const virCPUx86CPUID *cpuidMask; + + switch (item->type) { + case VIR_CPU_X86_DATA_CPUID: + cpuid = &item->data.cpuid; + cpuidMask = &mask->data.cpuid; + return ((cpuid->eax & cpuidMask->eax) == cpuidMask->eax && + (cpuid->ebx & cpuidMask->ebx) == cpuidMask->ebx && + (cpuid->ecx & cpuidMask->ecx) == cpuidMask->ecx && + (cpuid->edx & cpuidMask->edx) == cpuidMask->edx); + + case VIR_CPU_X86_DATA_NONE: + default: + return false; + } } @@ -217,13 +243,26 @@ static void virCPUx86DataItemSetBits(virCPUx86DataItemPtr item, const virCPUx86DataItem *mask) { + virCPUx86CPUIDPtr cpuid; + const virCPUx86CPUID *cpuidMask; + if (!mask) return; - item->cpuid.eax |= mask->cpuid.eax; - item->cpuid.ebx |= mask->cpuid.ebx; - item->cpuid.ecx |= mask->cpuid.ecx; - item->cpuid.edx |= mask->cpuid.edx; + switch (item->type) { + case VIR_CPU_X86_DATA_CPUID: + cpuid = &item->data.cpuid; + cpuidMask = &mask->data.cpuid; + cpuid->eax |= cpuidMask->eax; + cpuid->ebx |= cpuidMask->ebx; + cpuid->ecx |= cpuidMask->ecx; + cpuid->edx |= cpuidMask->edx; + break; + + case VIR_CPU_X86_DATA_NONE: + default: + break; + } } @@ -231,13 +270,26 @@ static void virCPUx86DataItemClearBits(virCPUx86DataItemPtr item, const virCPUx86DataItem *mask) { + virCPUx86CPUIDPtr cpuid; + const virCPUx86CPUID *cpuidMask; + if (!mask) return; - item->cpuid.eax &= ~mask->cpuid.eax; - item->cpuid.ebx &= ~mask->cpuid.ebx; - item->cpuid.ecx &= ~mask->cpuid.ecx; - item->cpuid.edx &= ~mask->cpuid.edx; + switch (item->type) { + case VIR_CPU_X86_DATA_CPUID: + cpuid = &item->data.cpuid; + cpuidMask = &mask->data.cpuid; + cpuid->eax &= ~cpuidMask->eax; + cpuid->ebx &= ~cpuidMask->ebx; + cpuid->ecx &= ~cpuidMask->ecx; + cpuid->edx &= ~cpuidMask->edx; + break; + + case VIR_CPU_X86_DATA_NONE: + default: + break; + } } @@ -245,13 +297,26 @@ static void virCPUx86DataItemAndBits(virCPUx86DataItemPtr item, const virCPUx86DataItem *mask) { + virCPUx86CPUIDPtr cpuid; + const virCPUx86CPUID *cpuidMask; + if (!mask) return; - item->cpuid.eax &= mask->cpuid.eax; - item->cpuid.ebx &= mask->cpuid.ebx; - item->cpuid.ecx &= mask->cpuid.ecx; - item->cpuid.edx &= mask->cpuid.edx; + switch (item->type) { + case VIR_CPU_X86_DATA_CPUID: + cpuid = &item->data.cpuid; + cpuidMask = &mask->data.cpuid; + cpuid->eax &= cpuidMask->eax; + cpuid->ebx &= cpuidMask->ebx; + cpuid->ecx &= cpuidMask->ecx; + cpuid->edx &= cpuidMask->edx; + break; + + case VIR_CPU_X86_DATA_NONE: + default: + break; + } } @@ -291,15 +356,29 @@ virCPUx86DataSorter(const void *a, const void *b) virCPUx86DataItemPtr da = (virCPUx86DataItemPtr) a; virCPUx86DataItemPtr db = (virCPUx86DataItemPtr) b; - if (da->cpuid.eax_in > db->cpuid.eax_in) + if (da->type > db->type) return 1; - else if (da->cpuid.eax_in < db->cpuid.eax_in) + else if (da->type < db->type) return -1; - if (da->cpuid.ecx_in > db->cpuid.ecx_in) - return 1; - else if (da->cpuid.ecx_in < db->cpuid.ecx_in) - return -1; + switch (da->type) { + case VIR_CPU_X86_DATA_CPUID: + if (da->data.cpuid.eax_in > db->data.cpuid.eax_in) + return 1; + else if (da->data.cpuid.eax_in < db->data.cpuid.eax_in) + return -1; + + if (da->data.cpuid.ecx_in > db->data.cpuid.ecx_in) + return 1; + else if (da->data.cpuid.ecx_in < db->data.cpuid.ecx_in) + return -1; + + break; + + case VIR_CPU_X86_DATA_NONE: + default: + break; + } return 0; } @@ -527,9 +606,9 @@ x86DataToVendor(const virCPUx86Data *data, static int virCPUx86VendorToData(const char *vendor, - virCPUx86DataItemPtr data) + virCPUx86DataItemPtr item) { - virCPUx86CPUIDPtr cpuid = &data->cpuid; + virCPUx86CPUIDPtr cpuid; if (strlen(vendor) != VENDOR_STRING_LENGTH) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -537,6 +616,8 @@ virCPUx86VendorToData(const char *vendor, return -1; } + item->type = VIR_CPU_X86_DATA_CPUID; + cpuid = &item->data.cpuid; cpuid->eax_in = 0; cpuid->ecx_in = 0; cpuid->ebx = virReadBufInt32LE(vendor); @@ -612,7 +693,7 @@ x86DataToSignatureFull(const virCPUx86Data *data, if (!(item = virCPUx86DataGet(data, &leaf1))) return; - cpuid = &item->cpuid; + cpuid = &item->data.cpuid; *family = ((cpuid->eax >> 20) & 0xff) + ((cpuid->eax >> 8) & 0xf); *model = ((cpuid->eax >> 12) & 0xf0) + ((cpuid->eax >> 4) & 0xf); *stepping = cpuid->eax & 0xf; @@ -631,7 +712,7 @@ x86DataToSignature(const virCPUx86Data *data) if (!(item = virCPUx86DataGet(data, &leaf1))) return 0; - return item->cpuid.eax & SIGNATURE_MASK; + return item->data.cpuid.eax & SIGNATURE_MASK; } @@ -886,7 +967,8 @@ x86ParseCPUID(xmlXPathContextPtr ctxt, ret_eax == -2 || ret_ebx == -2 || ret_ecx == -2 || ret_edx == -2) return -1; - cpuid = &item->cpuid; + item->type = VIR_CPU_X86_DATA_CPUID; + cpuid = &item->data.cpuid; cpuid->eax_in = eax_in; cpuid->ecx_in = ecx_in; cpuid->eax = eax; @@ -1462,13 +1544,23 @@ virCPUx86DataFormat(const virCPUData *data) virBufferAddLit(&buf, "<cpudata arch='x86'>\n"); while ((item = virCPUx86DataNext(&iter))) { - virCPUx86CPUIDPtr cpuid = &item->cpuid; - virBufferAsprintf(&buf, - " <cpuid eax_in='0x%08x' ecx_in='0x%08x'" - " eax='0x%08x' ebx='0x%08x'" - " ecx='0x%08x' edx='0x%08x'/>\n", - cpuid->eax_in, cpuid->ecx_in, - cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx); + virCPUx86CPUIDPtr cpuid; + + switch (item->type) { + case VIR_CPU_X86_DATA_CPUID: + cpuid = &item->data.cpuid; + virBufferAsprintf(&buf, + " <cpuid eax_in='0x%08x' ecx_in='0x%08x'" + " eax='0x%08x' ebx='0x%08x'" + " ecx='0x%08x' edx='0x%08x'/>\n", + cpuid->eax_in, cpuid->ecx_in, + cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx); + break; + + case VIR_CPU_X86_DATA_NONE: + default: + break; + } } virBufferAddLit(&buf, "</cpudata>\n"); @@ -2227,7 +2319,7 @@ cpuidSetLeaf4(virCPUDataPtr data, virCPUx86DataItemPtr subLeaf0) { virCPUx86DataItem item = *subLeaf0; - virCPUx86CPUIDPtr cpuid = &item.cpuid; + virCPUx86CPUIDPtr cpuid = &item.data.cpuid; if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; @@ -2251,13 +2343,13 @@ cpuidSetLeaf7(virCPUDataPtr data, virCPUx86DataItemPtr subLeaf0) { virCPUx86DataItem item = CPUID(.eax_in = 0x7); - virCPUx86CPUIDPtr cpuid = &item.cpuid; + virCPUx86CPUIDPtr cpuid = &item.data.cpuid; uint32_t sub; if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; - for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) { + for (sub = 1; sub <= subLeaf0->data.cpuid.eax; sub++) { cpuid->ecx_in = sub; cpuidCall(cpuid); if (virCPUx86DataAdd(data, &item) < 0) @@ -2279,7 +2371,7 @@ cpuidSetLeafB(virCPUDataPtr data, virCPUx86DataItemPtr subLeaf0) { virCPUx86DataItem item = *subLeaf0; - virCPUx86CPUIDPtr cpuid = &item.cpuid; + virCPUx86CPUIDPtr cpuid = &item.data.cpuid; while (cpuid->ecx & 0xff00) { if (virCPUx86DataAdd(data, &item) < 0) @@ -2304,7 +2396,7 @@ cpuidSetLeafD(virCPUDataPtr data, virCPUx86DataItemPtr subLeaf0) { virCPUx86DataItem item = CPUID(.eax_in = 0xd); - virCPUx86CPUIDPtr cpuid = &item.cpuid; + virCPUx86CPUIDPtr cpuid = &item.data.cpuid; virCPUx86CPUID sub0; virCPUx86CPUID sub1; uint32_t sub; @@ -2317,7 +2409,7 @@ cpuidSetLeafD(virCPUDataPtr data, if (virCPUx86DataAdd(data, &item) < 0) return -1; - sub0 = subLeaf0->cpuid; + sub0 = subLeaf0->data.cpuid; sub1 = *cpuid; for (sub = 2; sub < 64; sub++) { if (sub < 32 && @@ -2352,8 +2444,8 @@ cpuidSetLeafResID(virCPUDataPtr data, virCPUx86DataItemPtr subLeaf0, uint32_t res) { - virCPUx86DataItem item = CPUID(.eax_in = subLeaf0->cpuid.eax_in); - virCPUx86CPUIDPtr cpuid = &item.cpuid; + virCPUx86DataItem item = CPUID(.eax_in = subLeaf0->data.cpuid.eax_in); + virCPUx86CPUIDPtr cpuid = &item.data.cpuid; uint32_t sub; if (virCPUx86DataAdd(data, subLeaf0) < 0) @@ -2381,11 +2473,11 @@ cpuidSetLeaf12(virCPUDataPtr data, virCPUx86DataItemPtr subLeaf0) { virCPUx86DataItem item = CPUID(.eax_in = 0x7); - virCPUx86CPUIDPtr cpuid = &item.cpuid; + virCPUx86CPUIDPtr cpuid = &item.data.cpuid; virCPUx86DataItemPtr leaf7; if (!(leaf7 = virCPUx86DataGet(&data->data.x86, &item)) || - !(leaf7->cpuid.ebx & (1 << 2))) + !(leaf7->data.cpuid.ebx & (1 << 2))) return 0; if (virCPUx86DataAdd(data, subLeaf0) < 0) @@ -2418,13 +2510,13 @@ cpuidSetLeaf14(virCPUDataPtr data, virCPUx86DataItemPtr subLeaf0) { virCPUx86DataItem item = CPUID(.eax_in = 0x14); - virCPUx86CPUIDPtr cpuid = &item.cpuid; + virCPUx86CPUIDPtr cpuid = &item.data.cpuid; uint32_t sub; if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; - for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) { + for (sub = 1; sub <= subLeaf0->data.cpuid.eax; sub++) { cpuid->ecx_in = sub; cpuidCall(cpuid); if (virCPUx86DataAdd(data, &item) < 0) @@ -2444,16 +2536,16 @@ cpuidSetLeaf17(virCPUDataPtr data, virCPUx86DataItemPtr subLeaf0) { virCPUx86DataItem item = CPUID(.eax_in = 0x17); - virCPUx86CPUIDPtr cpuid = &item.cpuid; + virCPUx86CPUIDPtr cpuid = &item.data.cpuid; uint32_t sub; - if (subLeaf0->cpuid.eax < 3) + if (subLeaf0->data.cpuid.eax < 3) return 0; if (virCPUx86DataAdd(data, subLeaf0) < 0) return -1; - for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) { + for (sub = 1; sub <= subLeaf0->data.cpuid.eax; sub++) { cpuid->ecx_in = sub; cpuidCall(cpuid); if (virCPUx86DataAdd(data, &item) < 0) @@ -2470,7 +2562,7 @@ cpuidSet(uint32_t base, virCPUDataPtr data) uint32_t max; uint32_t leaf; virCPUx86DataItem item = CPUID(.eax_in = base); - virCPUx86CPUIDPtr cpuid = &item.cpuid; + virCPUx86CPUIDPtr cpuid = &item.data.cpuid; cpuidCall(cpuid); max = cpuid->eax; diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h index 0e63dd9245..b16860b201 100644 --- a/src/cpu/cpu_x86_data.h +++ b/src/cpu/cpu_x86_data.h @@ -69,10 +69,18 @@ struct _virCPUx86CPUID { # define VIR_CPU_X86_DATA_INIT { 0 } +typedef enum { + VIR_CPU_X86_DATA_NONE = 0, + VIR_CPU_X86_DATA_CPUID, +} virCPUx86DataType; + typedef struct _virCPUx86DataItem virCPUx86DataItem; typedef virCPUx86DataItem *virCPUx86DataItemPtr; struct _virCPUx86DataItem { - virCPUx86CPUID cpuid; + virCPUx86DataType type; + union { + virCPUx86CPUID cpuid; + } data; }; typedef struct _virCPUx86Data virCPUx86Data; diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c index 7ab556af3c..73ae0b3fa1 100644 --- a/src/libxl/libxl_capabilities.c +++ b/src/libxl/libxl_capabilities.c @@ -69,8 +69,9 @@ libxlCapsAddCPUID(virCPUDataPtr data, virCPUx86CPUID *cpuid, ssize_t ncaps) virCPUx86DataItem item = { 0 }; size_t i; + item.type = VIR_CPU_X86_DATA_CPUID; for (i = 0; i < ncaps; i++) { - item.cpuid = cpuid[i]; + item.data.cpuid = cpuid[i]; if (virCPUx86DataAdd(data, &item) < 0) { VIR_DEBUG("Failed to add CPUID(%x,%x)", diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index a9ba6cf4f6..bd2d65e804 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7192,9 +7192,10 @@ qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data) if (!(cpudata = virCPUDataNew(VIR_ARCH_X86_64))) goto error; + item.type = VIR_CPU_X86_DATA_CPUID; for (i = 0; i < virJSONValueArraySize(data); i++) { if (qemuMonitorJSONParseCPUx86FeatureWord(virJSONValueArrayGet(data, i), - &item.cpuid) < 0 || + &item.data.cpuid) < 0 || virCPUx86DataAdd(cpudata, &item) < 0) goto error; } -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:26AM +0200, Jiri Denemark wrote:
The structure can only be used for CPUID data now. Adding a type indicator and moving the data into a union will let us store alternative data types.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 202 ++++++++++++++++++++++++--------- src/cpu/cpu_x86_data.h | 10 +- src/libxl/libxl_capabilities.c | 3 +- src/qemu/qemu_monitor_json.c | 3 +- 4 files changed, 160 insertions(+), 58 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 127 +++++++++++++++++++++++++++++---- src/cpu/cpu_x86_data.h | 10 +++ tests/cputestdata/cpu-cpuid.py | 3 +- 3 files changed, 127 insertions(+), 13 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 192e067d38..57837209b4 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -199,6 +199,8 @@ virCPUx86DataItemMatch(const virCPUx86DataItem *item1, { const virCPUx86CPUID *cpuid1; const virCPUx86CPUID *cpuid2; + const virCPUx86MSR *msr1; + const virCPUx86MSR *msr2; switch (item1->type) { case VIR_CPU_X86_DATA_CPUID: @@ -209,6 +211,12 @@ virCPUx86DataItemMatch(const virCPUx86DataItem *item1, cpuid1->ecx == cpuid2->ecx && cpuid1->edx == cpuid2->edx); + case VIR_CPU_X86_DATA_MSR: + msr1 = &item1->data.msr; + msr2 = &item2->data.msr; + return (msr1->eax == msr2->eax && + msr1->edx == msr2->edx); + case VIR_CPU_X86_DATA_NONE: default: return false; @@ -222,6 +230,8 @@ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item, { const virCPUx86CPUID *cpuid; const virCPUx86CPUID *cpuidMask; + const virCPUx86MSR *msr; + const virCPUx86MSR *msrMask; switch (item->type) { case VIR_CPU_X86_DATA_CPUID: @@ -232,6 +242,12 @@ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item, (cpuid->ecx & cpuidMask->ecx) == cpuidMask->ecx && (cpuid->edx & cpuidMask->edx) == cpuidMask->edx); + case VIR_CPU_X86_DATA_MSR: + msr = &item->data.msr; + msrMask = &mask->data.msr; + return ((msr->eax & msrMask->eax) == msrMask->eax && + (msr->edx & msrMask->edx) == msrMask->edx); + case VIR_CPU_X86_DATA_NONE: default: return false; @@ -245,6 +261,8 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item, { virCPUx86CPUIDPtr cpuid; const virCPUx86CPUID *cpuidMask; + virCPUx86MSRPtr msr; + const virCPUx86MSR *msrMask; if (!mask) return; @@ -259,6 +277,13 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item, cpuid->edx |= cpuidMask->edx; break; + case VIR_CPU_X86_DATA_MSR: + msr = &item->data.msr; + msrMask = &mask->data.msr; + msr->eax |= msrMask->eax; + msr->edx |= msrMask->edx; + break; + case VIR_CPU_X86_DATA_NONE: default: break; @@ -272,6 +297,8 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item, { virCPUx86CPUIDPtr cpuid; const virCPUx86CPUID *cpuidMask; + virCPUx86MSRPtr msr; + const virCPUx86MSR *msrMask; if (!mask) return; @@ -286,6 +313,13 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item, cpuid->edx &= ~cpuidMask->edx; break; + case VIR_CPU_X86_DATA_MSR: + msr = &item->data.msr; + msrMask = &mask->data.msr; + msr->eax &= ~msrMask->eax; + msr->edx &= ~msrMask->edx; + break; + case VIR_CPU_X86_DATA_NONE: default: break; @@ -299,6 +333,8 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item, { virCPUx86CPUIDPtr cpuid; const virCPUx86CPUID *cpuidMask; + virCPUx86MSRPtr msr; + const virCPUx86MSR *msrMask; if (!mask) return; @@ -313,6 +349,13 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item, cpuid->edx &= cpuidMask->edx; break; + case VIR_CPU_X86_DATA_MSR: + msr = &item->data.msr; + msrMask = &mask->data.msr; + msr->eax &= msrMask->eax; + msr->edx &= msrMask->edx; + break; + case VIR_CPU_X86_DATA_NONE: default: break; @@ -375,6 +418,14 @@ virCPUx86DataSorter(const void *a, const void *b) break; + case VIR_CPU_X86_DATA_MSR: + if (da->data.msr.index > db->data.msr.index) + return 1; + else if (da->data.msr.index < db->data.msr.index) + return -1; + + break; + case VIR_CPU_X86_DATA_NONE: default: break; @@ -979,6 +1030,31 @@ x86ParseCPUID(xmlXPathContextPtr ctxt, } +static int +x86ParseMSR(xmlXPathContextPtr ctxt, + virCPUx86DataItemPtr item) +{ + virCPUx86MSRPtr msr; + unsigned long index; + unsigned long eax; + unsigned long edx; + + memset(item, 0, sizeof(*item)); + + if (virXPathULongHex("string(@index)", ctxt, &index) < 0 || + virXPathULongHex("string(@eax)", ctxt, &eax) < 0 || + virXPathULongHex("string(@edx)", ctxt, &edx) < 0) + return -1; + + item->type = VIR_CPU_X86_DATA_MSR; + msr = &item->data.msr; + msr->index = index; + msr->eax = eax; + msr->edx = edx; + return 0; +} + + static int x86FeatureParse(xmlXPathContextPtr ctxt, const char *name, @@ -1011,25 +1087,35 @@ x86FeatureParse(xmlXPathContextPtr ctxt, if (STREQ_NULLABLE(str, "no")) feature->migratable = false; - n = virXPathNodeSet("./cpuid", ctxt, &nodes); + n = virXPathNodeSet("./cpuid|./msr", ctxt, &nodes); if (n < 0) goto cleanup; if (n == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("Missing cpuid for feature %s"), + _("Missing cpuid or msr element in feature %s"), feature->name); goto cleanup; } for (i = 0; i < n; i++) { ctxt->node = nodes[i]; - if (x86ParseCPUID(ctxt, &item) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Invalid cpuid[%zu] in %s feature"), - i, feature->name); - goto cleanup; + if (virXMLNodeNameEqual(nodes[i], "cpuid")) { + if (x86ParseCPUID(ctxt, &item) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid cpuid[%zu] in %s feature"), + i, feature->name); + goto cleanup; + } + } else { + if (x86ParseMSR(ctxt, &item) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid msr[%zu] in %s feature"), + i, feature->name); + goto cleanup; + } } + if (virCPUx86DataAddItem(&feature->data, &item)) goto cleanup; } @@ -1545,6 +1631,7 @@ virCPUx86DataFormat(const virCPUData *data) virBufferAddLit(&buf, "<cpudata arch='x86'>\n"); while ((item = virCPUx86DataNext(&iter))) { virCPUx86CPUIDPtr cpuid; + virCPUx86MSRPtr msr; switch (item->type) { case VIR_CPU_X86_DATA_CPUID: @@ -1557,6 +1644,13 @@ virCPUx86DataFormat(const virCPUData *data) cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx); break; + case VIR_CPU_X86_DATA_MSR: + msr = &item->data.msr; + virBufferAsprintf(&buf, + " <msr index='0x%x' eax='0x%08x' edx='0x%08x'/>\n", + msr->index, msr->eax, msr->edx); + break; + case VIR_CPU_X86_DATA_NONE: default: break; @@ -1580,7 +1674,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt) size_t i; int n; - n = virXPathNodeSet("/cpudata/cpuid", ctxt, &nodes); + n = virXPathNodeSet("/cpudata/cpuid|/cpudata/msr", ctxt, &nodes); if (n <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no x86 CPU data found")); @@ -1592,11 +1686,20 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt) for (i = 0; i < n; i++) { ctxt->node = nodes[i]; - if (x86ParseCPUID(ctxt, &item) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("failed to parse cpuid[%zu]"), i); - goto error; + if (virXMLNodeNameEqual(nodes[i], "cpuid")) { + if (x86ParseCPUID(ctxt, &item) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to parse cpuid[%zu]"), i); + goto error; + } + } else { + if (x86ParseMSR(ctxt, &item) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to parse msr[%zu]"), i); + goto error; + } } + if (virCPUx86DataAdd(cpuData, &item) < 0) goto error; } diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h index b16860b201..4600870c4c 100644 --- a/src/cpu/cpu_x86_data.h +++ b/src/cpu/cpu_x86_data.h @@ -33,6 +33,14 @@ struct _virCPUx86CPUID { uint32_t edx; }; +typedef struct _virCPUx86MSR virCPUx86MSR; +typedef virCPUx86MSR *virCPUx86MSRPtr; +struct _virCPUx86MSR { + uint32_t index; + uint32_t eax; + uint32_t edx; +}; + # define CPUX86_BASIC 0x0 # define CPUX86_KVM 0x40000000 # define CPUX86_EXTENDED 0x80000000 @@ -72,6 +80,7 @@ struct _virCPUx86CPUID { typedef enum { VIR_CPU_X86_DATA_NONE = 0, VIR_CPU_X86_DATA_CPUID, + VIR_CPU_X86_DATA_MSR, } virCPUx86DataType; typedef struct _virCPUx86DataItem virCPUx86DataItem; @@ -80,6 +89,7 @@ struct _virCPUx86DataItem { virCPUx86DataType type; union { virCPUx86CPUID cpuid; + virCPUx86MSR msr; } data; }; diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py index f532475702..f549003124 100755 --- a/tests/cputestdata/cpu-cpuid.py +++ b/tests/cputestdata/cpu-cpuid.py @@ -307,7 +307,8 @@ def parseMap(): cpuMap = {} for feature in data["cpus"]["feature"]: - cpuMap[feature["@name"]] = parseFeature(feature["cpuid"]) + if "cpuid" in feature: + cpuMap[feature["@name"]] = parseFeature(feature["cpuid"]) return cpuMap -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:27AM +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 127 +++++++++++++++++++++++++++++---- src/cpu/cpu_x86_data.h | 10 +++ tests/cputestdata/cpu-cpuid.py | 3 +- 3 files changed, 127 insertions(+), 13 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

They are static and we will need to call them a little bit closer to the beginning of the file. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 69 ++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 57837209b4..1fe6770d57 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -2707,6 +2707,41 @@ cpuidSet(uint32_t base, virCPUDataPtr data) } +static int +virCPUx86CheckFeature(const virCPUDef *cpu, + const char *name) +{ + int ret = -1; + virCPUx86MapPtr map; + virCPUx86ModelPtr model = NULL; + + if (!(map = virCPUx86GetMap())) + return -1; + + if (!(model = x86ModelFromCPU(cpu, map, -1))) + goto cleanup; + + ret = x86FeatureInData(name, &model->data, map); + + cleanup: + x86ModelFree(model); + return ret; +} + + +static int +virCPUx86DataCheckFeature(const virCPUData *data, + const char *name) +{ + virCPUx86MapPtr map; + + if (!(map = virCPUx86GetMap())) + return -1; + + return x86FeatureInData(name, &data->data.x86, map); +} + + static int virCPUx86GetHost(virCPUDefPtr cpu, virDomainCapsCPUModelsPtr models) @@ -3063,40 +3098,6 @@ virCPUx86UpdateLive(virCPUDefPtr cpu, } -static int -virCPUx86CheckFeature(const virCPUDef *cpu, - const char *name) -{ - int ret = -1; - virCPUx86MapPtr map; - virCPUx86ModelPtr model = NULL; - - if (!(map = virCPUx86GetMap())) - return -1; - - if (!(model = x86ModelFromCPU(cpu, map, -1))) - goto cleanup; - - ret = x86FeatureInData(name, &model->data, map); - - cleanup: - x86ModelFree(model); - return ret; -} - - -static int -virCPUx86DataCheckFeature(const virCPUData *data, - const char *name) -{ - virCPUx86MapPtr map; - - if (!(map = virCPUx86GetMap())) - return -1; - - return x86FeatureInData(name, &data->data.x86, map); -} - static int virCPUx86GetModels(char ***models) { -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:28AM +0200, Jiri Denemark wrote:
They are static and we will need to call them a little bit closer to the beginning of the file.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 69 ++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 34 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

We don't really need to parse CPU data from QEMU older than 2.9 (i.e., before query-cpu-model-expansion) at this point. But even if there's a need to do so, we can always use an older version of this script to do the conversion. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 262 ++------------------------------- tests/cputestdata/cpu-parse.sh | 3 +- 2 files changed, 12 insertions(+), 253 deletions(-) diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py index f549003124..56d5efc1c2 100755 --- a/tests/cputestdata/cpu-cpuid.py +++ b/tests/cputestdata/cpu-cpuid.py @@ -5,175 +5,6 @@ import sys import json import xmltodict -# This is a list of x86 CPU features as of QEMU 2.8.50 and it won't need any -# updates since in the future because query-cpu-model-expansion will be used -# with newer QEMU. -cpuidMap = [ - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000001, "edx": 0, "names": ["pni", "sse3"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000002, "edx": 0, "names": ["pclmulqdq", "pclmuldq"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000004, "edx": 0, "names": ["dtes64"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000008, "edx": 0, "names": ["monitor"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000010, "edx": 0, "names": ["ds-cpl", "ds_cpl"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000020, "edx": 0, "names": ["vmx"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000040, "edx": 0, "names": ["smx"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000080, "edx": 0, "names": ["est"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000100, "edx": 0, "names": ["tm2"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000200, "edx": 0, "names": ["ssse3"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000400, "edx": 0, "names": ["cid"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00001000, "edx": 0, "names": ["fma"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00002000, "edx": 0, "names": ["cx16"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00004000, "edx": 0, "names": ["xtpr"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00008000, "edx": 0, "names": ["pdcm"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00020000, "edx": 0, "names": ["pcid"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00040000, "edx": 0, "names": ["dca"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00080000, "edx": 0, "names": ["sse4.1", "sse4-1", "sse4_1"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00100000, "edx": 0, "names": ["sse4.2", "sse4-2", "sse4_2"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00200000, "edx": 0, "names": ["x2apic"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00400000, "edx": 0, "names": ["movbe"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00800000, "edx": 0, "names": ["popcnt"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x01000000, "edx": 0, "names": ["tsc-deadline"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x02000000, "edx": 0, "names": ["aes"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x04000000, "edx": 0, "names": ["xsave"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x08000000, "edx": 0, "names": ["osxsave"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x10000000, "edx": 0, "names": ["avx"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x20000000, "edx": 0, "names": ["f16c"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x40000000, "edx": 0, "names": ["rdrand"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x80000000, "edx": 0, "names": ["hypervisor"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000001, "names": ["fpu"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000002, "names": ["vme"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000004, "names": ["de"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000008, "names": ["pse"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000010, "names": ["tsc"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000020, "names": ["msr"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000040, "names": ["pae"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000080, "names": ["mce"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000100, "names": ["cx8"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000200, "names": ["apic"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000800, "names": ["sep"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00001000, "names": ["mtrr"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00002000, "names": ["pge"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00004000, "names": ["mca"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00008000, "names": ["cmov"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00010000, "names": ["pat"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00020000, "names": ["pse36"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00040000, "names": ["pn"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00080000, "names": ["clflush"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00200000, "names": ["ds"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00400000, "names": ["acpi"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00800000, "names": ["mmx"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x01000000, "names": ["fxsr"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x02000000, "names": ["sse"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x04000000, "names": ["sse2"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x08000000, "names": ["ss"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x10000000, "names": ["ht"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x20000000, "names": ["tm"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x40000000, "names": ["ia64"]}, - {"in_eax": 0x00000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x80000000, "names": ["pbe"]}, - {"in_eax": 0x00000006, "in_ecx": 0, "eax": 0x00000004, "ebx": 0, "ecx": 0, "edx": 0, "names": ["arat"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00000001, "ecx": 0, "edx": 0, "names": ["fsgsbase"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00000002, "ecx": 0, "edx": 0, "names": ["tsc-adjust", "tsc_adjust"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00000008, "ecx": 0, "edx": 0, "names": ["bmi1"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00000010, "ecx": 0, "edx": 0, "names": ["hle"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00000020, "ecx": 0, "edx": 0, "names": ["avx2"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00000080, "ecx": 0, "edx": 0, "names": ["smep"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00000100, "ecx": 0, "edx": 0, "names": ["bmi2"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00000200, "ecx": 0, "edx": 0, "names": ["erms"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00000400, "ecx": 0, "edx": 0, "names": ["invpcid"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00000800, "ecx": 0, "edx": 0, "names": ["rtm"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00001000, "ecx": 0, "edx": 0, "names": []}, # cmt is unknown to QEMU - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00004000, "ecx": 0, "edx": 0, "names": ["mpx"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00010000, "ecx": 0, "edx": 0, "names": ["avx512f"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00020000, "ecx": 0, "edx": 0, "names": ["avx512dq"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00040000, "ecx": 0, "edx": 0, "names": ["rdseed"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00080000, "ecx": 0, "edx": 0, "names": ["adx"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00100000, "ecx": 0, "edx": 0, "names": ["smap"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00200000, "ecx": 0, "edx": 0, "names": ["avx512ifma"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00400000, "ecx": 0, "edx": 0, "names": ["pcommit"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x00800000, "ecx": 0, "edx": 0, "names": ["clflushopt"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x01000000, "ecx": 0, "edx": 0, "names": ["clwb"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x04000000, "ecx": 0, "edx": 0, "names": ["avx512pf"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x08000000, "ecx": 0, "edx": 0, "names": ["avx512er"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x10000000, "ecx": 0, "edx": 0, "names": ["avx512cd"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x20000000, "ecx": 0, "edx": 0, "names": ["sha-ni"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x40000000, "ecx": 0, "edx": 0, "names": ["avx512bw"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0x80000000, "ecx": 0, "edx": 0, "names": ["avx512vl"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000002, "edx": 0, "names": ["avx512vbmi"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000004, "edx": 0, "names": ["umip"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000008, "edx": 0, "names": ["pku"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000010, "edx": 0, "names": ["ospke"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00004000, "edx": 0, "names": ["avx512-vpopcntdq"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00010000, "edx": 0, "names": ["la57"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00400000, "edx": 0, "names": ["rdpid"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000004, "names": ["avx512-4vnniw"]}, - {"in_eax": 0x00000007, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000008, "names": ["avx512-4fmaps"]}, - {"in_eax": 0x0000000d, "in_ecx": 1, "eax": 0x00000001, "ebx": 0, "ecx": 0, "edx": 0, "names": ["xsaveopt"]}, - {"in_eax": 0x0000000d, "in_ecx": 1, "eax": 0x00000002, "ebx": 0, "ecx": 0, "edx": 0, "names": ["xsavec"]}, - {"in_eax": 0x0000000d, "in_ecx": 1, "eax": 0x00000004, "ebx": 0, "ecx": 0, "edx": 0, "names": ["xgetbv1"]}, - {"in_eax": 0x0000000d, "in_ecx": 1, "eax": 0x00000008, "ebx": 0, "ecx": 0, "edx": 0, "names": ["xsaves"]}, - {"in_eax": 0x40000001, "in_ecx": 0, "eax": 0x00000001, "ebx": 0, "ecx": 0, "edx": 0, "names": ["kvmclock"]}, - {"in_eax": 0x40000001, "in_ecx": 0, "eax": 0x00000002, "ebx": 0, "ecx": 0, "edx": 0, "names": ["kvm-nopiodelay", "kvm_nopiodelay"]}, - {"in_eax": 0x40000001, "in_ecx": 0, "eax": 0x00000004, "ebx": 0, "ecx": 0, "edx": 0, "names": ["kvm-mmu", "kvm_mmu"]}, - {"in_eax": 0x40000001, "in_ecx": 0, "eax": 0x00000008, "ebx": 0, "ecx": 0, "edx": 0, "names": ["kvmclock"]}, - {"in_eax": 0x40000001, "in_ecx": 0, "eax": 0x00000010, "ebx": 0, "ecx": 0, "edx": 0, "names": ["kvm-asyncpf", "kvm_asyncpf"]}, - {"in_eax": 0x40000001, "in_ecx": 0, "eax": 0x00000020, "ebx": 0, "ecx": 0, "edx": 0, "names": ["kvm-steal-time", "kvm_steal_time"]}, - {"in_eax": 0x40000001, "in_ecx": 0, "eax": 0x00000040, "ebx": 0, "ecx": 0, "edx": 0, "names": ["kvm-pv-eoi", "kvm_pv_eoi"]}, - {"in_eax": 0x40000001, "in_ecx": 0, "eax": 0x00000080, "ebx": 0, "ecx": 0, "edx": 0, "names": ["kvm-pv-unhalt", "kvm_pv_unhalt"]}, - {"in_eax": 0x40000001, "in_ecx": 0, "eax": 0x01000000, "ebx": 0, "ecx": 0, "edx": 0, "names": ["kvmclock-stable-bit"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000001, "edx": 0, "names": ["lahf-lm", "lahf_lm"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000002, "edx": 0, "names": ["cmp-legacy", "cmp_legacy"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000004, "edx": 0, "names": ["svm"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000008, "edx": 0, "names": ["extapic"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000010, "edx": 0, "names": ["cr8legacy"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000020, "edx": 0, "names": ["abm"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000040, "edx": 0, "names": ["sse4a"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000080, "edx": 0, "names": ["misalignsse"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000100, "edx": 0, "names": ["3dnowprefetch"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000200, "edx": 0, "names": ["osvw"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000400, "edx": 0, "names": ["ibs"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00000800, "edx": 0, "names": ["xop"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00001000, "edx": 0, "names": ["skinit"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00002000, "edx": 0, "names": ["wdt"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00008000, "edx": 0, "names": ["lwp"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00010000, "edx": 0, "names": ["fma4"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00020000, "edx": 0, "names": ["tce"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00080000, "edx": 0, "names": ["nodeid-msr", "nodeid_msr"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00200000, "edx": 0, "names": ["tbm"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00400000, "edx": 0, "names": ["topoext"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x00800000, "edx": 0, "names": ["perfctr-core", "perfctr_core"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0x01000000, "edx": 0, "names": ["perfctr-nb", "perfctr_nb"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000800, "names": ["syscall"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00100000, "names": ["nx", "xd"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00400000, "names": ["mmxext"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x02000000, "names": ["fxsr-opt", "ffxsr", "fxsr_opt"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x04000000, "names": ["pdpe1gb"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x08000000, "names": ["rdtscp"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x20000000, "names": ["lm", "i64"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x40000000, "names": ["3dnowext"]}, - {"in_eax": 0x80000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x80000000, "names": ["3dnow"]}, - {"in_eax": 0x80000007, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000100, "names": ["invtsc"]}, - {"in_eax": 0x8000000A, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000001, "names": ["npt"]}, - {"in_eax": 0x8000000A, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000002, "names": ["lbrv"]}, - {"in_eax": 0x8000000A, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000004, "names": ["svm-lock", "svm_lock"]}, - {"in_eax": 0x8000000A, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000008, "names": ["nrip-save", "nrip_save"]}, - {"in_eax": 0x8000000A, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000010, "names": ["tsc-scale", "tsc_scale"]}, - {"in_eax": 0x8000000A, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000020, "names": ["vmcb-clean", "vmcb_clean"]}, - {"in_eax": 0x8000000A, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000040, "names": ["flushbyasid"]}, - {"in_eax": 0x8000000A, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000080, "names": ["decodeassists"]}, - {"in_eax": 0x8000000A, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000400, "names": ["pause-filter", "pause_filter"]}, - {"in_eax": 0x8000000A, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00001000, "names": ["pfthreshold"]}, - {"in_eax": 0xC0000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000004, "names": ["xstore"]}, - {"in_eax": 0xC0000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000008, "names": ["xstore-en"]}, - {"in_eax": 0xC0000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000040, "names": ["xcrypt"]}, - {"in_eax": 0xC0000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000080, "names": ["xcrypt-en"]}, - {"in_eax": 0xC0000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000100, "names": ["ace2"]}, - {"in_eax": 0xC0000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000200, "names": ["ace2-en"]}, - {"in_eax": 0xC0000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000400, "names": ["phe"]}, - {"in_eax": 0xC0000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00000800, "names": ["phe-en"]}, - {"in_eax": 0xC0000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00001000, "names": ["pmm"]}, - {"in_eax": 0xC0000001, "in_ecx": 0, "eax": 0, "ebx": 0, "ecx": 0, "edx": 0x00002000, "names": ["pmm-en"]}, -] - - def cpuidIsSet(cpuid, feature): in_eax = feature["in_eax"] in_ecx = feature["in_ecx"] @@ -192,68 +23,19 @@ def cpuidIsSet(cpuid, feature): (edx > 0 and leaf["edx"] & edx > 0)) -def cpuidLeaf(cpuid, in_eax, in_ecx): - if in_eax not in cpuid: - cpuid[in_eax] = {} - leaf = cpuid[in_eax] - - if in_ecx not in leaf: - leaf[in_ecx] = {"eax": 0, "ebx": 0, "ecx": 0, "edx": 0} - leaf = leaf[in_ecx] - - return leaf - - def cpuidAdd(cpuid, feature): - leaf = cpuidLeaf(cpuid, feature["in_eax"], feature["in_ecx"]) + if feature["in_eax"] not in cpuid: + cpuid[feature["in_eax"]] = {} + leaf = cpuid[feature["in_eax"]] + + if feature["in_ecx"] not in leaf: + leaf[feature["in_ecx"]] = {"eax": 0, "ebx": 0, "ecx": 0, "edx": 0} + leaf = leaf[feature["in_ecx"]] + for reg in ["eax", "ebx", "ecx", "edx"]: leaf[reg] |= feature[reg] -def parseFeatureWords(path): - features = None - - dec = json.JSONDecoder() - - with open(path, "r") as f: - s = f.read() - - props = {} - rest = [] - chunk = 0 - while s != "": - (data, pos) = dec.raw_decode(s) - if chunk == 0: - features = data["return"] - elif chunk < 5: - keys = ["family", "model", "stepping", "model-id"] - props[keys[chunk - 1]] = data["return"] - else: - rest.append(data) - - while pos < len(s) and s[pos] != "{": - pos += 1 - s = s[pos:] - chunk += 1 - - if props["model-id"].find("Intel") != -1: - props["vendor"] = "GenuineIntel" - elif props["model-id"].find("AMD") != -1: - props["vendor"] = "AuthenticAMD" - - cpuid = {} - for feat in features: - in_eax = feat["cpuid-input-eax"] - in_ecx = 0 - if "cpuid-input-ecx" in feat: - in_ecx = feat["cpuid-input-ecx"] - - leaf = cpuidLeaf(cpuid, in_eax, in_ecx) - leaf[feat["cpuid-register"].lower()] = feat["features"] - - return props, cpuid, rest - - def parseQemu(path, features): cpuid = {} with open(path, "r") as f: @@ -330,27 +112,6 @@ def formatCpuid(cpuid, path, comment): f.write("</cpudata>\n") -def convert(path): - props, cpuid, rest = parseFeatureWords(path) - - for feature in cpuidMap: - value = cpuidIsSet(cpuid, feature) - for name in feature["names"]: - props[name] = value - - print(path) - with open(path, "w") as f: - json.dump({"return": {"model": {"name": "base", "props": props}}, - "id": "model-expansion"}, - f, indent=2, separators=(',', ': ')) - f.write("\n") - - for chunk in rest: - f.write("\n") - json.dump(chunk, f, indent=2, separators=(',', ': ')) - f.write("\n") - - def diff(cpuMap, path): base = path.replace(".json", "") jsonFile = path @@ -374,16 +135,13 @@ def diff(cpuMap, path): if len(sys.argv) < 3: - print("Usage: %s convert|diff json_file..." % sys.argv[0]) + print("Usage: %s diff json_file..." % sys.argv[0]) sys.exit(1) action = sys.argv[1] args = sys.argv[2:] -if action == "convert": - for path in args: - convert(path) -elif action == "diff": +if action == "diff": cpuMap = parseMap() for path in args: diff(cpuMap, path) diff --git a/tests/cputestdata/cpu-parse.sh b/tests/cputestdata/cpu-parse.sh index 3a2bfa0491..a001647549 100755 --- a/tests/cputestdata/cpu-parse.sh +++ b/tests/cputestdata/cpu-parse.sh @@ -53,7 +53,8 @@ json <<<"$data" >$fname.json if [[ -s $fname.json ]]; then echo $fname.json if ! grep -q model-expansion $fname.json; then - $(dirname $0)/cpu-cpuid.py convert $fname.json + echo "Missing query-cpu-model-expansion reply in $name.json" >&2 + exit 1 fi $(dirname $0)/cpu-cpuid.py diff $fname.json else -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:29AM +0200, Jiri Denemark wrote:
We don't really need to parse CPU data from QEMU older than 2.9 (i.e., before query-cpu-model-expansion) at this point. But even if there's a need to do so, we can always use an older version of this script to do the conversion.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 262 ++------------------------------- tests/cputestdata/cpu-parse.sh | 3 +- 2 files changed, 12 insertions(+), 253 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The function will have to deal with both CPUID and MSR features. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py index 56d5efc1c2..866c8047cd 100755 --- a/tests/cputestdata/cpu-cpuid.py +++ b/tests/cputestdata/cpu-cpuid.py @@ -5,7 +5,7 @@ import sys import json import xmltodict -def cpuidIsSet(cpuid, feature): +def checkFeature(cpuid, feature): in_eax = feature["in_eax"] in_ecx = feature["in_ecx"] eax = feature["eax"] @@ -23,7 +23,7 @@ def cpuidIsSet(cpuid, feature): (edx > 0 and leaf["edx"] & edx > 0)) -def cpuidAdd(cpuid, feature): +def addFeature(cpuid, feature): if feature["in_eax"] not in cpuid: cpuid[feature["in_eax"]] = {} leaf = cpuid[feature["in_eax"]] @@ -37,19 +37,19 @@ def cpuidAdd(cpuid, feature): def parseQemu(path, features): - cpuid = {} + cpuData = {} with open(path, "r") as f: data, pos = json.JSONDecoder().raw_decode(f.read()) for (prop, val) in data["return"]["model"]["props"].items(): if val and prop in features: - cpuidAdd(cpuid, features[prop]) + addFeature(cpuData, features[prop]) - return cpuid + return cpuData -def parseCpuid(path): - cpuid = {} +def parseCPUData(path): + cpuData = {} with open(path, "rb") as f: data = xmltodict.parse(f) @@ -60,12 +60,12 @@ def parseCpuid(path): for reg in ["eax", "ebx", "ecx", "edx"]: feature[reg] = int(leaf["@" + reg], 0) - cpuidAdd(cpuid, feature) + addFeature(cpuData, feature) - return cpuid + return cpuData -def parseFeature(data): +def parseMapFeature(data): cpuid = {} for reg in ["in_eax", "in_ecx", "eax", "ebx", "ecx", "edx"]: if reg.startswith("in_"): @@ -90,12 +90,12 @@ def parseMap(): cpuMap = {} for feature in data["cpus"]["feature"]: if "cpuid" in feature: - cpuMap[feature["@name"]] = parseFeature(feature["cpuid"]) + cpuMap[feature["@name"]] = parseMapFeature(feature["cpuid"]) return cpuMap -def formatCpuid(cpuid, path, comment): +def formatCPUData(cpuid, path, comment): print(path) with open(path, "w") as f: f.write("<!-- " + comment + " -->\n") @@ -115,23 +115,23 @@ def formatCpuid(cpuid, path, comment): def diff(cpuMap, path): base = path.replace(".json", "") jsonFile = path - cpuidFile = base + ".xml" + cpuDataFile = base + ".xml" enabledFile = base + "-enabled.xml" disabledFile = base + "-disabled.xml" - cpuid = parseCpuid(cpuidFile) + cpuData = parseCPUData(cpuDataFile) qemu = parseQemu(jsonFile, cpuMap) enabled = {} disabled = {} for feature in cpuMap.values(): - if cpuidIsSet(qemu, feature): - cpuidAdd(enabled, feature) - elif cpuidIsSet(cpuid, feature): - cpuidAdd(disabled, feature) + if checkFeature(qemu, feature): + addFeature(enabled, feature) + elif checkFeature(cpuData, feature): + addFeature(disabled, feature) - formatCpuid(enabled, enabledFile, "Features enabled by QEMU") - formatCpuid(disabled, disabledFile, "Features disabled by QEMU") + formatCPUData(enabled, enabledFile, "Features enabled by QEMU") + formatCPUData(disabled, disabledFile, "Features disabled by QEMU") if len(sys.argv) < 3: -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:30AM +0200, Jiri Denemark wrote:
The function will have to deal with both CPUID and MSR features.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

leaf["eax"] & eax > 0 check works correctly only if there's at most 1 bit set in eax. Luckily that's been always the case, but fixing this could save us from future surprises. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py index 866c8047cd..0a2710689d 100755 --- a/tests/cputestdata/cpu-cpuid.py +++ b/tests/cputestdata/cpu-cpuid.py @@ -15,12 +15,12 @@ def checkFeature(cpuid, feature): if in_eax not in cpuid or in_ecx not in cpuid[in_eax]: return False - else: - leaf = cpuid[in_eax][in_ecx] - return ((eax > 0 and leaf["eax"] & eax > 0) or - (ebx > 0 and leaf["ebx"] & ebx > 0) or - (ecx > 0 and leaf["ecx"] & ecx > 0) or - (edx > 0 and leaf["edx"] & edx > 0)) + + leaf = cpuid[in_eax][in_ecx] + return ((eax > 0 and leaf["eax"] & eax == eax) or + (ebx > 0 and leaf["ebx"] & ebx == ebx) or + (ecx > 0 and leaf["ecx"] & ecx == ecx) or + (edx > 0 and leaf["edx"] & edx == edx)) def addFeature(cpuid, feature): -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:31AM +0200, Jiri Denemark wrote:
leaf["eax"] & eax > 0 check works correctly only if there's at most 1 bit set in eax. Luckily that's been always the case, but fixing this could save us from future surprises.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

This will let us simplify the code since the dictionary keys will match attribute names in various XMLs. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 39 ++++++++++++++++------------------ 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py index 0a2710689d..cba5fc165a 100755 --- a/tests/cputestdata/cpu-cpuid.py +++ b/tests/cputestdata/cpu-cpuid.py @@ -6,17 +6,17 @@ import json import xmltodict def checkFeature(cpuid, feature): - in_eax = feature["in_eax"] - in_ecx = feature["in_ecx"] + eax_in = feature["eax_in"] + ecx_in = feature["ecx_in"] eax = feature["eax"] ebx = feature["ebx"] ecx = feature["ecx"] edx = feature["edx"] - if in_eax not in cpuid or in_ecx not in cpuid[in_eax]: + if eax_in not in cpuid or ecx_in not in cpuid[eax_in]: return False - leaf = cpuid[in_eax][in_ecx] + leaf = cpuid[eax_in][ecx_in] return ((eax > 0 and leaf["eax"] & eax == eax) or (ebx > 0 and leaf["ebx"] & ebx == ebx) or (ecx > 0 and leaf["ecx"] & ecx == ecx) or @@ -24,13 +24,13 @@ def checkFeature(cpuid, feature): def addFeature(cpuid, feature): - if feature["in_eax"] not in cpuid: - cpuid[feature["in_eax"]] = {} - leaf = cpuid[feature["in_eax"]] + if feature["eax_in"] not in cpuid: + cpuid[feature["eax_in"]] = {} + leaf = cpuid[feature["eax_in"]] - if feature["in_ecx"] not in leaf: - leaf[feature["in_ecx"]] = {"eax": 0, "ebx": 0, "ecx": 0, "edx": 0} - leaf = leaf[feature["in_ecx"]] + if feature["ecx_in"] not in leaf: + leaf[feature["ecx_in"]] = {"eax": 0, "ebx": 0, "ecx": 0, "edx": 0} + leaf = leaf[feature["ecx_in"]] for reg in ["eax", "ebx", "ecx", "edx"]: leaf[reg] |= feature[reg] @@ -55,8 +55,8 @@ def parseCPUData(path): for leaf in data["cpudata"]["cpuid"]: feature = {} - feature["in_eax"] = int(leaf["@eax_in"], 0) - feature["in_ecx"] = int(leaf["@ecx_in"], 0) + feature["eax_in"] = int(leaf["@eax_in"], 0) + feature["ecx_in"] = int(leaf["@ecx_in"], 0) for reg in ["eax", "ebx", "ecx", "edx"]: feature[reg] = int(leaf["@" + reg], 0) @@ -67,11 +67,8 @@ def parseCPUData(path): def parseMapFeature(data): cpuid = {} - for reg in ["in_eax", "in_ecx", "eax", "ebx", "ecx", "edx"]: - if reg.startswith("in_"): - attr = "@%s_in" % reg[3:] - else: - attr = "@%s" % reg + for reg in ["eax_in", "ecx_in", "eax", "ebx", "ecx", "edx"]: + attr = "@%s" % reg if attr in data: cpuid[reg] = int(data[attr], 0) @@ -100,14 +97,14 @@ def formatCPUData(cpuid, path, comment): with open(path, "w") as f: f.write("<!-- " + comment + " -->\n") f.write("<cpudata arch='x86'>\n") - for in_eax in sorted(cpuid.keys()): - for in_ecx in sorted(cpuid[in_eax].keys()): - leaf = cpuid[in_eax][in_ecx] + for eax_in in sorted(cpuid.keys()): + for ecx_in in sorted(cpuid[eax_in].keys()): + leaf = cpuid[eax_in][ecx_in] line = (" <cpuid eax_in='0x%08x' ecx_in='0x%02x' " "eax='0x%08x' ebx='0x%08x' " "ecx='0x%08x' edx='0x%08x'/>\n") f.write(line % ( - in_eax, in_ecx, + eax_in, ecx_in, leaf["eax"], leaf["ebx"], leaf["ecx"], leaf["edx"])) f.write("</cpudata>\n") -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:32AM +0200, Jiri Denemark wrote:
This will let us simplify the code since the dictionary keys will match attribute names in various XMLs.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 39 ++++++++++++++++------------------ 1 file changed, 18 insertions(+), 21 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Let's make sure the current CPUID specific code is only applied to CPUID features. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 36 +++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py index cba5fc165a..ac69c5a012 100755 --- a/tests/cputestdata/cpu-cpuid.py +++ b/tests/cputestdata/cpu-cpuid.py @@ -5,7 +5,7 @@ import sys import json import xmltodict -def checkFeature(cpuid, feature): +def checkCPUIDFeature(cpuData, feature): eax_in = feature["eax_in"] ecx_in = feature["ecx_in"] eax = feature["eax"] @@ -13,6 +13,10 @@ def checkFeature(cpuid, feature): ecx = feature["ecx"] edx = feature["edx"] + if "cpuid" not in cpuData: + return False + + cpuid = cpuData["cpuid"] if eax_in not in cpuid or ecx_in not in cpuid[eax_in]: return False @@ -23,7 +27,18 @@ def checkFeature(cpuid, feature): (edx > 0 and leaf["edx"] & edx == edx)) -def addFeature(cpuid, feature): +def checkFeature(cpuData, feature): + if feature["type"] == "cpuid": + return checkCPUIDFeature(cpuData, feature) + + return False + + +def addCPUIDFeature(cpuData, feature): + if "cpuid" not in cpuData: + cpuData["cpuid"] = {} + cpuid = cpuData["cpuid"] + if feature["eax_in"] not in cpuid: cpuid[feature["eax_in"]] = {} leaf = cpuid[feature["eax_in"]] @@ -36,6 +51,11 @@ def addFeature(cpuid, feature): leaf[reg] |= feature[reg] +def addFeature(cpuData, feature): + if feature["type"] == "cpuid": + addCPUIDFeature(cpuData, feature) + + def parseQemu(path, features): cpuData = {} with open(path, "r") as f: @@ -54,7 +74,7 @@ def parseCPUData(path): data = xmltodict.parse(f) for leaf in data["cpudata"]["cpuid"]: - feature = {} + feature = {"type": "cpuid"} feature["eax_in"] = int(leaf["@eax_in"], 0) feature["ecx_in"] = int(leaf["@ecx_in"], 0) for reg in ["eax", "ebx", "ecx", "edx"]: @@ -66,7 +86,7 @@ def parseCPUData(path): def parseMapFeature(data): - cpuid = {} + cpuid = {"type": "cpuid"} for reg in ["eax_in", "ecx_in", "eax", "ebx", "ecx", "edx"]: attr = "@%s" % reg @@ -92,11 +112,13 @@ def parseMap(): return cpuMap -def formatCPUData(cpuid, path, comment): +def formatCPUData(cpuData, path, comment): print(path) with open(path, "w") as f: f.write("<!-- " + comment + " -->\n") f.write("<cpudata arch='x86'>\n") + + cpuid = cpuData["cpuid"] for eax_in in sorted(cpuid.keys()): for ecx_in in sorted(cpuid[eax_in].keys()): leaf = cpuid[eax_in][ecx_in] @@ -119,8 +141,8 @@ def diff(cpuMap, path): cpuData = parseCPUData(cpuDataFile) qemu = parseQemu(jsonFile, cpuMap) - enabled = {} - disabled = {} + enabled = {"cpuid": {}} + disabled = {"cpuid": {}} for feature in cpuMap.values(): if checkFeature(qemu, feature): addFeature(enabled, feature) -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:33AM +0200, Jiri Denemark wrote:
Let's make sure the current CPUID specific code is only applied to CPUID features.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 36 +++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The parseMapFeature for parsing features from CPU map XML can be easily generalized to support more feature types. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py index ac69c5a012..89efc3a40c 100755 --- a/tests/cputestdata/cpu-cpuid.py +++ b/tests/cputestdata/cpu-cpuid.py @@ -85,17 +85,20 @@ def parseCPUData(path): return cpuData -def parseMapFeature(data): - cpuid = {"type": "cpuid"} - for reg in ["eax_in", "ecx_in", "eax", "ebx", "ecx", "edx"]: - attr = "@%s" % reg +def parseMapFeature(fType, data): + ret = {"type": fType} + if fType == "cpuid": + fields = ["eax_in", "ecx_in", "eax", "ebx", "ecx", "edx"] + + for field in fields: + attr = "@%s" % field if attr in data: - cpuid[reg] = int(data[attr], 0) + ret[field] = int(data[attr], 0) else: - cpuid[reg] = 0 + ret[field] = 0 - return cpuid + return ret def parseMap(): @@ -106,8 +109,9 @@ def parseMap(): cpuMap = {} for feature in data["cpus"]["feature"]: - if "cpuid" in feature: - cpuMap[feature["@name"]] = parseMapFeature(feature["cpuid"]) + for fType in ["cpuid"]: + if fType in feature: + cpuMap[feature["@name"]] = parseMapFeature(fType, feature[fType]) return cpuMap -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:34AM +0200, Jiri Denemark wrote:
The parseMapFeature for parsing features from CPU map XML can be easily generalized to support more feature types.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

This patch adds an inline python code for reading MSR features. Since reading MSRs is a privileged operation, we have to read them from /dev/cpu/*/msr if it is readable (i.e., the script runs as root) or fallback to using KVM ioctl which can be done by any user that can start virtual machines. The python code is inlined rather than provided in a separate script because whenever there's an issue with proper detection of CPU features, we ask the reporter to run cpu-gather.sh script to give us all data we need to know about the host CPU. Asking them to run several scripts would likely result in one of them being ignored or forgotten. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-gather.sh | 49 ++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/tests/cputestdata/cpu-gather.sh b/tests/cputestdata/cpu-gather.sh index 9c696f57bd..cefd1b0d0d 100755 --- a/tests/cputestdata/cpu-gather.sh +++ b/tests/cputestdata/cpu-gather.sh @@ -7,8 +7,55 @@ grep 'model name' /proc/cpuinfo | head -n1 cpuid -1r - echo + +for python in python3 python2; do + $python <<EOF +from __future__ import print_function +from struct import pack, unpack +from fcntl import ioctl +import sys, errno + +IA32_ARCH_CAPABILITIES_MSR = 0x10a +KVM_GET_MSRS = 0xc008ae88 + +def print_msr(msr, via=None): + if via is None: + print("MSR:") + else: + print("MSR via %s:" % via) + print(" 0x%x: 0x%016x" % (IA32_ARCH_CAPABILITIES_MSR, msr)) + print() + +try: + fd = open("/dev/cpu/0/msr", "rb") + fd.seek(IA32_ARCH_CAPABILITIES_MSR) + buf = fd.read(8) + msr = unpack("=Q", buf)[0] + + print_msr(msr) + sys.exit(0) +except IOError as e: + # The MSR is not supported on the host + if e.errno == errno.EIO: + sys.exit(0) + +try: + fd = open("/dev/kvm", "r") + bufIn = pack("=LLLLQ", 1, 0, IA32_ARCH_CAPABILITIES_MSR, 0, 0) + bufOut = ioctl(fd, KVM_GET_MSRS, bufIn) + msr = unpack("=LLLLQ", bufOut)[4] + + print_msr(msr, via="KVM") +except IOError as e: + pass +EOF + + if [[ $? -eq 0 ]]; then + break + fi +done + qemu=qemu-system-x86_64 for cmd in /usr/bin/$qemu /usr/bin/qemu-kvm /usr/libexec/qemu-kvm; do if [[ -x $cmd ]]; then -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:35AM +0200, Jiri Denemark wrote:
This patch adds an inline python code for reading MSR features. Since reading MSRs is a privileged operation, we have to read them from /dev/cpu/*/msr if it is readable (i.e., the script runs as root) or fallback to using KVM ioctl which can be done by any user that can start virtual machines.
The python code is inlined rather than provided in a separate script because whenever there's an issue with proper detection of CPU features, we ask the reporter to run cpu-gather.sh script to give us all data we need to know about the host CPU. Asking them to run several scripts would likely result in one of them being ignored or forgotten.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-gather.sh | 49 ++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The script just parses whatever cpu-gather.sh printed out. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-parse.sh | 9 ++++++--- tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/cputestdata/cpu-parse.sh b/tests/cputestdata/cpu-parse.sh index a001647549..7501c57cba 100755 --- a/tests/cputestdata/cpu-parse.sh +++ b/tests/cputestdata/cpu-parse.sh @@ -23,12 +23,15 @@ fname="x86_64-cpuid-$fname" xml() { hex='\(0x[0-9a-f]\+\)' - match="$hex $hex: eax=$hex ebx=$hex ecx=$hex edx=$hex" - subst="<cpuid eax_in='\\1' ecx_in='\\2' eax='\\3' ebx='\\4' ecx='\\5' edx='\\6'\\/>" + matchCPUID="$hex $hex: eax=$hex ebx=$hex ecx=$hex edx=$hex" + substCPUID="<cpuid eax_in='\\1' ecx_in='\\2' eax='\\3' ebx='\\4' ecx='\\5' edx='\\6'\\/>" + + matchMSR="$hex: $hex\(.......[0-9a-f]\)" + substMSR="<msr index='\\1' edx='\\2' eax='0x\\3'\\/>" echo "<!-- $model -->" echo "<cpudata arch='x86'>" - sed -ne "s/^ *$match$/ $subst/p" + sed -ne "s/^ *$matchCPUID$/ $substCPUID/p; s/^ *$matchMSR$/ $substMSR/p" echo "</cpudata>" } diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml index 75472d44fe..f1261da891 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml @@ -51,4 +51,5 @@ <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x0000302e' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/> <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/> + <msr index='0x10a' edx='0x00000000' eax='0x0000002b'/> </cpudata> -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:36AM +0200, Jiri Denemark wrote:
The script just parses whatever cpu-gather.sh printed out.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-parse.sh | 9 ++++++--- tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml | 1 + 2 files changed, 7 insertions(+), 3 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 58 ++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py index 89efc3a40c..ae3cf5996a 100755 --- a/tests/cputestdata/cpu-cpuid.py +++ b/tests/cputestdata/cpu-cpuid.py @@ -27,11 +27,29 @@ def checkCPUIDFeature(cpuData, feature): (edx > 0 and leaf["edx"] & edx == edx)) +def checkMSRFeature(cpuData, feature): + index = feature["index"] + edx = feature["edx"] + eax = feature["eax"] + + if "msr" not in cpuData: + return False + + msr = cpuData["msr"] + if index not in msr: + return False + + msr = msr[index] + return ((edx > 0 and msr["edx"] & edx == edx) or + (eax > 0 and msr["eax"] & eax == eax)) + + def checkFeature(cpuData, feature): if feature["type"] == "cpuid": return checkCPUIDFeature(cpuData, feature) - return False + if feature["type"] == "msr": + return checkMSRFeature(cpuData, feature) def addCPUIDFeature(cpuData, feature): @@ -51,9 +69,24 @@ def addCPUIDFeature(cpuData, feature): leaf[reg] |= feature[reg] +def addMSRFeature(cpuData, feature): + if "msr" not in cpuData: + cpuData["msr"] = {} + msr = cpuData["msr"] + + if feature["index"] not in msr: + msr[feature["index"]] = {"edx": 0, "eax": 0} + msr = msr[feature["index"]] + + for reg in ["edx", "eax"]: + msr[reg] |= feature[reg] + + def addFeature(cpuData, feature): if feature["type"] == "cpuid": addCPUIDFeature(cpuData, feature) + elif feature["type"] == "msr": + addMSRFeature(cpuData, feature) def parseQemu(path, features): @@ -82,6 +115,18 @@ def parseCPUData(path): addFeature(cpuData, feature) + if "msr" in data["cpudata"]: + if not isinstance(data["cpudata"]["msr"], list): + data["cpudata"]["msr"] = [data["cpudata"]["msr"]] + + for msr in data["cpudata"]["msr"]: + feature = {"type": "msr"} + feature["index"] = int(msr["@index"], 0) + feature["edx"] = int(msr["@edx"], 0) + feature["eax"] = int(msr["@eax"], 0) + + addFeature(cpuData, feature) + return cpuData @@ -90,6 +135,8 @@ def parseMapFeature(fType, data): if fType == "cpuid": fields = ["eax_in", "ecx_in", "eax", "ebx", "ecx", "edx"] + elif fType == "msr": + fields = ["index", "edx", "eax"] for field in fields: attr = "@%s" % field @@ -109,7 +156,7 @@ def parseMap(): cpuMap = {} for feature in data["cpus"]["feature"]: - for fType in ["cpuid"]: + for fType in ["cpuid", "msr"]: if fType in feature: cpuMap[feature["@name"]] = parseMapFeature(fType, feature[fType]) @@ -132,6 +179,13 @@ def formatCPUData(cpuData, path, comment): f.write(line % ( eax_in, ecx_in, leaf["eax"], leaf["ebx"], leaf["ecx"], leaf["edx"])) + + if "msr" in cpuData: + msr = cpuData["msr"] + for index in sorted(msr.keys()): + f.write(" <msr index='0x%x' edx='0x%08x' eax='0x%08x'/>\n" %( + index, msr[index]['edx'], msr[index]['eax'])) + f.write("</cpudata>\n") -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:37AM +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-cpuid.py | 58 ++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

The new virHostCPUGetMSR internal API will try to read the MSR from /dev/cpu/0/msr and if it is not possible (the device does not exist or libvirt is running unprivileged), it will fallback to asking KVM for the MSR using KVM_GET_MSRS ioctl. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virhostcpu.c | 80 ++++++++++++++++++++++++++++++++++++++++ src/util/virhostcpu.h | 3 ++ 3 files changed, 84 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 132ee3cae9..59a9a6f093 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2016,6 +2016,7 @@ virHostCPUGetInfo; virHostCPUGetKVMMaxVCPUs; virHostCPUGetMap; virHostCPUGetMicrocodeVersion; +virHostCPUGetMSR; virHostCPUGetOnline; virHostCPUGetOnlineBitmap; virHostCPUGetPresentBitmap; diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c index 6514c3d765..10bf3a93d5 100644 --- a/src/util/virhostcpu.c +++ b/src/util/virhostcpu.c @@ -58,6 +58,7 @@ VIR_LOG_INIT("util.hostcpu"); #define KVM_DEVICE "/dev/kvm" +#define MSR_DEVICE "/dev/cpu/0/msr" #if defined(__FreeBSD__) || defined(__APPLE__) @@ -1254,3 +1255,82 @@ virHostCPUGetMicrocodeVersion(void) } #endif /* __linux__ */ + + +#if HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) +static int +virHostCPUGetMSRFromKVM(unsigned long index, + uint64_t *result) +{ + VIR_AUTOCLOSE fd = -1; + struct { + struct kvm_msrs header; + struct kvm_msr_entry entry; + } msr = { + .header = { .nmsrs = 1 }, + .entry = { .index = index }, + }; + + if ((fd = open(KVM_DEVICE, O_RDONLY)) < 0) { + virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE); + return -1; + } + + if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) { + VIR_DEBUG("Cannot get MSR 0x%lx from KVM", index); + return 1; + } + + *result = msr.entry.data; + return 0; +} + +#else + +static int +virHostCPUGetMSRFromKVM(unsigned long index ATTRIBUTE_UNUSED, + uint64_t *result ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Reading MSRs via KVM is not supported on this platform")); + return -1; +} +#endif /* HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) */ + + +/* + * Returns 0 on success, + * 1 when the MSR is not supported by the host CPU, +* -1 on error. + */ +int +virHostCPUGetMSR(unsigned long index, + uint64_t *msr) +{ + VIR_AUTOCLOSE fd = -1; + char ebuf[1024]; + + *msr = 0; + + if ((fd = open(MSR_DEVICE, O_RDONLY)) < 0) { + VIR_DEBUG("Unable to open %s: %s", + MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf))); + } else { + int rc = pread(fd, msr, sizeof(*msr), index); + + if (rc == sizeof(*msr)) + return 0; + + if (rc < 0 && errno == EIO) { + VIR_DEBUG("CPU does not support MSR 0x%lx", index); + return 1; + } + + VIR_DEBUG("Cannot read MSR 0x%lx from %s: %s", + index, MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf))); + } + + VIR_DEBUG("Falling back to KVM ioctl"); + + return virHostCPUGetMSRFromKVM(index, msr); +} diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h index df6a7e789d..0d20dbef61 100644 --- a/src/util/virhostcpu.h +++ b/src/util/virhostcpu.h @@ -66,4 +66,7 @@ int virHostCPUGetOnline(unsigned int cpu, bool *online); unsigned int virHostCPUGetMicrocodeVersion(void); +int virHostCPUGetMSR(unsigned long index, + uint64_t *msr); + #endif /* LIBVIRT_VIRHOSTCPU_H */ -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:38AM +0200, Jiri Denemark wrote:
The new virHostCPUGetMSR internal API will try to read the MSR from /dev/cpu/0/msr and if it is not possible (the device does not exist or libvirt is running unprivileged), it will fallback to asking KVM for the MSR using KVM_GET_MSRS ioctl.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virhostcpu.c | 80 ++++++++++++++++++++++++++++++++++++++++ src/util/virhostcpu.h | 3 ++ 3 files changed, 84 insertions(+)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

On Mon, Apr 08, 2019 at 10:42:38AM +0200, Jiri Denemark wrote:
The new virHostCPUGetMSR internal API will try to read the MSR from /dev/cpu/0/msr and if it is not possible (the device does not exist or libvirt is running unprivileged), it will fallback to asking KVM for the MSR using KVM_GET_MSRS ioctl.
Is there benefit to using /dev/cpu/0/msr, instead of always using /dev/kvm ? Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Thu, Apr 11, 2019 at 17:13:51 +0100, Daniel P. Berrangé wrote:
On Mon, Apr 08, 2019 at 10:42:38AM +0200, Jiri Denemark wrote:
The new virHostCPUGetMSR internal API will try to read the MSR from /dev/cpu/0/msr and if it is not possible (the device does not exist or libvirt is running unprivileged), it will fallback to asking KVM for the MSR using KVM_GET_MSRS ioctl.
Is there benefit to using /dev/cpu/0/msr, instead of always using /dev/kvm ?
KVM may report some bits in the IA32_ARCH_CAPABILITIES MSR even when the host does not set them or even support MSR at all. So for reporting host capabilities /dev/cpu/0/msr is IMHO better. We will still get the made up bits in the MSR via QEMU for host-model. For example, on my laptop which does not support IA32_ARCH_CAPABILITIES MSR at all I get 0x8 when asking KVM, while reading /dev/cpu/0/msr returns I/O error since the MSR does not exist. Jirka

On Fri, Apr 12, 2019 at 11:47:15AM +0200, Jiri Denemark wrote:
On Thu, Apr 11, 2019 at 17:13:51 +0100, Daniel P. Berrangé wrote:
On Mon, Apr 08, 2019 at 10:42:38AM +0200, Jiri Denemark wrote:
The new virHostCPUGetMSR internal API will try to read the MSR from /dev/cpu/0/msr and if it is not possible (the device does not exist or libvirt is running unprivileged), it will fallback to asking KVM for the MSR using KVM_GET_MSRS ioctl.
Is there benefit to using /dev/cpu/0/msr, instead of always using /dev/kvm ?
KVM may report some bits in the IA32_ARCH_CAPABILITIES MSR even when the host does not set them or even support MSR at all. So for reporting host capabilities /dev/cpu/0/msr is IMHO better. We will still get the made up bits in the MSR via QEMU for host-model.
For example, on my laptop which does not support IA32_ARCH_CAPABILITIES MSR at all I get 0x8 when asking KVM, while reading /dev/cpu/0/msr returns I/O error since the MSR does not exist.
Hmm, do we need to get /dev/kvm fixed in this regard ? It seems bad that libvirt will be relying on different information about MSRs when running as root vs non-root. Could like to even more painful bugs to triage. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Fri, Apr 12, 2019 at 11:11:38 +0100, Daniel P. Berrangé wrote:
On Fri, Apr 12, 2019 at 11:47:15AM +0200, Jiri Denemark wrote:
On Thu, Apr 11, 2019 at 17:13:51 +0100, Daniel P. Berrangé wrote:
On Mon, Apr 08, 2019 at 10:42:38AM +0200, Jiri Denemark wrote:
The new virHostCPUGetMSR internal API will try to read the MSR from /dev/cpu/0/msr and if it is not possible (the device does not exist or libvirt is running unprivileged), it will fallback to asking KVM for the MSR using KVM_GET_MSRS ioctl.
Is there benefit to using /dev/cpu/0/msr, instead of always using /dev/kvm ?
KVM may report some bits in the IA32_ARCH_CAPABILITIES MSR even when the host does not set them or even support MSR at all. So for reporting host capabilities /dev/cpu/0/msr is IMHO better. We will still get the made up bits in the MSR via QEMU for host-model.
For example, on my laptop which does not support IA32_ARCH_CAPABILITIES MSR at all I get 0x8 when asking KVM, while reading /dev/cpu/0/msr returns I/O error since the MSR does not exist.
Hmm, do we need to get /dev/kvm fixed in this regard ? It seems bad that libvirt will be relying on different information about MSRs when running as root vs non-root. Could like to even more painful bugs to triage.
Hmm, actually we read any of those only if the corresponding CPUID bit is set, that is when the host CPU supports this MSR. So the problem with reading something from KVM when the MSR is not supported does not exist. However, we can still see more bits enabled when reading the MSR via KVM. So when libvirtd is unprivileged, it will show MSR features which can be emulated by KVM even in host capabilities (while normally we would only see them in domain capabilities). I don't think this should be a big deal. But I still think it's better to show the real results read from the host CPU when possible. Jirka

Jiri Denemark <jdenemar@redhat.com> [2019-04-08, 10:42AM +0200]:
@@ -1254,3 +1255,82 @@ virHostCPUGetMicrocodeVersion(void) }
#endif /* __linux__ */ + + +#if HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) +static int +virHostCPUGetMSRFromKVM(unsigned long index, + uint64_t *result) +{ + VIR_AUTOCLOSE fd = -1; + struct { + struct kvm_msrs header; + struct kvm_msr_entry entry; + } msr = { + .header = { .nmsrs = 1 }, + .entry = { .index = index }, + }; + + if ((fd = open(KVM_DEVICE, O_RDONLY)) < 0) { + virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE); + return -1; + } + + if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) { + VIR_DEBUG("Cannot get MSR 0x%lx from KVM", index); + return 1; + } + + *result = msr.entry.data; + return 0; +}
This breaks build on S390: ../../src/util/virhostcpu.c: In function 'virHostCPUGetMSRFromKVM': ../../src/util/virhostcpu.c:1267:25: error: field 'header' has incomplete type struct kvm_msrs header; ^~~~~~ ../../src/util/virhostcpu.c:1268:30: error: field 'entry' has incomplete type struct kvm_msr_entry entry; ^~~~~ ../../src/util/virhostcpu.c:1270:21: error: field name not in record or union initializer .header = { .nmsrs = 1 }, ^ ../../src/util/virhostcpu.c:1270:21: note: (near initialization for 'msr.header') ../../src/util/virhostcpu.c:1271:20: error: field name not in record or union initializer .entry = { .index = index }, ^ ../../src/util/virhostcpu.c:1271:20: note: (near initialization for 'msr.entry') In file included from /usr/include/asm/ioctl.h:1, from /usr/include/linux/ioctl.h:5, from /usr/include/asm-generic/ioctls.h:5, from /usr/include/asm/ioctls.h:7, from /usr/include/bits/ioctls.h:23, from /usr/include/sys/ioctl.h:26, from ../gnulib/lib/sys/ioctl.h:27, from ../../src/util/virhostcpu.c:27: ../../src/util/virhostcpu.c:1279:19: error: invalid application of 'sizeof' to incomplete type 'struct kvm_msrs' if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) { ^~~~~~~~~~~~

On 4/13/19 5:17 PM, Bjoern Walk wrote:
<snip/>
This breaks build on S390:
../../src/util/virhostcpu.c: In function 'virHostCPUGetMSRFromKVM': ../../src/util/virhostcpu.c:1267:25: error: field 'header' has incomplete type struct kvm_msrs header; ^~~~~~ ../../src/util/virhostcpu.c:1268:30: error: field 'entry' has incomplete type struct kvm_msr_entry entry; ^~~~~ ../../src/util/virhostcpu.c:1270:21: error: field name not in record or union initializer .header = { .nmsrs = 1 }, ^ ../../src/util/virhostcpu.c:1270:21: note: (near initialization for 'msr.header') ../../src/util/virhostcpu.c:1271:20: error: field name not in record or union initializer .entry = { .index = index }, ^ ../../src/util/virhostcpu.c:1271:20: note: (near initialization for 'msr.entry') In file included from /usr/include/asm/ioctl.h:1, from /usr/include/linux/ioctl.h:5, from /usr/include/asm-generic/ioctls.h:5, from /usr/include/asm/ioctls.h:7, from /usr/include/bits/ioctls.h:23, from /usr/include/sys/ioctl.h:26, from ../gnulib/lib/sys/ioctl.h:27, from ../../src/util/virhostcpu.c:27: ../../src/util/virhostcpu.c:1279:19: error: invalid application of 'sizeof' to incomplete type 'struct kvm_msrs' if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) {
Yep, it breaks the build on my arm box too. MSRs are specific to x86. I guess we need to put some more #ifdef-s in. Let me see if I can cook a patch. Michal

On Mon, Apr 08, 2019 at 10:42:38AM +0200, Jiri Denemark wrote:
The new virHostCPUGetMSR internal API will try to read the MSR from /dev/cpu/0/msr and if it is not possible (the device does not exist or libvirt is running unprivileged), it will fallback to asking KVM for the MSR using KVM_GET_MSRS ioctl.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virhostcpu.c | 80 ++++++++++++++++++++++++++++++++++++++++ src/util/virhostcpu.h | 3 ++ 3 files changed, 84 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 132ee3cae9..59a9a6f093 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2016,6 +2016,7 @@ virHostCPUGetInfo; virHostCPUGetKVMMaxVCPUs; virHostCPUGetMap; virHostCPUGetMicrocodeVersion; +virHostCPUGetMSR;
Hi, This breaks build on powerpc too. CC util/libvirt_util_la-virhook.lo CC util/libvirt_util_la-virhostcpu.lo util/virhostcpu.c: In function 'virHostCPUGetMSRFromKVM': util/virhostcpu.c:1267:25: error: field 'header' has incomplete type 1267 | struct kvm_msrs header; 2019-04-15 01:06:28,740 process L0458 DEBUG| [stdout] make[3]: Leaving directory '/usr/share/avocado-plugins-vt/build/libvirt/src' | ^~~~~~ 2019-04-15 01:06:28,741 process L0458 DEBUG| [stdout] make[2]: Leaving directory '/usr/share/avocado-plugins-vt/build/libvirt/src' util/virhostcpu.c:1268:30: error: field 'entry' has incomplete type 2019-04-15 01:06:28,742 process L0714 INFO | Command 'make' finished with 2 after 27.617787838s 2019-04-15 01:06:28,742 process L0458 DEBUG| [stdout] make[1]: Leaving directory '/usr/share/avocado-plugins-vt/build/libvirt' 1268 | struct kvm_msr_entry entry; | ^~~~~ util/virhostcpu.c:1270:21: error: field name not in record or union initializer 1270 | .header = { .nmsrs = 1 }, | ^ util/virhostcpu.c:1270:21: note: (near initialization for 'msr.header') util/virhostcpu.c:1271:20: error: field name not in record or union initializer 1271 | .entry = { .index = index }, | ^ util/virhostcpu.c:1271:20: note: (near initialization for 'msr.entry') In file included from /usr/include/asm/ioctl.h:12, from /usr/include/asm/ioctls.h:5, from /usr/include/bits/ioctls.h:23, from /usr/include/sys/ioctl.h:26, from ../gnulib/lib/sys/ioctl.h:27, from util/virhostcpu.c:27: util/virhostcpu.c:1279:19: error: invalid application of 'sizeof' to incomplete type 'struct kvm_msrs' 1279 | if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) { | ^~~~~~~~~~~~ make[3]: *** [Makefile:11963: util/libvirt_util_la-virhostcpu.lo] Error 1 make[2]: *** [Makefile:7128: all] Error 2 make[1]: *** [Makefile:2257: all-recursive] Error 1 make: *** [Makefile:2149: all] Error 2 Regards, -Satheesh
virHostCPUGetOnline; virHostCPUGetOnlineBitmap; virHostCPUGetPresentBitmap; diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c index 6514c3d765..10bf3a93d5 100644 --- a/src/util/virhostcpu.c +++ b/src/util/virhostcpu.c @@ -58,6 +58,7 @@ VIR_LOG_INIT("util.hostcpu");
#define KVM_DEVICE "/dev/kvm" +#define MSR_DEVICE "/dev/cpu/0/msr"
#if defined(__FreeBSD__) || defined(__APPLE__) @@ -1254,3 +1255,82 @@ virHostCPUGetMicrocodeVersion(void) }
#endif /* __linux__ */ + + +#if HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) +static int +virHostCPUGetMSRFromKVM(unsigned long index, + uint64_t *result) +{ + VIR_AUTOCLOSE fd = -1; + struct { + struct kvm_msrs header; + struct kvm_msr_entry entry; + } msr = { + .header = { .nmsrs = 1 }, + .entry = { .index = index }, + }; + + if ((fd = open(KVM_DEVICE, O_RDONLY)) < 0) { + virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE); + return -1; + } + + if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) { + VIR_DEBUG("Cannot get MSR 0x%lx from KVM", index); + return 1; + } + + *result = msr.entry.data; + return 0; +} + +#else + +static int +virHostCPUGetMSRFromKVM(unsigned long index ATTRIBUTE_UNUSED, + uint64_t *result ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Reading MSRs via KVM is not supported on this platform")); + return -1; +} +#endif /* HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) */ + + +/* + * Returns 0 on success, + * 1 when the MSR is not supported by the host CPU, +* -1 on error. + */ +int +virHostCPUGetMSR(unsigned long index, + uint64_t *msr) +{ + VIR_AUTOCLOSE fd = -1; + char ebuf[1024]; + + *msr = 0; + + if ((fd = open(MSR_DEVICE, O_RDONLY)) < 0) { + VIR_DEBUG("Unable to open %s: %s", + MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf))); + } else { + int rc = pread(fd, msr, sizeof(*msr), index); + + if (rc == sizeof(*msr)) + return 0; + + if (rc < 0 && errno == EIO) { + VIR_DEBUG("CPU does not support MSR 0x%lx", index); + return 1; + } + + VIR_DEBUG("Cannot read MSR 0x%lx from %s: %s", + index, MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf))); + } + + VIR_DEBUG("Falling back to KVM ioctl"); + + return virHostCPUGetMSRFromKVM(index, msr); +} diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h index df6a7e789d..0d20dbef61 100644 --- a/src/util/virhostcpu.h +++ b/src/util/virhostcpu.h @@ -66,4 +66,7 @@ int virHostCPUGetOnline(unsigned int cpu, bool *online);
unsigned int virHostCPUGetMicrocodeVersion(void);
+int virHostCPUGetMSR(unsigned long index, + uint64_t *msr); + #endif /* LIBVIRT_VIRHOSTCPU_H */ -- 2.21.0
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

This is used by the host capabilities code to construct host CPU definition. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 1fe6770d57..74385f7992 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -2759,6 +2759,30 @@ virCPUx86GetHost(virCPUDefPtr cpu, cpuidSet(CPUX86_EXTENDED, cpuData) < 0) goto cleanup; + /* Read the IA32_ARCH_CAPABILITIES MSR (0x10a) if supported. + * This is best effort since there might be no way to read the MSR. */ + if (virCPUx86DataCheckFeature(cpuData, "arch-capabilities") == 1) { + uint64_t msr; + unsigned long index = 0x10a; + int rc = virHostCPUGetMSR(index, &msr); + + if (rc < 0) { + virResetLastError(); + } else if (rc == 0) { + virCPUx86DataItem item = { + .type = VIR_CPU_X86_DATA_MSR, + .data.msr = { + .index = index, + .eax = msr & 0xffffffff, + .edx = msr >> 32, + }, + }; + + if (virCPUx86DataAdd(cpuData, &item) < 0) + return -1; + } + } + ret = x86DecodeCPUData(cpu, cpuData, models); cpu->microcodeVersion = virHostCPUGetMicrocodeVersion(); -- 2.21.0

On Mon, Apr 08, 2019 at 10:42:39AM +0200, Jiri Denemark wrote:
This is used by the host capabilities code to construct host CPU definition.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 1fe6770d57..74385f7992 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -2759,6 +2759,30 @@ virCPUx86GetHost(virCPUDefPtr cpu, cpuidSet(CPUX86_EXTENDED, cpuData) < 0) goto cleanup;
+ /* Read the IA32_ARCH_CAPABILITIES MSR (0x10a) if supported. + * This is best effort since there might be no way to read the MSR. */ + if (virCPUx86DataCheckFeature(cpuData, "arch-capabilities") == 1) { + uint64_t msr; + unsigned long index = 0x10a; + int rc = virHostCPUGetMSR(index, &msr); + + if (rc < 0) { + virResetLastError();
Using virResetLastError in a place other than starting a public API seems fishy. If we're ignoring the error, we should not have logged it in the first place.
+ } else if (rc == 0) { + virCPUx86DataItem item = { + .type = VIR_CPU_X86_DATA_MSR, + .data.msr = { + .index = index, + .eax = msr & 0xffffffff, + .edx = msr >> 32, + }, + }; + + if (virCPUx86DataAdd(cpuData, &item) < 0) + return -1; + } + } + ret = x86DecodeCPUData(cpu, cpuData, models); cpu->microcodeVersion = virHostCPUGetMicrocodeVersion();
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

--- This should not be pushed yet as the QEMU interface for MSR features is not complete yet. If a domain with some MSR features enabled would be started, all of them would be marked as disabled in the live domain configuration (even though they were actually enabled by QEMU) and they would disappear during migration. src/cpu_map/x86_features.xml | 17 +++++++++++++++++ .../x86_64-cpuid-Core-i7-7600U-enabled.xml | 1 + .../x86_64-cpuid-Core-i7-7600U-json.xml | 1 + .../x86_64-cpuid-Xeon-Platinum-8268-enabled.xml | 1 + .../x86_64-cpuid-Xeon-Platinum-8268-guest.xml | 3 +++ .../x86_64-cpuid-Xeon-Platinum-8268-host.xml | 3 +++ .../x86_64-cpuid-Xeon-Platinum-8268-json.xml | 3 +++ .../domaincapsschemadata/qemu_3.1.0.x86_64.xml | 1 + .../domaincapsschemadata/qemu_4.0.0.x86_64.xml | 1 + 9 files changed, 31 insertions(+) diff --git a/src/cpu_map/x86_features.xml b/src/cpu_map/x86_features.xml index 02431bea29..d73a30017f 100644 --- a/src/cpu_map/x86_features.xml +++ b/src/cpu_map/x86_features.xml @@ -476,4 +476,21 @@ <feature name='amd-no-ssb'> <cpuid eax_in='0x80000008' ebx='0x04000000'/> </feature> + + <!-- IA32_ARCH_CAPABILITIES features --> + <feature name='rdctl-no'> + <msr index='0x10a' edx='0x00000000' eax='0x00000001'/> + </feature> + <feature name='ibrs-all'> + <msr index='0x10a' edx='0x00000000' eax='0x00000002'/> + </feature> + <feature name='rsba'> + <msr index='0x10a' edx='0x00000000' eax='0x00000004'/> + </feature> + <feature name='skip-l1dfl-vmentry'> + <msr index='0x10a' edx='0x00000000' eax='0x00000008'/> + </feature> + <feature name='ssb-no'> + <msr index='0x10a' edx='0x00000000' eax='0x00000010'/> + </feature> </cpus> diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml index b1cdaa802a..58bc84577c 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml @@ -5,4 +5,5 @@ <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x009c4fbb' ecx='0x00000004' edx='0x84000000'/> <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/> + <msr index='0x10a' edx='0x00000000' eax='0x00000008'/> </cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml index 48089c6003..690081493b 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml @@ -10,4 +10,5 @@ <feature policy='require' name='ssbd'/> <feature policy='require' name='xsaves'/> <feature policy='require' name='pdpe1gb'/> + <feature policy='require' name='skip-l1dfl-vmentry'/> </cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml index 434ac1956a..313009b156 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml @@ -5,4 +5,5 @@ <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0xd19f4fbb' ecx='0x0000080c' edx='0x84000000'/> <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/> + <msr index='0x10a' edx='0x00000000' eax='0x0000000b'/> </cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml index cc1fc90c45..d401230a87 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml @@ -29,4 +29,7 @@ <feature policy='require' name='mbm_total'/> <feature policy='require' name='mbm_local'/> <feature policy='require' name='invtsc'/> + <feature policy='require' name='rdctl-no'/> + <feature policy='require' name='ibrs-all'/> + <feature policy='require' name='skip-l1dfl-vmentry'/> </cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml index dfabdc57c7..e96712533a 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml @@ -30,4 +30,7 @@ <feature name='mbm_total'/> <feature name='mbm_local'/> <feature name='invtsc'/> + <feature name='rdctl-no'/> + <feature name='ibrs-all'/> + <feature name='skip-l1dfl-vmentry'/> </cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml index b7d12dced7..78863c61d1 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml @@ -7,4 +7,7 @@ <feature policy='require' name='umip'/> <feature policy='require' name='pku'/> <feature policy='require' name='xsaves'/> + <feature policy='require' name='rdctl-no'/> + <feature policy='require' name='ibrs-all'/> + <feature policy='require' name='skip-l1dfl-vmentry'/> </cpu> diff --git a/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml b/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml index f49da218e2..cd816d816d 100644 --- a/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml +++ b/tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml @@ -35,6 +35,7 @@ <feature policy='require' name='xsaves'/> <feature policy='require' name='pdpe1gb'/> <feature policy='require' name='invtsc'/> + <feature policy='require' name='skip-l1dfl-vmentry'/> </mode> <mode name='custom' supported='yes'> <model usable='yes'>qemu64</model> diff --git a/tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml b/tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml index 84c33437a2..7b563d8dc0 100644 --- a/tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml +++ b/tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml @@ -35,6 +35,7 @@ <feature policy='require' name='xsaves'/> <feature policy='require' name='pdpe1gb'/> <feature policy='require' name='invtsc'/> + <feature policy='require' name='skip-l1dfl-vmentry'/> </mode> <mode name='custom' supported='yes'> <model usable='yes'>qemu64</model> -- 2.21.0
participants (6)
-
Bjoern Walk
-
Daniel P. Berrangé
-
Jiri Denemark
-
Ján Tomko
-
Michal Prívozník
-
Satheesh Rajendran