diff options
author | David Hildenbrand <dahi@linux.vnet.ibm.com> | 2016-09-05 10:52:35 +0200 |
---|---|---|
committer | Cornelia Huck <cornelia.huck@de.ibm.com> | 2016-09-06 17:06:50 +0200 |
commit | 3b84c25cc7e4106a588737b2031863994bb86f03 (patch) | |
tree | 52092af377a25f9acf2d9f550de47824b05b18f0 /target-s390x/cpu_models.c | |
parent | 392529cb7747a4226e724c5a59858334f76021e2 (diff) |
s390x/kvm: implement CPU model support
Let's implement our two hooks so we can support CPU models.
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Message-Id: <20160905085244.99980-22-dahi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Diffstat (limited to 'target-s390x/cpu_models.c')
-rw-r--r-- | target-s390x/cpu_models.c | 75 |
1 files changed, 72 insertions, 3 deletions
diff --git a/target-s390x/cpu_models.c b/target-s390x/cpu_models.c index 25ac2c9884..5b9f35ee87 100644 --- a/target-s390x/cpu_models.c +++ b/target-s390x/cpu_models.c @@ -162,6 +162,61 @@ bool s390_has_feat(S390Feat feat) return test_bit(feat, cpu->model->features); } +uint8_t s390_get_gen_for_cpu_type(uint16_t type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) { + if (s390_cpu_defs[i].type == type) { + return s390_cpu_defs[i].gen; + } + } + return 0; +} + +const S390CPUDef *s390_find_cpu_def(uint16_t type, uint8_t gen, uint8_t ec_ga, + S390FeatBitmap features) +{ + const S390CPUDef *last_compatible = NULL; + int i; + + if (!gen) { + ec_ga = 0; + } + if (!gen && type) { + gen = s390_get_gen_for_cpu_type(type); + } + + for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) { + const S390CPUDef *def = &s390_cpu_defs[i]; + S390FeatBitmap missing; + + /* don't even try newer generations if we know the generation */ + if (gen) { + if (def->gen > gen) { + break; + } else if (def->gen == gen && ec_ga && def->ec_ga > ec_ga) { + break; + } + } + + if (features) { + /* see if the model satisfies the minimum features */ + bitmap_andnot(missing, def->base_feat, features, S390_FEAT_MAX); + if (!bitmap_empty(missing, S390_FEAT_MAX)) { + break; + } + } + + /* stop the search if we found the exact model */ + if (def->type == type && def->ec_ga == ec_ga) { + return def; + } + last_compatible = def; + } + return last_compatible; +} + struct S390PrintCpuListInfo { FILE *f; fprintf_function print; @@ -324,7 +379,7 @@ static S390CPUModel *get_max_cpu_model(Error **errp) } if (kvm_enabled()) { - error_setg(errp, "KVM does not support CPU models."); + kvm_s390_get_host_cpu_model(&max_model, errp); } else { /* TCG enulates a z900 */ max_model.def = &s390_cpu_defs[0]; @@ -357,8 +412,7 @@ static inline void apply_cpu_model(const S390CPUModel *model, Error **errp) } if (kvm_enabled()) { - /* FIXME KVM */ - error_setg(errp, "KVM doesn't support CPU models."); + kvm_s390_apply_cpu_model(model, errp); } else if (model) { /* FIXME TCG - use data for stdip/stfl */ } @@ -563,6 +617,21 @@ static void s390_cpu_model_initfn(Object *obj) #ifdef CONFIG_KVM static void s390_host_cpu_model_initfn(Object *obj) { + S390CPU *cpu = S390_CPU(obj); + Error *err = NULL; + + if (!kvm_enabled() || !kvm_s390_cpu_models_supported()) { + return; + } + + cpu->model = g_malloc0(sizeof(*cpu->model)); + kvm_s390_get_host_cpu_model(cpu->model, &err); + if (err) { + error_report_err(err); + g_free(cpu->model); + /* fallback to unsupported cpu models */ + cpu->model = NULL; + } } #endif |