From 130913e14581c87340ff5d7650a2915e9067b736 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost <ehabkost@redhat.com>
Date: Tue, 9 Jan 2018 13:45:16 -0200
Subject: [PATCH] i386: Add FEAT_8000_0008_EBX CPUID feature word

Add the new feature word and the "ibpb" feature flag.

Based on a patch by Paolo Bonzini.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20180109154519.25634-5-ehabkost@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
(cherry picked from commit 1b3420e1c4d523c49866cca4e7544753201cd43d)
[BR: BSC#1068032 CVE-2017-5715 change to match current code's feat_name
type. Also adapted to old style feature management.]
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
 target-i386/cpu.c | 30 ++++++++++++++++++++++++++++--
 target-i386/cpu.h |  4 ++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 6046cfc322..3af15f42d2 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -160,6 +160,17 @@ static const char *cpuid_7_0_edx_feature_name[] = {
     NULL, NULL, NULL, NULL,
 };
 
+static const char *cpuid_ibpb_ebx_feature_name[] = {
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    "ibpb", NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+};
+
 typedef struct FeatureWordInfo {
     const char **feat_names;
     uint32_t cpuid_eax; /* Input EAX for CPUID */
@@ -203,6 +214,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
         .feat_names = cpuid_7_0_edx_feature_name,
         .cpuid_eax = 7, .cpuid_reg = R_EDX,
     },
+    [FEAT_8000_0008_EBX] = {
+        .feat_names = cpuid_ibpb_ebx_feature_name,
+        .cpuid_eax = 0x80000008,
+        .cpuid_reg = R_EBX,
+    },
 };
 
 typedef struct ExtSaveArea {
@@ -390,6 +406,7 @@ typedef struct x86_def_t {
     uint32_t cpuid_7_0_ebx_features;
     /* The feature bits on CPUID[EAX=7,ECX=0].EDX */
     uint32_t cpuid_7_0_edx_features;
+    uint32_t cpuid_8000_0008_ebx_features;
 } x86_def_t;
 
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -947,7 +964,9 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
     } else {
         x86_cpu_def->cpuid_7_0_ebx_features = 0;
         x86_cpu_def->cpuid_7_0_edx_features = 0;
-    }
+    }  
+    x86_cpu_def->cpuid_8000_0008_ebx_features =
+                    kvm_arch_get_supported_cpuid(s, 0x80000008, 0, R_EBX);
 
     x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
     x86_cpu_def->ext2_features =
@@ -1024,6 +1043,8 @@ static int kvm_check_features_against_host(X86CPU *cpu)
             FEAT_7_0_EBX },
         {&env->cpuid_7_0_edx_features, &host_def.cpuid_7_0_edx_features,
             FEAT_7_0_EDX },
+        {&env->cpuid_8000_0008_ebx_features, &host_def.cpuid_8000_0008_ebx_features,
+            FEAT_8000_0008_EBX },
         {&env->cpuid_svm_features, &host_def.svm_features,
             FEAT_SVM },
         {&env->cpuid_kvm_features, &host_def.kvm_features,
@@ -1441,6 +1462,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
     env->cpuid_svm_features &= ~minus_features[FEAT_SVM];
     env->cpuid_7_0_ebx_features &= ~minus_features[FEAT_7_0_EBX];
     env->cpuid_7_0_edx_features &= ~minus_features[FEAT_7_0_EDX];
+    env->cpuid_8000_0008_ebx_features &= ~minus_features[FEAT_8000_0008_EBX];
 
 out:
     return;
@@ -1550,6 +1572,8 @@ static void filter_features_for_kvm(X86CPU *cpu)
         kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
     env->cpuid_ext4_features &=
         kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX);
+    env->cpuid_8000_0008_ebx_features &= 
+        kvm_arch_get_supported_cpuid(s, 0x80000008, 0, R_EBX);
 
 }
 #endif
@@ -1598,6 +1622,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
     env->cpuid_7_0_ebx_features = def->cpuid_7_0_ebx_features;
     env->cpuid_7_0_edx_features = def->cpuid_7_0_edx_features;
     env->cpuid_xlevel2 = def->xlevel2;
+    env->cpuid_8000_0008_ebx_features = def->cpuid_8000_0008_ebx_features;
 
     object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error);
     if (error) {
@@ -1893,7 +1918,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
             else
                 *eax = 0x00000020; /* 32 bits physical */
         }
-        *ebx = 0;
+        *ebx = env->cpuid_8000_0008_ebx_features;
         *ecx = 0;
         *edx = 0;
         if (cs->nr_cores * cs->nr_threads > 1) {
@@ -2145,6 +2170,7 @@ void x86_cpu_realize(Object *obj, Error **errp)
         env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
         env->cpuid_svm_features &= TCG_SVM_FEATURES;
         env->cpuid_7_0_edx_features &= TCG_7_0_EDX_FEATURES;
+        env->cpuid_8000_0008_ebx_features &= 0;
     } else {
         if (check_cpuid && kvm_check_features_against_host(cpu)
             && enforce_cpuid) {
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 7af6c3257e..3bbba0564f 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -383,6 +383,7 @@ typedef enum FeatureWord {
     FEAT_7_0_EDX,       /* CPUID[EAX=7,ECX=0].EDX */
     FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
     FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
+    FEAT_8000_0008_EBX, /* CPUID[8000_0008].EBX */
     FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
     FEAT_KVM,           /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
     FEAT_SVM,           /* CPUID[8000_000A].EDX */
@@ -542,6 +543,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_EBX_SMAP     (1 << 20)
 #define CPUID_7_0_EDX_SPEC_CTRL     (1U << 26) /* Speculation Control */
 
+#define CPUID_8000_0008_EBX_IBPB    (1U << 12) /* Indirect Branch Prediction Barrier */
+
 #define CPUID_VENDOR_SZ      12
 
 #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
@@ -853,6 +856,7 @@ typedef struct CPUX86State {
     uint32_t cpuid_7_0_ebx_features;
     /* Flags from CPUID[EAX=7,ECX=0].EDX */
     uint32_t cpuid_7_0_edx_features;
+    uint32_t cpuid_8000_0008_ebx_features;
 
     /* MTRRs */
     uint64_t mtrr_fixed[11];
