[2] As mentioned in [1], QEMU always sets the vCPU's vendor to match the host's
vendor
when acceleration (KVM or HVF) is enabled. Therefore, if users want to emulate a
Zhaoxin CPU on an Intel host, the vendor must be set manually.Furthermore,
should we display a warning to users who enable both vPMU and KVM acceleration
but do not manually set the guest vendor when it differs from the host vendor?
Maybe not? Sometimes I emulate AMD on Intel host, while vendor is still the
default :)
Okay, handling this situation can be rather complex, so let's keep it simple. I
have added a dedicated function to capture the intended behavior for potential
future reference.
Anyway, Thanks for taking Zhaoxin's situation into account, regardless.
+/*
+ * check_vendor_compatibility_and_warn() returns true if the host and
+ * guest vendors are compatible for vPMU virtualization. In addition, if
+ * the guest vendor is not explicitly set in a cross-vendor emulation
+ * scenario (e.g., a Zhaoxin host emulating an Intel guest or vice versa),
+ * it issues a warning.
+ */
+static bool check_vendor_compatibility_and_warn(CPUX86State *env)
+{
+ char host_vendor[CPUID_VENDOR_SZ + 1];
+ uint32_t host_cpuid_vendor1, host_cpuid_vendor2, host_cpuid_vendor3;
+
+ /* Retrieve host vendor info */
+ host_cpuid(0x0, 0, NULL, &host_cpuid_vendor1, &host_cpuid_vendor3,
+ &host_cpuid_vendor2);
+ x86_cpu_vendor_words2str(host_vendor, host_cpuid_vendor1,
+ host_cpuid_vendor2, host_cpuid_vendor3);
+
+ /*
+ * Case A:
+ * If the host vendor is Intel or Zhaoxin and the guest CPU type is
+ * either Intel or Zhaoxin, consider them compatible. However, if a
+ * cross-vendor scenario is detected (e.g., host is Zhaoxin but guest is
+ * Intel, or vice versa) and the guest vendor fields have not been
+ * overridden (i.e., they still match the host), then warn the user.
+ */
+ if ((g_str_equal(host_vendor, CPUID_VENDOR_INTEL) ||
+ g_str_equal(host_vendor, CPUID_VENDOR_ZHAOXIN1) ||
+ g_str_equal(host_vendor, CPUID_VENDOR_ZHAOXIN2)) &&
+ (IS_INTEL_CPU(env) || IS_ZHAOXIN_CPU(env)))
+ {
+ if ((g_str_equal(host_vendor, CPUID_VENDOR_ZHAOXIN1) ||
+ g_str_equal(host_vendor, CPUID_VENDOR_ZHAOXIN2)) &&
+ IS_INTEL_CPU(env) &&
+ (env->cpuid_vendor1 == host_cpuid_vendor1 &&
+ env->cpuid_vendor2 == host_cpuid_vendor2 &&
+ env->cpuid_vendor3 == host_cpuid_vendor3))
+ {
+ warning_report("vPMU emulation will fail because the guest vendor "
+ "is not explicitly set. Use '-cpu,vendor=Intel' to
"
+ "emulate Intel vPMU on a Zhaoxin host.");
+ }
+ else if (g_str_equal(host_vendor, CPUID_VENDOR_INTEL) &&
+ IS_ZHAOXIN_CPU(env) &&
+ (env->cpuid_vendor1 == host_cpuid_vendor1 &&
+ env->cpuid_vendor2 == host_cpuid_vendor2 &&
+ env->cpuid_vendor3 == host_cpuid_vendor3))
+ {
+ warning_report("vPMU emulation will fail because the guest vendor"
+ "is not explicitly set. Use '-cpu,vendor=Zhaoxin' "
+ "to emulate Zhaoxin vPMU on an Intel host.");
+ }
+ return true;
+ }
+
+ /*
+ * Case B:
+ * For other CPU types, if the guest vendor fields exactly match the host,
+ * consider them compatible.
+ */
+ if (env->cpuid_vendor1 == host_cpuid_vendor1 &&
+ env->cpuid_vendor2 == host_cpuid_vendor2 &&
+ env->cpuid_vendor3 == host_cpuid_vendor3)
+ {
+ return true;
+ }
+
+ return false;
+}
+