@@ -1117,7 +1117,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
NULL, NULL, "pts", NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "hfi",
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
@@ -1125,10 +1125,10 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
.cpuid = { .eax = 6, .reg = R_EAX, },
.tcg_features = TCG_6_EAX_FEATURES,
/*
- * PTS shouldn't be enabled by default since it has
+ * PTS and HFI shouldn't be enabled by default since they have
* requirement for cpu topology.
*/
- .no_autoenable_flags = CPUID_6_EAX_PTS,
+ .no_autoenable_flags = CPUID_6_EAX_PTS | CPUID_6_EAX_HFI,
},
[FEAT_XSAVE_XCR0_LO] = {
.type = CPUID_FEATURE_WORD,
@@ -1557,6 +1557,18 @@ static FeatureDep feature_dependencies[] = {
.from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE },
.to = { FEAT_7_0_ECX, CPUID_7_0_ECX_WAITPKG },
},
+ {
+ .from = { FEAT_1_EDX, CPUID_ACPI },
+ .to = { FEAT_6_EAX, CPUID_6_EAX_HFI },
+ },
+ {
+ .from = { FEAT_1_EDX, CPUID_TM },
+ .to = { FEAT_6_EAX, CPUID_6_EAX_HFI },
+ },
+ {
+ .from = { FEAT_6_EAX, CPUID_6_EAX_PTS },
+ .to = { FEAT_6_EAX, CPUID_6_EAX_HFI },
+ },
};
typedef struct X86RegisterInfo32 {
@@ -6158,6 +6170,25 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*ebx = 0;
*ecx = 0;
*edx = 0;
+ /*
+ * KVM only supports HFI virtualization with ITD, so
+ * set the HFI information only if the ITD is enabled.
+ */
+ if (*eax & CPUID_6_EAX_ITD) {
+ if (kvm_enabled()) {
+ *ecx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x6,
+ count, R_ECX);
+ /*
+ * No need to adjust the number of pages since the default
+ * 1 4KB page is enough to hold the HFI entries of max_cpus
+ * (1024) supported by i386 machine (q35).
+ */
+ *edx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x6,
+ count, R_EDX);
+ /* Set HFI table index as CPU index. */
+ *edx |= cs->cpu_index << 16;
+ }
+ }
break;
case 7:
/* Structured Extended Feature Flags Enumeration Leaf */
@@ -7437,11 +7468,19 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
return;
}
- if (env->features[FEAT_6_EAX] & CPUID_6_EAX_PTS &&
+ if (env->features[FEAT_6_EAX] & CPUID_6_EAX_HFI &&
+ (ms->smp.dies > 1 || ms->smp.sockets > 1)) {
+ error_setg(errp,
+ "HFI currently only supports die/package, "
+ "please set by \"-smp ...,sockets=1,dies=1\"");
+ return;
+ }
+
+ if (env->features[FEAT_6_EAX] & (CPUID_6_EAX_PTS | CPUID_6_EAX_HFI) &&
!(env->features[FEAT_6_EAX] & CPUID_6_EAX_ITD)) {
error_setg(errp,
"In the absence of ITD, Guest does "
- "not need PTS");
+ "not need PTS/HFI");
return;
}
#endif
@@ -533,6 +533,9 @@ typedef enum X86Seg {
#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1
#define MSR_IA32_PACKAGE_THERM_INTERRUPT 0x000001b2
+#define MSR_IA32_HW_FEEDBACK_CONFIG 0x000017d0
+#define MSR_IA32_HW_FEEDBACK_PTR 0x000017d1
+
#define MSR_IA32_VMX_BASIC 0x00000480
#define MSR_IA32_VMX_PINBASED_CTLS 0x00000481
#define MSR_IA32_VMX_PROCBASED_CTLS 0x00000482
@@ -986,6 +989,7 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
#define CPUID_6_EAX_ARAT (1U << 2)
#define CPUID_6_EAX_PTS (1U << 6)
+#define CPUID_6_EAX_HFI (1U << 19)
#define CPUID_6_EAX_ITD (1U << 23)
/* CPUID[0x80000007].EDX flags: */
@@ -1773,12 +1777,14 @@ typedef struct CPUArchState {
uint64_t therm_status;
/*
- * Although these are package level MSRs, for the PTS feature, we
+ * Although these are package level MSRs, for the PTS/HFI feature, we
* temporarily limit it to be enabled for only 1 package, so the value
* of each vCPU is same and it's enough to support the save/load.
*/
uint64_t pkg_therm_interrupt;
uint64_t pkg_therm_status;
+ uint64_t hfi_config;
+ uint64_t hfi_ptr;
/* exception/interrupt handling */
int error_code;
@@ -140,6 +140,7 @@ static bool has_msr_perf_capabs;
static bool has_msr_pkrs;
static bool has_msr_therm;
static bool has_msr_pkg_therm;
+static bool has_msr_hfi;
static uint32_t has_architectural_pmu_version;
static uint32_t num_architectural_pmu_gp_counters;
@@ -2466,6 +2467,10 @@ static int kvm_get_supported_msrs(KVMState *s)
case MSR_IA32_PACKAGE_THERM_INTERRUPT:
has_msr_pkg_therm = true;
break;
+ case MSR_IA32_HW_FEEDBACK_CONFIG:
+ case MSR_IA32_HW_FEEDBACK_PTR:
+ has_msr_hfi = true;
+ break;
}
}
}
@@ -3326,6 +3331,12 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
kvm_msr_entry_add(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
env->therm_interrupt);
}
+ if (has_msr_hfi) {
+ kvm_msr_entry_add(cpu, MSR_IA32_HW_FEEDBACK_CONFIG,
+ env->hfi_config);
+ kvm_msr_entry_add(cpu, MSR_IA32_HW_FEEDBACK_PTR,
+ env->hfi_ptr);
+ }
}
#ifdef TARGET_X86_64
@@ -3808,6 +3819,10 @@ static int kvm_get_msrs(X86CPU *cpu)
kvm_msr_entry_add(cpu, MSR_IA32_PACKAGE_THERM_STATUS, 0);
kvm_msr_entry_add(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, 0);
}
+ if (has_msr_hfi) {
+ kvm_msr_entry_add(cpu, MSR_IA32_HW_FEEDBACK_CONFIG, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_HW_FEEDBACK_PTR, 0);
+ }
#ifdef TARGET_X86_64
if (lm_capable_kernel) {
@@ -4304,6 +4319,12 @@ static int kvm_get_msrs(X86CPU *cpu)
case MSR_IA32_PACKAGE_THERM_INTERRUPT:
env->pkg_therm_interrupt = msrs[i].data;
break;
+ case MSR_IA32_HW_FEEDBACK_CONFIG:
+ env->hfi_config = msrs[i].data;
+ break;
+ case MSR_IA32_HW_FEEDBACK_PTR:
+ env->hfi_ptr = msrs[i].data;
+ break;
}
}