forked from rpms/qemu-kvm
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
8.8 KiB
225 lines
8.8 KiB
1 month ago
|
From 704bfed342ca7cfbef44b639aadfeada1841b091 Mon Sep 17 00:00:00 2001
|
||
|
From: Tao Su <tao1.su@linux.intel.com>
|
||
|
Date: Thu, 31 Oct 2024 16:52:29 +0800
|
||
|
Subject: [PATCH 33/38] target/i386: add AVX10 feature and AVX10 version
|
||
|
property
|
||
|
|
||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
RH-MergeRequest: 280: Add support for the AVX10.1, SHA512, SM3 and SM4 instruction sets
|
||
|
RH-Jira: RHEL-30315 RHEL-45110
|
||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||
|
RH-Commit: [4/9] 8101218e0a5789770fcef7ca277f7b39df48f176 (bonzini/rhel-qemu-kvm)
|
||
|
|
||
|
When AVX10 enable bit is set, the 0x24 leaf will be present as "AVX10
|
||
|
Converged Vector ISA leaf" containing fields for the version number and
|
||
|
the supported vector bit lengths.
|
||
|
|
||
|
Introduce avx10-version property so that avx10 version can be controlled
|
||
|
by user and cpu model. Per spec, avx10 version can never be 0, the default
|
||
|
value of avx10-version is set to 0 to determine whether it is specified by
|
||
|
user. The default can come from the device model or, for the max model,
|
||
|
from KVM's reported value.
|
||
|
|
||
|
Signed-off-by: Tao Su <tao1.su@linux.intel.com>
|
||
|
Link: https://lore.kernel.org/r/20241028024512.156724-3-tao1.su@linux.intel.com
|
||
|
Link: https://lore.kernel.org/r/20241028024512.156724-4-tao1.su@linux.intel.com
|
||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
Tested-by: Xuelian Guo <xuelian.guo@intel.com>
|
||
|
Link: https://lore.kernel.org/r/20241031085233.425388-5-tao1.su@linux.intel.com
|
||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
(cherry picked from commit bccfb846fd52d6f20704ecfa4d01b60b43c6f640)
|
||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
---
|
||
|
target/i386/cpu.c | 64 ++++++++++++++++++++++++++++++++++++++-----
|
||
|
target/i386/cpu.h | 4 +++
|
||
|
target/i386/kvm/kvm.c | 3 +-
|
||
|
3 files changed, 63 insertions(+), 8 deletions(-)
|
||
|
|
||
|
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
||
|
index 353f50a1b9..a2e1a18537 100644
|
||
|
--- a/target/i386/cpu.c
|
||
|
+++ b/target/i386/cpu.c
|
||
|
@@ -47,6 +47,9 @@
|
||
|
#include "cpu-internal.h"
|
||
|
|
||
|
static void x86_cpu_realizefn(DeviceState *dev, Error **errp);
|
||
|
+static void x86_cpu_get_supported_cpuid(uint32_t func, uint32_t index,
|
||
|
+ uint32_t *eax, uint32_t *ebx,
|
||
|
+ uint32_t *ecx, uint32_t *edx);
|
||
|
|
||
|
/* Helpers for building CPUID[2] descriptors: */
|
||
|
|
||
|
@@ -1133,7 +1136,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||
|
"avx-vnni-int8", "avx-ne-convert", NULL, NULL,
|
||
|
"amx-complex", NULL, "avx-vnni-int16", NULL,
|
||
|
NULL, NULL, "prefetchiti", NULL,
|
||
|
- NULL, NULL, NULL, NULL,
|
||
|
+ NULL, NULL, NULL, "avx10",
|
||
|
NULL, NULL, NULL, NULL,
|
||
|
NULL, NULL, NULL, NULL,
|
||
|
NULL, NULL, NULL, NULL,
|
||
|
@@ -1961,6 +1964,7 @@ typedef struct X86CPUDefinition {
|
||
|
int family;
|
||
|
int model;
|
||
|
int stepping;
|
||
|
+ uint8_t avx10_version;
|
||
|
FeatureWordArray features;
|
||
|
const char *model_id;
|
||
|
const CPUCaches *const cache_info;
|
||
|
@@ -6326,6 +6330,9 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model)
|
||
|
*/
|
||
|
object_property_set_str(OBJECT(cpu), "vendor", def->vendor, &error_abort);
|
||
|
|
||
|
+ object_property_set_uint(OBJECT(cpu), "avx10-version", def->avx10_version,
|
||
|
+ &error_abort);
|
||
|
+
|
||
|
x86_cpu_apply_version_props(cpu, model);
|
||
|
|
||
|
/*
|
||
|
@@ -6854,6 +6861,16 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
+ case 0x24: {
|
||
|
+ *eax = 0;
|
||
|
+ *ebx = 0;
|
||
|
+ *ecx = 0;
|
||
|
+ *edx = 0;
|
||
|
+ if ((env->features[FEAT_7_1_EDX] & CPUID_7_1_EDX_AVX10) && count == 0) {
|
||
|
+ *ebx = env->features[FEAT_24_0_EBX] | env->avx10_version;
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ }
|
||
|
case 0x40000000:
|
||
|
/*
|
||
|
* CPUID code in kvm_arch_init_vcpu() ignores stuff
|
||
|
@@ -7434,6 +7451,12 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
|
||
|
~env->user_features[w] &
|
||
|
~feature_word_info[w].no_autoenable_flags;
|
||
|
}
|
||
|
+
|
||
|
+ if ((env->features[FEAT_7_1_EDX] & CPUID_7_1_EDX_AVX10) && !env->avx10_version) {
|
||
|
+ uint32_t eax, ebx, ecx, edx;
|
||
|
+ x86_cpu_get_supported_cpuid(0x24, 0, &eax, &ebx, &ecx, &edx);
|
||
|
+ env->avx10_version = ebx & 0xff;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) {
|
||
|
@@ -7497,6 +7520,11 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
|
||
|
x86_cpu_adjust_level(cpu, &env->cpuid_min_level, 0x1F);
|
||
|
}
|
||
|
|
||
|
+ /* Advanced Vector Extensions 10 (AVX10) requires CPUID[0x24] */
|
||
|
+ if (env->features[FEAT_7_1_EDX] & CPUID_7_1_EDX_AVX10) {
|
||
|
+ x86_cpu_adjust_level(cpu, &env->cpuid_min_level, 0x24);
|
||
|
+ }
|
||
|
+
|
||
|
/* SVM requires CPUID[0x8000000A] */
|
||
|
if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
|
||
|
x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A);
|
||
|
@@ -7547,6 +7575,10 @@ static bool x86_cpu_filter_features(X86CPU *cpu, bool verbose)
|
||
|
CPUX86State *env = &cpu->env;
|
||
|
FeatureWord w;
|
||
|
const char *prefix = NULL;
|
||
|
+ bool have_filtered_features;
|
||
|
+
|
||
|
+ uint32_t eax_0, ebx_0, ecx_0, edx_0;
|
||
|
+ uint32_t eax_1, ebx_1, ecx_1, edx_1;
|
||
|
|
||
|
if (verbose) {
|
||
|
prefix = accel_uses_host_cpuid()
|
||
|
@@ -7568,13 +7600,10 @@ static bool x86_cpu_filter_features(X86CPU *cpu, bool verbose)
|
||
|
*/
|
||
|
if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) &&
|
||
|
kvm_enabled()) {
|
||
|
- uint32_t eax_0, ebx_0, ecx_0, edx_0_unused;
|
||
|
- uint32_t eax_1, ebx_1, ecx_1_unused, edx_1_unused;
|
||
|
-
|
||
|
x86_cpu_get_supported_cpuid(0x14, 0,
|
||
|
- &eax_0, &ebx_0, &ecx_0, &edx_0_unused);
|
||
|
+ &eax_0, &ebx_0, &ecx_0, &edx_0);
|
||
|
x86_cpu_get_supported_cpuid(0x14, 1,
|
||
|
- &eax_1, &ebx_1, &ecx_1_unused, &edx_1_unused);
|
||
|
+ &eax_1, &ebx_1, &ecx_1, &edx_1);
|
||
|
|
||
|
if (!eax_0 ||
|
||
|
((ebx_0 & INTEL_PT_MINIMAL_EBX) != INTEL_PT_MINIMAL_EBX) ||
|
||
|
@@ -7595,7 +7624,27 @@ static bool x86_cpu_filter_features(X86CPU *cpu, bool verbose)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- return x86_cpu_have_filtered_features(cpu);
|
||
|
+ have_filtered_features = x86_cpu_have_filtered_features(cpu);
|
||
|
+
|
||
|
+ if (env->features[FEAT_7_1_EDX] & CPUID_7_1_EDX_AVX10) {
|
||
|
+ x86_cpu_get_supported_cpuid(0x24, 0,
|
||
|
+ &eax_0, &ebx_0, &ecx_0, &edx_0);
|
||
|
+ uint8_t version = ebx_0 & 0xff;
|
||
|
+
|
||
|
+ if (version < env->avx10_version) {
|
||
|
+ if (prefix) {
|
||
|
+ warn_report("%s: avx10.%d. Adjust to avx10.%d",
|
||
|
+ prefix, env->avx10_version, version);
|
||
|
+ }
|
||
|
+ env->avx10_version = version;
|
||
|
+ have_filtered_features = true;
|
||
|
+ }
|
||
|
+ } else if (env->avx10_version && prefix) {
|
||
|
+ warn_report("%s: avx10.%d.", prefix, env->avx10_version);
|
||
|
+ have_filtered_features = true;
|
||
|
+ }
|
||
|
+
|
||
|
+ return have_filtered_features;
|
||
|
}
|
||
|
|
||
|
static void x86_cpu_hyperv_realize(X86CPU *cpu)
|
||
|
@@ -8376,6 +8425,7 @@ static Property x86_cpu_properties[] = {
|
||
|
DEFINE_PROP_UINT32("min-level", X86CPU, env.cpuid_min_level, 0),
|
||
|
DEFINE_PROP_UINT32("min-xlevel", X86CPU, env.cpuid_min_xlevel, 0),
|
||
|
DEFINE_PROP_UINT32("min-xlevel2", X86CPU, env.cpuid_min_xlevel2, 0),
|
||
|
+ DEFINE_PROP_UINT8("avx10-version", X86CPU, env.avx10_version, 0),
|
||
|
DEFINE_PROP_UINT64("ucode-rev", X86CPU, ucode_rev, 0),
|
||
|
DEFINE_PROP_BOOL("full-cpuid-auto-level", X86CPU, full_cpuid_auto_level, true),
|
||
|
DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor),
|
||
|
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
|
||
|
index 14edd57a37..591113349d 100644
|
||
|
--- a/target/i386/cpu.h
|
||
|
+++ b/target/i386/cpu.h
|
||
|
@@ -972,6 +972,8 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w);
|
||
|
#define CPUID_7_1_EDX_AMX_COMPLEX (1U << 8)
|
||
|
/* PREFETCHIT0/1 Instructions */
|
||
|
#define CPUID_7_1_EDX_PREFETCHITI (1U << 14)
|
||
|
+/* Support for Advanced Vector Extensions 10 */
|
||
|
+#define CPUID_7_1_EDX_AVX10 (1U << 19)
|
||
|
/* Flexible return and event delivery (FRED) */
|
||
|
#define CPUID_7_1_EAX_FRED (1U << 17)
|
||
|
/* Load into IA32_KERNEL_GS_BASE (LKGS) */
|
||
|
@@ -1914,6 +1916,8 @@ typedef struct CPUArchState {
|
||
|
uint32_t cpuid_vendor3;
|
||
|
uint32_t cpuid_version;
|
||
|
FeatureWordArray features;
|
||
|
+ /* AVX10 version */
|
||
|
+ uint8_t avx10_version;
|
||
|
/* Features that were explicitly enabled/disabled */
|
||
|
FeatureWordArray user_features;
|
||
|
uint32_t cpuid_model[12];
|
||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||
|
index 814f93da19..d0329a4ed7 100644
|
||
|
--- a/target/i386/kvm/kvm.c
|
||
|
+++ b/target/i386/kvm/kvm.c
|
||
|
@@ -1891,7 +1891,8 @@ static uint32_t kvm_x86_build_cpuid(CPUX86State *env,
|
||
|
case 0x7:
|
||
|
case 0x14:
|
||
|
case 0x1d:
|
||
|
- case 0x1e: {
|
||
|
+ case 0x1e:
|
||
|
+ case 0x24: {
|
||
|
uint32_t times;
|
||
|
|
||
|
c->function = i;
|
||
|
--
|
||
|
2.39.3
|
||
|
|