diff options
| -rw-r--r-- | target/i386/cpu.c | 16 | ||||
| -rw-r--r-- | target/i386/cpu.h | 1 | ||||
| -rw-r--r-- | target/i386/kvm/kvm.c | 2 | ||||
| -rw-r--r-- | target/i386/kvm/kvm_i386.h | 1 | ||||
| -rw-r--r-- | target/i386/kvm/tdx.c | 34 |
5 files changed, 53 insertions, 1 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 6a97d7549e..5aacb62f08 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1678,6 +1678,22 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { }, }; +bool is_feature_word_cpuid(uint32_t feature, uint32_t index, int reg) +{ + FeatureWordInfo *wi; + FeatureWord w; + + for (w = 0; w < FEATURE_WORDS; w++) { + wi = &feature_word_info[w]; + if (wi->type == CPUID_FEATURE_WORD && wi->cpuid.eax == feature && + (!wi->cpuid.needs_ecx || wi->cpuid.ecx == index) && + wi->cpuid.reg == reg) { + return true; + } + } + return false; +} + typedef struct FeatureMask { FeatureWord index; uint64_t mask; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index ad0e3d8cdd..7ffcf91b01 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2502,6 +2502,7 @@ void cpu_set_apic_feature(CPUX86State *env); void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); bool cpu_has_x2apic_feature(CPUX86State *env); +bool is_feature_word_cpuid(uint32_t feature, uint32_t index, int reg); static inline bool x86_has_cpuid_0x1f(X86CPU *cpu) { diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 0d47463431..cd87f5502a 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -394,7 +394,7 @@ static bool host_tsx_broken(void) /* Returns the value for a specific register on the cpuid entry */ -static uint32_t cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, int reg) +uint32_t cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, int reg) { uint32_t ret = 0; switch (reg) { diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h index dc696cb723..484a1de84d 100644 --- a/target/i386/kvm/kvm_i386.h +++ b/target/i386/kvm/kvm_i386.h @@ -62,6 +62,7 @@ void kvm_update_msi_routes_all(void *private, bool global, struct kvm_cpuid_entry2 *cpuid_find_entry(struct kvm_cpuid2 *cpuid, uint32_t function, uint32_t index); +uint32_t cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, int reg); uint32_t kvm_x86_build_cpuid(CPUX86State *env, struct kvm_cpuid_entry2 *entries, uint32_t cpuid_i); #endif /* CONFIG_KVM */ diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c index 68ed3b9f98..e3b7ad6d14 100644 --- a/target/i386/kvm/tdx.c +++ b/target/i386/kvm/tdx.c @@ -45,6 +45,7 @@ static TdxGuest *tdx_guest; static struct kvm_tdx_capabilities *tdx_caps; +static struct kvm_cpuid2 *tdx_supported_cpuid; /* Valid after kvm_arch_init()->confidential_guest_kvm_init()->tdx_kvm_init() */ bool is_tdx_vm(void) @@ -366,6 +367,20 @@ static Notifier tdx_machine_done_notify = { .notify = tdx_finalize_vm, }; +static void tdx_setup_supported_cpuid(void) +{ + if (tdx_supported_cpuid) { + return; + } + + tdx_supported_cpuid = g_malloc0(sizeof(*tdx_supported_cpuid) + + KVM_MAX_CPUID_ENTRIES * sizeof(struct kvm_cpuid_entry2)); + + memcpy(tdx_supported_cpuid->entries, tdx_caps->cpuid.entries, + tdx_caps->cpuid.nent * sizeof(struct kvm_cpuid_entry2)); + tdx_supported_cpuid->nent = tdx_caps->cpuid.nent; +} + static int tdx_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) { MachineState *ms = MACHINE(qdev_get_machine()); @@ -403,6 +418,8 @@ static int tdx_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) } } + tdx_setup_supported_cpuid(); + /* TDX relies on KVM_HC_MAP_GPA_RANGE to handle TDG.VP.VMCALL<MapGPA> */ if (!kvm_enable_hypercall(BIT_ULL(KVM_HC_MAP_GPA_RANGE))) { return -EOPNOTSUPP; @@ -440,6 +457,22 @@ static void tdx_cpu_instance_init(X86ConfidentialGuest *cg, CPUState *cpu) x86cpu->enable_cpuid_0x1f = true; } +static uint32_t tdx_adjust_cpuid_features(X86ConfidentialGuest *cg, + uint32_t feature, uint32_t index, + int reg, uint32_t value) +{ + struct kvm_cpuid_entry2 *e; + + if (is_feature_word_cpuid(feature, index, reg)) { + e = cpuid_find_entry(tdx_supported_cpuid, feature, index); + if (e) { + value &= cpuid_entry_get_reg(e, reg); + } + } + + return value; +} + static int tdx_validate_attributes(TdxGuest *tdx, Error **errp) { if ((tdx->attributes & ~tdx_caps->supported_attrs)) { @@ -834,4 +867,5 @@ static void tdx_guest_class_init(ObjectClass *oc, const void *data) klass->kvm_init = tdx_kvm_init; x86_klass->kvm_type = tdx_kvm_type; x86_klass->cpu_instance_init = tdx_cpu_instance_init; + x86_klass->adjust_cpuid_features = tdx_adjust_cpuid_features; } |