[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH 04/23] i386/kvm: Move architectural CPUID leaf generation to
From: |
Isaku Yamahata |
Subject: |
[RFC PATCH 04/23] i386/kvm: Move architectural CPUID leaf generation to separarte helper |
Date: |
Mon, 15 Feb 2021 18:13:00 -0800 |
From: Sean Christopherson <sean.j.christopherson@intel.com>
Move the architectural (for lack of a better term) CPUID leaf generation
to a separate helper so that the generation code can be reused by TDX,
which needs to generate a canonical VM-scoped configuration.
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
target/i386/kvm/kvm.c | 170 +++++++++++++++++++------------------
target/i386/kvm/kvm_i386.h | 4 +
2 files changed, 93 insertions(+), 81 deletions(-)
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 8a04cf1337..bb241d8aa1 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -1461,82 +1461,11 @@ static int hyperv_init_vcpu(X86CPU *cpu)
static Error *invtsc_mig_blocker;
-#define KVM_MAX_CPUID_ENTRIES 100
-
-int kvm_arch_init_vcpu(CPUState *cs)
+uint32_t kvm_x86_arch_cpuid(CPUX86State *env, struct kvm_cpuid_entry2 *entries,
+ uint32_t cpuid_i)
{
- struct {
- struct kvm_cpuid2 cpuid;
- struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES];
- } cpuid_data;
- /*
- * The kernel defines these structs with padding fields so there
- * should be no extra padding in our cpuid_data struct.
- */
- QEMU_BUILD_BUG_ON(sizeof(cpuid_data) !=
- sizeof(struct kvm_cpuid2) +
- sizeof(struct kvm_cpuid_entry2) * KVM_MAX_CPUID_ENTRIES);
-
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- uint32_t limit, i, j, cpuid_i;
- uint32_t unused;
+ uint32_t limit, i, j, unused;
struct kvm_cpuid_entry2 *c;
- uint32_t signature[3];
- int kvm_base = KVM_CPUID_SIGNATURE;
- int max_nested_state_len;
- int r;
- Error *local_err = NULL;
-
- memset(&cpuid_data, 0, sizeof(cpuid_data));
-
- cpuid_i = 0;
-
- r = kvm_arch_set_tsc_khz(cs);
- if (r < 0) {
- return r;
- }
-
- /* vcpu's TSC frequency is either specified by user, or following
- * the value used by KVM if the former is not present. In the
- * latter case, we query it from KVM and record in env->tsc_khz,
- * so that vcpu's TSC frequency can be migrated later via this field.
- */
- if (!env->tsc_khz) {
- r = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
- kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
- -ENOTSUP;
- if (r > 0) {
- env->tsc_khz = r;
- }
- }
-
- env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY;
-
- /* Paravirtualization CPUIDs */
- r = hyperv_handle_properties(cs, cpuid_data.entries);
- if (r < 0) {
- return r;
- } else if (r > 0) {
- cpuid_i = r;
- kvm_base = KVM_CPUID_SIGNATURE_NEXT;
- has_msr_hv_hypercall = true;
- }
-
- if (cpu->expose_kvm) {
- memcpy(signature, "KVMKVMKVM\0\0\0", 12);
- c = &cpuid_data.entries[cpuid_i++];
- c->function = KVM_CPUID_SIGNATURE | kvm_base;
- c->eax = KVM_CPUID_FEATURES | kvm_base;
- c->ebx = signature[0];
- c->ecx = signature[1];
- c->edx = signature[2];
-
- c = &cpuid_data.entries[cpuid_i++];
- c->function = KVM_CPUID_FEATURES | kvm_base;
- c->eax = env->features[FEAT_KVM];
- c->edx = env->features[FEAT_KVM_HINTS];
- }
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
@@ -1545,7 +1474,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
fprintf(stderr, "unsupported level value: 0x%x\n", limit);
abort();
}
- c = &cpuid_data.entries[cpuid_i++];
+ c = &entries[cpuid_i++];
switch (i) {
case 2: {
@@ -1564,7 +1493,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
"cpuid(eax:2):eax & 0xf = 0x%x\n", times);
abort();
}
- c = &cpuid_data.entries[cpuid_i++];
+ c = &entries[cpuid_i++];
c->function = i;
c->flags = KVM_CPUID_FLAG_STATEFUL_FUNC;
cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
@@ -1610,7 +1539,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
"cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
abort();
}
- c = &cpuid_data.entries[cpuid_i++];
+ c = &entries[cpuid_i++];
}
break;
case 0x7:
@@ -1629,7 +1558,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
"cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
abort();
}
- c = &cpuid_data.entries[cpuid_i++];
+ c = &entries[cpuid_i++];
c->function = i;
c->index = j;
c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
@@ -1686,7 +1615,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
fprintf(stderr, "unsupported xlevel value: 0x%x\n", limit);
abort();
}
- c = &cpuid_data.entries[cpuid_i++];
+ c = &entries[cpuid_i++];
switch (i) {
case 0x8000001d:
@@ -1705,7 +1634,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
"cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
abort();
}
- c = &cpuid_data.entries[cpuid_i++];
+ c = &entries[cpuid_i++];
}
break;
default:
@@ -1732,7 +1661,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
fprintf(stderr, "unsupported xlevel2 value: 0x%x\n", limit);
abort();
}
- c = &cpuid_data.entries[cpuid_i++];
+ c = &entries[cpuid_i++];
c->function = i;
c->flags = 0;
@@ -1740,6 +1669,85 @@ int kvm_arch_init_vcpu(CPUState *cs)
}
}
+ return cpuid_i;
+}
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+ struct {
+ struct kvm_cpuid2 cpuid;
+ struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES];
+ } cpuid_data;
+ /*
+ * The kernel defines these structs with padding fields so there
+ * should be no extra padding in our cpuid_data struct.
+ */
+ QEMU_BUILD_BUG_ON(sizeof(cpuid_data) !=
+ sizeof(struct kvm_cpuid2) +
+ sizeof(struct kvm_cpuid_entry2) * KVM_MAX_CPUID_ENTRIES);
+
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+ uint32_t cpuid_i;
+ struct kvm_cpuid_entry2 *c;
+ uint32_t signature[3];
+ int kvm_base = KVM_CPUID_SIGNATURE;
+ int max_nested_state_len;
+ int r;
+ Error *local_err = NULL;
+
+ memset(&cpuid_data, 0, sizeof(cpuid_data));
+
+ cpuid_i = 0;
+
+ r = kvm_arch_set_tsc_khz(cs);
+ if (r < 0) {
+ return r;
+ }
+
+ /*
+ * vcpu's TSC frequency is either specified by user, or following
+ * the value used by KVM if the former is not present. In the
+ * latter case, we query it from KVM and record in env->tsc_khz,
+ * so that vcpu's TSC frequency can be migrated later via this field.
+ */
+ if (!env->tsc_khz) {
+ r = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
+ kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
+ -ENOTSUP;
+ if (r > 0) {
+ env->tsc_khz = r;
+ }
+ }
+
+ env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY;
+
+ /* Paravirtualization CPUIDs */
+ r = hyperv_handle_properties(cs, cpuid_data.entries);
+ if (r < 0) {
+ return r;
+ } else if (r > 0) {
+ cpuid_i = r;
+ kvm_base = KVM_CPUID_SIGNATURE_NEXT;
+ has_msr_hv_hypercall = true;
+ }
+
+ if (cpu->expose_kvm) {
+ memcpy(signature, "KVMKVMKVM\0\0\0", 12);
+ c = &cpuid_data.entries[cpuid_i++];
+ c->function = KVM_CPUID_SIGNATURE | kvm_base;
+ c->eax = KVM_CPUID_FEATURES | kvm_base;
+ c->ebx = signature[0];
+ c->ecx = signature[1];
+ c->edx = signature[2];
+
+ c = &cpuid_data.entries[cpuid_i++];
+ c->function = KVM_CPUID_FEATURES | kvm_base;
+ c->eax = env->features[FEAT_KVM];
+ c->edx = env->features[FEAT_KVM_HINTS];
+ }
+
+ cpuid_i = kvm_x86_arch_cpuid(env, cpuid_data.entries, cpuid_i);
cpuid_data.cpuid.nent = cpuid_i;
if (((env->cpuid_version >> 8)&0xF) >= 6
diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h
index dc72508389..c9a92578b1 100644
--- a/target/i386/kvm/kvm_i386.h
+++ b/target/i386/kvm/kvm_i386.h
@@ -24,6 +24,10 @@
#define kvm_ioapic_in_kernel() \
(kvm_irqchip_in_kernel() && !kvm_irqchip_is_split())
+#define KVM_MAX_CPUID_ENTRIES 100
+uint32_t kvm_x86_arch_cpuid(CPUX86State *env, struct kvm_cpuid_entry2 *entries,
+ uint32_t cpuid_i);
+
#else
#define kvm_pit_in_kernel() 0
--
2.17.1
- [RFC PATCH 00/23] [RFC PATCH 00/24] TDX support, Isaku Yamahata, 2021/02/15
- [RFC PATCH 05/23] vl: Introduce machine_init_done_late notifier, Isaku Yamahata, 2021/02/15
- [RFC PATCH 06/23] hw/i386: Introduce kvm-type for TDX guest, Isaku Yamahata, 2021/02/15
- [RFC PATCH 02/23] kvm: Switch KVM_CAP_READONLY_MEM to a per-VM ioctl(), Isaku Yamahata, 2021/02/15
- [RFC PATCH 07/23] i386/kvm: Squash getting/putting guest state for TDX VMs, Isaku Yamahata, 2021/02/15
- [RFC PATCH 03/23] KVM: i386: use VM capability check for KVM_CAP_X86_SMM, Isaku Yamahata, 2021/02/15
- [RFC PATCH 08/23] i386/kvm: Skip KVM_X86_SETUP_MCE for TDX guests, Isaku Yamahata, 2021/02/15
- [RFC PATCH 04/23] i386/kvm: Move architectural CPUID leaf generation to separarte helper,
Isaku Yamahata <=
- [RFC PATCH 09/23] target/i386: kvm: don't synchronize guest tsc for TD guest, Isaku Yamahata, 2021/02/15
- [RFC PATCH 01/23] target/i386: Expose x86_cpu_get_supported_feature_word() for TDX, Isaku Yamahata, 2021/02/15
- [RFC PATCH 10/23] linux-headers: Update headers to pull in TDX API changes, Isaku Yamahata, 2021/02/15
- [RFC PATCH 13/23] i386/tdx: Frame in tdx_get_supported_cpuid with KVM_TDX_CAPABILITIES, Isaku Yamahata, 2021/02/15
- [RFC PATCH 11/23] hw/i386: Initialize TDX via KVM ioctl() when kvm_type is TDX, Isaku Yamahata, 2021/02/15
- [RFC PATCH 14/23] i386/tdx: Frame in the call for KVM_TDX_INIT_VCPU, Isaku Yamahata, 2021/02/15
- [RFC PATCH 12/23] target/i386/tdx: Finalize the TD's measurement when machine is done, Isaku Yamahata, 2021/02/15
- [RFC PATCH 15/23] i386/tdx: Add hook to require generic device loader, Isaku Yamahata, 2021/02/15
- [RFC PATCH 17/23] i386/tdx: Add definitions for TDVF metadata, Isaku Yamahata, 2021/02/15