1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "cpu.h"
15#include "gen-features.h"
16#include "qapi/error.h"
17#include "qapi/visitor.h"
18#include "qemu/error-report.h"
19#include "qapi/qmp/qerror.h"
20#include "qapi/qobject-input-visitor.h"
21#include "qapi/qmp/qbool.h"
22#ifndef CONFIG_USER_ONLY
23#include "sysemu/arch_init.h"
24#endif
25
26#define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \
27 { \
28 .name = _name, \
29 .type = _type, \
30 .gen = _gen, \
31 .ec_ga = _ec_ga, \
32 .mha_pow = _mha_pow, \
33 .hmfai = _hmfai, \
34 .desc = _desc, \
35 .base_init = { S390_FEAT_LIST_GEN ## _gen ## _GA ## _ec_ga ## _BASE }, \
36 .default_init = { S390_FEAT_LIST_GEN ## _gen ## _GA ## _ec_ga ## _DEFAULT }, \
37 .full_init = { S390_FEAT_LIST_GEN ## _gen ## _GA ## _ec_ga ## _FULL }, \
38 }
39
40
41
42
43
44
45
46static S390CPUDef s390_cpu_defs[] = {
47 CPUDEF_INIT(0x2064, 7, 1, 38, 0x00000000U, "z900", "IBM zSeries 900 GA1"),
48 CPUDEF_INIT(0x2064, 7, 2, 38, 0x00000000U, "z900.2", "IBM zSeries 900 GA2"),
49 CPUDEF_INIT(0x2064, 7, 3, 38, 0x00000000U, "z900.3", "IBM zSeries 900 GA3"),
50 CPUDEF_INIT(0x2066, 7, 3, 38, 0x00000000U, "z800", "IBM zSeries 800 GA1"),
51 CPUDEF_INIT(0x2084, 8, 1, 38, 0x00000000U, "z990", "IBM zSeries 990 GA1"),
52 CPUDEF_INIT(0x2084, 8, 2, 38, 0x00000000U, "z990.2", "IBM zSeries 990 GA2"),
53 CPUDEF_INIT(0x2084, 8, 3, 38, 0x00000000U, "z990.3", "IBM zSeries 990 GA3"),
54 CPUDEF_INIT(0x2086, 8, 3, 38, 0x00000000U, "z890", "IBM zSeries 880 GA1"),
55 CPUDEF_INIT(0x2084, 8, 4, 38, 0x00000000U, "z990.4", "IBM zSeries 990 GA4"),
56 CPUDEF_INIT(0x2086, 8, 4, 38, 0x00000000U, "z890.2", "IBM zSeries 880 GA2"),
57 CPUDEF_INIT(0x2084, 8, 5, 38, 0x00000000U, "z990.5", "IBM zSeries 990 GA5"),
58 CPUDEF_INIT(0x2086, 8, 5, 38, 0x00000000U, "z890.3", "IBM zSeries 880 GA3"),
59 CPUDEF_INIT(0x2094, 9, 1, 40, 0x00000000U, "z9EC", "IBM System z9 EC GA1"),
60 CPUDEF_INIT(0x2094, 9, 2, 40, 0x00000000U, "z9EC.2", "IBM System z9 EC GA2"),
61 CPUDEF_INIT(0x2096, 9, 2, 40, 0x00000000U, "z9BC", "IBM System z9 BC GA1"),
62 CPUDEF_INIT(0x2094, 9, 3, 40, 0x00000000U, "z9EC.3", "IBM System z9 EC GA3"),
63 CPUDEF_INIT(0x2096, 9, 3, 40, 0x00000000U, "z9BC.2", "IBM System z9 BC GA2"),
64 CPUDEF_INIT(0x2097, 10, 1, 43, 0x00000000U, "z10EC", "IBM System z10 EC GA1"),
65 CPUDEF_INIT(0x2097, 10, 2, 43, 0x00000000U, "z10EC.2", "IBM System z10 EC GA2"),
66 CPUDEF_INIT(0x2098, 10, 2, 43, 0x00000000U, "z10BC", "IBM System z10 BC GA1"),
67 CPUDEF_INIT(0x2097, 10, 3, 43, 0x00000000U, "z10EC.3", "IBM System z10 EC GA3"),
68 CPUDEF_INIT(0x2098, 10, 3, 43, 0x00000000U, "z10BC.2", "IBM System z10 BC GA2"),
69 CPUDEF_INIT(0x2817, 11, 1, 44, 0x08000000U, "z196", "IBM zEnterprise 196 GA1"),
70 CPUDEF_INIT(0x2817, 11, 2, 44, 0x08000000U, "z196.2", "IBM zEnterprise 196 GA2"),
71 CPUDEF_INIT(0x2818, 11, 2, 44, 0x08000000U, "z114", "IBM zEnterprise 114 GA1"),
72 CPUDEF_INIT(0x2827, 12, 1, 44, 0x08000000U, "zEC12", "IBM zEnterprise EC12 GA1"),
73 CPUDEF_INIT(0x2827, 12, 2, 44, 0x08000000U, "zEC12.2", "IBM zEnterprise EC12 GA2"),
74 CPUDEF_INIT(0x2828, 12, 2, 44, 0x08000000U, "zBC12", "IBM zEnterprise BC12 GA1"),
75 CPUDEF_INIT(0x2964, 13, 1, 47, 0x08000000U, "z13", "IBM z13 GA1"),
76 CPUDEF_INIT(0x2964, 13, 2, 47, 0x08000000U, "z13.2", "IBM z13 GA2"),
77 CPUDEF_INIT(0x2965, 13, 2, 47, 0x08000000U, "z13s", "IBM z13s GA1"),
78 CPUDEF_INIT(0x3906, 14, 1, 47, 0x08000000U, "z14", "IBM z14 GA1"),
79};
80
81
82S390FeatBitmap ignored_base_feat;
83
84void s390_cpudef_featoff(uint8_t gen, uint8_t ec_ga, S390Feat feat)
85{
86 const S390CPUDef *def;
87
88 def = s390_find_cpu_def(0, gen, ec_ga, NULL);
89 clear_bit(feat, (unsigned long *)&def->default_feat);
90}
91
92void s390_cpudef_featoff_greater(uint8_t gen, uint8_t ec_ga, S390Feat feat)
93{
94 int i;
95
96 for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
97 const S390CPUDef *def = &s390_cpu_defs[i];
98
99 if (def->gen < gen) {
100 continue;
101 }
102 if (def->gen == gen && def->ec_ga < ec_ga) {
103 continue;
104 }
105
106 clear_bit(feat, (unsigned long *)&def->default_feat);
107 }
108}
109
110uint32_t s390_get_hmfai(void)
111{
112 static S390CPU *cpu;
113
114 if (!cpu) {
115 cpu = S390_CPU(qemu_get_cpu(0));
116 }
117
118 if (!cpu || !cpu->model) {
119 return 0;
120 }
121 return cpu->model->def->hmfai;
122}
123
124uint8_t s390_get_mha_pow(void)
125{
126 static S390CPU *cpu;
127
128 if (!cpu) {
129 cpu = S390_CPU(qemu_get_cpu(0));
130 }
131
132 if (!cpu || !cpu->model) {
133 return 0;
134 }
135 return cpu->model->def->mha_pow;
136}
137
138uint32_t s390_get_ibc_val(void)
139{
140 uint16_t unblocked_ibc, lowest_ibc;
141 static S390CPU *cpu;
142
143 if (!cpu) {
144 cpu = S390_CPU(qemu_get_cpu(0));
145 }
146
147 if (!cpu || !cpu->model) {
148 return 0;
149 }
150 unblocked_ibc = s390_ibc_from_cpu_model(cpu->model);
151 lowest_ibc = cpu->model->lowest_ibc;
152
153 if (!lowest_ibc || lowest_ibc > unblocked_ibc) {
154 return 0;
155 }
156 return ((uint32_t) lowest_ibc << 16) | unblocked_ibc;
157}
158
159void s390_get_feat_block(S390FeatType type, uint8_t *data)
160{
161 static S390CPU *cpu;
162
163 if (!cpu) {
164 cpu = S390_CPU(qemu_get_cpu(0));
165 }
166
167 if (!cpu || !cpu->model) {
168 return;
169 }
170 s390_fill_feat_block(cpu->model->features, type, data);
171}
172
173bool s390_has_feat(S390Feat feat)
174{
175 static S390CPU *cpu;
176
177 if (!cpu) {
178 cpu = S390_CPU(qemu_get_cpu(0));
179 }
180
181 if (!cpu || !cpu->model) {
182#ifdef CONFIG_KVM
183 if (kvm_enabled()) {
184 if (feat == S390_FEAT_VECTOR) {
185 return kvm_check_extension(kvm_state,
186 KVM_CAP_S390_VECTOR_REGISTERS);
187 }
188 if (feat == S390_FEAT_RUNTIME_INSTRUMENTATION) {
189 return kvm_s390_get_ri();
190 }
191 if (feat == S390_FEAT_MSA_EXT_3) {
192 return true;
193 }
194 }
195#endif
196 return 0;
197 }
198 return test_bit(feat, cpu->model->features);
199}
200
201uint8_t s390_get_gen_for_cpu_type(uint16_t type)
202{
203 int i;
204
205 for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
206 if (s390_cpu_defs[i].type == type) {
207 return s390_cpu_defs[i].gen;
208 }
209 }
210 return 0;
211}
212
213const S390CPUDef *s390_find_cpu_def(uint16_t type, uint8_t gen, uint8_t ec_ga,
214 S390FeatBitmap features)
215{
216 const S390CPUDef *last_compatible = NULL;
217 const S390CPUDef *matching_cpu_type = NULL;
218 int i;
219
220 if (!gen) {
221 ec_ga = 0;
222 }
223 if (!gen && type) {
224 gen = s390_get_gen_for_cpu_type(type);
225 }
226
227 for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
228 const S390CPUDef *def = &s390_cpu_defs[i];
229 S390FeatBitmap missing;
230
231
232 if (gen) {
233 if (def->gen > gen) {
234 break;
235 } else if (def->gen == gen && ec_ga && def->ec_ga > ec_ga) {
236 break;
237 }
238 }
239
240 if (features) {
241
242 bitmap_andnot(missing, def->base_feat, features, S390_FEAT_MAX);
243
244
245
246
247 bitmap_andnot(missing, missing, ignored_base_feat, S390_FEAT_MAX);
248 if (!bitmap_empty(missing, S390_FEAT_MAX)) {
249 break;
250 }
251 }
252
253
254 if (def->type == type && def->ec_ga == ec_ga) {
255 return def;
256 }
257
258 if (def->type == type) {
259 matching_cpu_type = def;
260 }
261 last_compatible = def;
262 }
263
264 if (matching_cpu_type) {
265 return matching_cpu_type;
266 }
267 return last_compatible;
268}
269
270struct S390PrintCpuListInfo {
271 FILE *f;
272 fprintf_function print;
273};
274
275static void print_cpu_model_list(ObjectClass *klass, void *opaque)
276{
277 struct S390PrintCpuListInfo *info = opaque;
278 S390CPUClass *scc = S390_CPU_CLASS(klass);
279 char *name = g_strdup(object_class_get_name(klass));
280 const char *details = "";
281
282 if (scc->is_static) {
283 details = "(static, migration-safe)";
284 } else if (scc->is_migration_safe) {
285 details = "(migration-safe)";
286 }
287
288
289 g_strrstr(name, "-" TYPE_S390_CPU)[0] = 0;
290 (*info->print)(info->f, "s390 %-15s %-35s %s\n", name, scc->desc,
291 details);
292 g_free(name);
293}
294
295void s390_cpu_list(FILE *f, fprintf_function print)
296{
297 struct S390PrintCpuListInfo info = {
298 .f = f,
299 .print = print,
300 };
301 S390FeatGroup group;
302 S390Feat feat;
303
304 object_class_foreach(print_cpu_model_list, TYPE_S390_CPU, false, &info);
305
306 (*print)(f, "\nRecognized feature flags:\n");
307 for (feat = 0; feat < S390_FEAT_MAX; feat++) {
308 const S390FeatDef *def = s390_feat_def(feat);
309
310 (*print)(f, "%-20s %-50s\n", def->name, def->desc);
311 }
312
313 (*print)(f, "\nRecognized feature groups:\n");
314 for (group = 0; group < S390_FEAT_GROUP_MAX; group++) {
315 const S390FeatGroupDef *def = s390_feat_group_def(group);
316
317 (*print)(f, "%-20s %-50s\n", def->name, def->desc);
318 }
319}
320
321static S390CPUModel *get_max_cpu_model(Error **errp);
322
323#ifndef CONFIG_USER_ONLY
324static void list_add_feat(const char *name, void *opaque);
325
326static void check_unavailable_features(const S390CPUModel *max_model,
327 const S390CPUModel *model,
328 strList **unavailable)
329{
330 S390FeatBitmap missing;
331
332
333 if (max_model->def->gen < model->def->gen ||
334 (max_model->def->gen == model->def->gen &&
335 max_model->def->ec_ga < model->def->ec_ga)) {
336 list_add_feat("type", unavailable);
337 }
338
339
340 bitmap_andnot(missing, model->features, max_model->features,
341 S390_FEAT_MAX);
342 if (!bitmap_empty(missing, S390_FEAT_MAX)) {
343 s390_feat_bitmap_to_ascii(missing, unavailable, list_add_feat);
344 }
345}
346
347struct CpuDefinitionInfoListData {
348 CpuDefinitionInfoList *list;
349 S390CPUModel *model;
350};
351
352static void create_cpu_model_list(ObjectClass *klass, void *opaque)
353{
354 struct CpuDefinitionInfoListData *cpu_list_data = opaque;
355 CpuDefinitionInfoList **cpu_list = &cpu_list_data->list;
356 CpuDefinitionInfoList *entry;
357 CpuDefinitionInfo *info;
358 char *name = g_strdup(object_class_get_name(klass));
359 S390CPUClass *scc = S390_CPU_CLASS(klass);
360
361
362 g_strrstr(name, "-" TYPE_S390_CPU)[0] = 0;
363 info = g_malloc0(sizeof(*info));
364 info->name = name;
365 info->has_migration_safe = true;
366 info->migration_safe = scc->is_migration_safe;
367 info->q_static = scc->is_static;
368 info->q_typename = g_strdup(object_class_get_name(klass));
369
370 if (cpu_list_data->model) {
371 Object *obj;
372 S390CPU *sc;
373 obj = object_new(object_class_get_name(klass));
374 sc = S390_CPU(obj);
375 if (sc->model) {
376 info->has_unavailable_features = true;
377 check_unavailable_features(cpu_list_data->model, sc->model,
378 &info->unavailable_features);
379 }
380 object_unref(obj);
381 }
382
383 entry = g_malloc0(sizeof(*entry));
384 entry->value = info;
385 entry->next = *cpu_list;
386 *cpu_list = entry;
387}
388
389CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
390{
391 struct CpuDefinitionInfoListData list_data = {
392 .list = NULL,
393 };
394
395 list_data.model = get_max_cpu_model(errp);
396 if (*errp) {
397 error_free(*errp);
398 *errp = NULL;
399 }
400
401 object_class_foreach(create_cpu_model_list, TYPE_S390_CPU, false,
402 &list_data);
403
404 return list_data.list;
405}
406
407static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info,
408 Error **errp)
409{
410 const QDict *qdict = NULL;
411 const QDictEntry *e;
412 Visitor *visitor;
413 ObjectClass *oc;
414 S390CPU *cpu;
415 Object *obj;
416
417 if (info->props) {
418 qdict = qobject_to_qdict(info->props);
419 if (!qdict) {
420 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
421 return;
422 }
423 }
424
425 oc = cpu_class_by_name(TYPE_S390_CPU, info->name);
426 if (!oc) {
427 error_setg(errp, "The CPU definition \'%s\' is unknown.", info->name);
428 return;
429 }
430 if (S390_CPU_CLASS(oc)->kvm_required && !kvm_enabled()) {
431 error_setg(errp, "The CPU definition '%s' requires KVM", info->name);
432 return;
433 }
434 obj = object_new(object_class_get_name(oc));
435 cpu = S390_CPU(obj);
436
437 if (!cpu->model) {
438 error_setg(errp, "Details about the host CPU model are not available, "
439 "it cannot be used.");
440 object_unref(obj);
441 return;
442 }
443
444 if (qdict) {
445 visitor = qobject_input_visitor_new(info->props);
446 visit_start_struct(visitor, NULL, NULL, 0, errp);
447 if (*errp) {
448 object_unref(obj);
449 return;
450 }
451 for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
452 object_property_set(obj, visitor, e->key, errp);
453 if (*errp) {
454 break;
455 }
456 }
457 if (!*errp) {
458 visit_check_struct(visitor, errp);
459 }
460 visit_end_struct(visitor, NULL);
461 visit_free(visitor);
462 if (*errp) {
463 object_unref(obj);
464 return;
465 }
466 }
467
468
469 memcpy(model, cpu->model, sizeof(*model));
470 object_unref(obj);
471}
472
473static void qdict_add_disabled_feat(const char *name, void *opaque)
474{
475 qdict_put_bool(opaque, name, false);
476}
477
478static void qdict_add_enabled_feat(const char *name, void *opaque)
479{
480 qdict_put_bool(opaque, name, true);
481}
482
483
484static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
485 bool delta_changes)
486{
487 QDict *qdict = qdict_new();
488 S390FeatBitmap bitmap;
489
490
491 info->name = g_strdup_printf("%s-base", model->def->name);
492
493 if (delta_changes) {
494
495 bitmap_andnot(bitmap, model->def->base_feat, model->features,
496 S390_FEAT_MAX);
497 if (!bitmap_empty(bitmap, S390_FEAT_MAX)) {
498 s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_disabled_feat);
499 }
500
501
502 bitmap_andnot(bitmap, model->features, model->def->base_feat,
503 S390_FEAT_MAX);
504 if (!bitmap_empty(bitmap, S390_FEAT_MAX)) {
505 s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_enabled_feat);
506 }
507 } else {
508
509 s390_feat_bitmap_to_ascii(model->features, qdict,
510 qdict_add_enabled_feat);
511 bitmap_complement(bitmap, model->features, S390_FEAT_MAX);
512 s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_disabled_feat);
513 }
514
515 if (!qdict_size(qdict)) {
516 QDECREF(qdict);
517 } else {
518 info->props = QOBJECT(qdict);
519 info->has_props = true;
520 }
521}
522
523CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
524 CpuModelInfo *model,
525 Error **errp)
526{
527 CpuModelExpansionInfo *expansion_info = NULL;
528 S390CPUModel s390_model;
529 bool delta_changes = false;
530
531
532 cpu_model_from_info(&s390_model, model, errp);
533 if (*errp) {
534 return NULL;
535 }
536
537 if (type == CPU_MODEL_EXPANSION_TYPE_STATIC) {
538 delta_changes = true;
539 } else if (type != CPU_MODEL_EXPANSION_TYPE_FULL) {
540 error_setg(errp, "The requested expansion type is not supported.");
541 return NULL;
542 }
543
544
545 expansion_info = g_malloc0(sizeof(*expansion_info));
546 expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
547 cpu_info_from_model(expansion_info->model, &s390_model, delta_changes);
548 return expansion_info;
549}
550
551static void list_add_feat(const char *name, void *opaque)
552{
553 strList **last = (strList **) opaque;
554 strList *entry;
555
556 entry = g_malloc0(sizeof(*entry));
557 entry->value = g_strdup(name);
558 entry->next = *last;
559 *last = entry;
560}
561
562CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *infoa,
563 CpuModelInfo *infob,
564 Error **errp)
565{
566 CpuModelCompareResult feat_result, gen_result;
567 CpuModelCompareInfo *compare_info;
568 S390FeatBitmap missing, added;
569 S390CPUModel modela, modelb;
570
571
572 cpu_model_from_info(&modela, infoa, errp);
573 if (*errp) {
574 return NULL;
575 }
576 cpu_model_from_info(&modelb, infob, errp);
577 if (*errp) {
578 return NULL;
579 }
580 compare_info = g_malloc0(sizeof(*compare_info));
581
582
583 if (modela.def->gen == modelb.def->gen) {
584 if (modela.def->ec_ga == modelb.def->ec_ga) {
585
586 gen_result = CPU_MODEL_COMPARE_RESULT_IDENTICAL;
587 } else if (modela.def->ec_ga < modelb.def->ec_ga) {
588 gen_result = CPU_MODEL_COMPARE_RESULT_SUBSET;
589 } else {
590 gen_result = CPU_MODEL_COMPARE_RESULT_SUPERSET;
591 }
592 } else if (modela.def->gen < modelb.def->gen) {
593 gen_result = CPU_MODEL_COMPARE_RESULT_SUBSET;
594 } else {
595 gen_result = CPU_MODEL_COMPARE_RESULT_SUPERSET;
596 }
597 if (gen_result != CPU_MODEL_COMPARE_RESULT_IDENTICAL) {
598
599 list_add_feat("type", &compare_info->responsible_properties);
600 }
601
602
603 if (bitmap_equal(modela.features, modelb.features, S390_FEAT_MAX)) {
604 feat_result = CPU_MODEL_COMPARE_RESULT_IDENTICAL;
605 } else {
606 bitmap_andnot(missing, modela.features, modelb.features, S390_FEAT_MAX);
607 s390_feat_bitmap_to_ascii(missing,
608 &compare_info->responsible_properties,
609 list_add_feat);
610 bitmap_andnot(added, modelb.features, modela.features, S390_FEAT_MAX);
611 s390_feat_bitmap_to_ascii(added, &compare_info->responsible_properties,
612 list_add_feat);
613 if (bitmap_empty(missing, S390_FEAT_MAX)) {
614 feat_result = CPU_MODEL_COMPARE_RESULT_SUBSET;
615 } else if (bitmap_empty(added, S390_FEAT_MAX)) {
616 feat_result = CPU_MODEL_COMPARE_RESULT_SUPERSET;
617 } else {
618 feat_result = CPU_MODEL_COMPARE_RESULT_INCOMPATIBLE;
619 }
620 }
621
622
623 if (gen_result == feat_result) {
624 compare_info->result = gen_result;
625 } else if (feat_result == CPU_MODEL_COMPARE_RESULT_IDENTICAL) {
626 compare_info->result = gen_result;
627 } else if (gen_result == CPU_MODEL_COMPARE_RESULT_IDENTICAL) {
628 compare_info->result = feat_result;
629 } else {
630 compare_info->result = CPU_MODEL_COMPARE_RESULT_INCOMPATIBLE;
631 }
632 return compare_info;
633}
634
635CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *infoa,
636 CpuModelInfo *infob,
637 Error **errp)
638{
639 CpuModelBaselineInfo *baseline_info;
640 S390CPUModel modela, modelb, model;
641 uint16_t cpu_type;
642 uint8_t max_gen_ga;
643 uint8_t max_gen;
644
645
646 cpu_model_from_info(&modela, infoa, errp);
647 if (*errp) {
648 return NULL;
649 }
650
651 cpu_model_from_info(&modelb, infob, errp);
652 if (*errp) {
653 return NULL;
654 }
655
656
657 bitmap_and(model.features, modela.features, modelb.features, S390_FEAT_MAX);
658
659
660 if (modela.def->gen == modelb.def->gen) {
661 if (modela.def->type == modelb.def->type) {
662 cpu_type = modela.def->type;
663 } else {
664 cpu_type = 0;
665 }
666 max_gen = modela.def->gen;
667 max_gen_ga = MIN(modela.def->ec_ga, modelb.def->ec_ga);
668 } else if (modela.def->gen > modelb.def->gen) {
669 cpu_type = modelb.def->type;
670 max_gen = modelb.def->gen;
671 max_gen_ga = modelb.def->ec_ga;
672 } else {
673 cpu_type = modela.def->type;
674 max_gen = modela.def->gen;
675 max_gen_ga = modela.def->ec_ga;
676 }
677
678 model.def = s390_find_cpu_def(cpu_type, max_gen, max_gen_ga,
679 model.features);
680
681 bitmap_and(model.features, model.features, model.def->full_feat,
682 S390_FEAT_MAX);
683
684 baseline_info = g_malloc0(sizeof(*baseline_info));
685 baseline_info->model = g_malloc0(sizeof(*baseline_info->model));
686 cpu_info_from_model(baseline_info->model, &model, true);
687 return baseline_info;
688}
689#endif
690
691static void check_consistency(const S390CPUModel *model)
692{
693 static int dep[][2] = {
694 { S390_FEAT_IPTE_RANGE, S390_FEAT_DAT_ENH },
695 { S390_FEAT_IDTE_SEGMENT, S390_FEAT_DAT_ENH },
696 { S390_FEAT_IDTE_REGION, S390_FEAT_DAT_ENH },
697 { S390_FEAT_IDTE_REGION, S390_FEAT_IDTE_SEGMENT },
698 { S390_FEAT_LOCAL_TLB_CLEARING, S390_FEAT_DAT_ENH},
699 { S390_FEAT_LONG_DISPLACEMENT_FAST, S390_FEAT_LONG_DISPLACEMENT },
700 { S390_FEAT_DFP_FAST, S390_FEAT_DFP },
701 { S390_FEAT_TRANSACTIONAL_EXE, S390_FEAT_STFLE_49 },
702 { S390_FEAT_EDAT_2, S390_FEAT_EDAT},
703 { S390_FEAT_MSA_EXT_5, S390_FEAT_KIMD_SHA_512 },
704 { S390_FEAT_MSA_EXT_5, S390_FEAT_KLMD_SHA_512 },
705 { S390_FEAT_MSA_EXT_4, S390_FEAT_MSA_EXT_3 },
706 { S390_FEAT_SIE_CMMA, S390_FEAT_CMM },
707 { S390_FEAT_SIE_CMMA, S390_FEAT_SIE_GSLS },
708 { S390_FEAT_SIE_PFMFI, S390_FEAT_EDAT },
709 { S390_FEAT_MSA_EXT_8, S390_FEAT_MSA_EXT_3 },
710 { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_TOD_CLOCK_STEERING },
711 { S390_FEAT_VECTOR_PACKED_DECIMAL, S390_FEAT_VECTOR },
712 { S390_FEAT_VECTOR_ENH, S390_FEAT_VECTOR },
713 { S390_FEAT_INSTRUCTION_EXEC_PROT, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2 },
714 { S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, S390_FEAT_ESOP },
715 { S390_FEAT_CMM_NT, S390_FEAT_CMM },
716 { S390_FEAT_GUARDED_STORAGE, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2 },
717 { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_STORE_CLOCK_FAST },
718 { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_TOD_CLOCK_STEERING },
719 { S390_FEAT_SEMAPHORE_ASSIST, S390_FEAT_STFLE_49 },
720 { S390_FEAT_KIMD_SHA3_224, S390_FEAT_MSA },
721 { S390_FEAT_KIMD_SHA3_256, S390_FEAT_MSA },
722 { S390_FEAT_KIMD_SHA3_384, S390_FEAT_MSA },
723 { S390_FEAT_KIMD_SHA3_512, S390_FEAT_MSA },
724 { S390_FEAT_KIMD_SHAKE_128, S390_FEAT_MSA },
725 { S390_FEAT_KIMD_SHAKE_256, S390_FEAT_MSA },
726 { S390_FEAT_KLMD_SHA3_224, S390_FEAT_MSA },
727 { S390_FEAT_KLMD_SHA3_256, S390_FEAT_MSA },
728 { S390_FEAT_KLMD_SHA3_384, S390_FEAT_MSA },
729 { S390_FEAT_KLMD_SHA3_512, S390_FEAT_MSA },
730 { S390_FEAT_KLMD_SHAKE_128, S390_FEAT_MSA },
731 { S390_FEAT_KLMD_SHAKE_256, S390_FEAT_MSA },
732 { S390_FEAT_PRNO_TRNG_QRTCR, S390_FEAT_MSA_EXT_5 },
733 { S390_FEAT_PRNO_TRNG, S390_FEAT_MSA_EXT_5 },
734 { S390_FEAT_SIE_KSS, S390_FEAT_SIE_F2 },
735 };
736 int i;
737
738 for (i = 0; i < ARRAY_SIZE(dep); i++) {
739 if (test_bit(dep[i][0], model->features) &&
740 !test_bit(dep[i][1], model->features)) {
741 warn_report("\'%s\' requires \'%s\'.",
742 s390_feat_def(dep[i][0])->name,
743 s390_feat_def(dep[i][1])->name);
744 }
745 }
746}
747
748static void error_prepend_missing_feat(const char *name, void *opaque)
749{
750 error_prepend((Error **) opaque, "%s ", name);
751}
752
753static void check_compatibility(const S390CPUModel *max_model,
754 const S390CPUModel *model, Error **errp)
755{
756 S390FeatBitmap missing;
757
758 if (model->def->gen > max_model->def->gen) {
759 error_setg(errp, "Selected CPU generation is too new. Maximum "
760 "supported model in the configuration: \'%s\'",
761 max_model->def->name);
762 return;
763 } else if (model->def->gen == max_model->def->gen &&
764 model->def->ec_ga > max_model->def->ec_ga) {
765 error_setg(errp, "Selected CPU GA level is too new. Maximum "
766 "supported model in the configuration: \'%s\'",
767 max_model->def->name);
768 return;
769 }
770
771
772 bitmap_andnot(missing, model->features, max_model->features, S390_FEAT_MAX);
773 if (bitmap_empty(missing, S390_FEAT_MAX)) {
774 return;
775 }
776
777 error_setg(errp, " ");
778 s390_feat_bitmap_to_ascii(missing, errp, error_prepend_missing_feat);
779 error_prepend(errp, "Some features requested in the CPU model are not "
780 "available in the configuration: ");
781}
782
783
784
785
786
787
788static void add_qemu_cpu_model_features(S390FeatBitmap fbm)
789{
790 static const int feats[] = {
791 S390_FEAT_DAT_ENH,
792 S390_FEAT_IDTE_SEGMENT,
793 S390_FEAT_STFLE,
794 S390_FEAT_EXTENDED_IMMEDIATE,
795 S390_FEAT_EXTENDED_TRANSLATION_2,
796 S390_FEAT_EXTENDED_TRANSLATION_3,
797 S390_FEAT_LONG_DISPLACEMENT,
798 S390_FEAT_LONG_DISPLACEMENT_FAST,
799 S390_FEAT_ETF2_ENH,
800 S390_FEAT_STORE_CLOCK_FAST,
801 S390_FEAT_MOVE_WITH_OPTIONAL_SPEC,
802 S390_FEAT_ETF3_ENH,
803 S390_FEAT_COMPARE_AND_SWAP_AND_STORE,
804 S390_FEAT_COMPARE_AND_SWAP_AND_STORE_2,
805 S390_FEAT_GENERAL_INSTRUCTIONS_EXT,
806 S390_FEAT_EXECUTE_EXT,
807 S390_FEAT_FLOATING_POINT_SUPPPORT_ENH,
808 S390_FEAT_STFLE_45,
809 S390_FEAT_STFLE_49,
810 S390_FEAT_LOCAL_TLB_CLEARING,
811 S390_FEAT_STFLE_53,
812 };
813 int i;
814
815 for (i = 0; i < ARRAY_SIZE(feats); i++) {
816 set_bit(feats[i], fbm);
817 }
818}
819
820static S390CPUModel *get_max_cpu_model(Error **errp)
821{
822 static S390CPUModel max_model;
823 static bool cached;
824
825 if (cached) {
826 return &max_model;
827 }
828
829 if (kvm_enabled()) {
830 kvm_s390_get_host_cpu_model(&max_model, errp);
831 } else {
832
833 max_model.def = &s390_cpu_defs[0];
834 bitmap_copy(max_model.features, max_model.def->default_feat,
835 S390_FEAT_MAX);
836 add_qemu_cpu_model_features(max_model.features);
837 }
838 if (!*errp) {
839 cached = true;
840 return &max_model;
841 }
842 return NULL;
843}
844
845static inline void apply_cpu_model(const S390CPUModel *model, Error **errp)
846{
847#ifndef CONFIG_USER_ONLY
848 static S390CPUModel applied_model;
849 static bool applied;
850
851
852
853
854
855 if (applied) {
856 if (model && memcmp(&applied_model, model, sizeof(S390CPUModel))) {
857 error_setg(errp, "Mixed CPU models are not supported on s390x.");
858 }
859 return;
860 }
861
862 if (kvm_enabled()) {
863 kvm_s390_apply_cpu_model(model, errp);
864 }
865
866 if (!*errp) {
867 applied = true;
868 if (model) {
869 applied_model = *model;
870 }
871 }
872#endif
873}
874
875void s390_realize_cpu_model(CPUState *cs, Error **errp)
876{
877 S390CPUClass *xcc = S390_CPU_GET_CLASS(cs);
878 S390CPU *cpu = S390_CPU(cs);
879 const S390CPUModel *max_model;
880
881 if (xcc->kvm_required && !kvm_enabled()) {
882 error_setg(errp, "CPU definition requires KVM");
883 return;
884 }
885
886 if (!cpu->model) {
887
888 apply_cpu_model(NULL, errp);
889 return;
890 }
891
892 max_model = get_max_cpu_model(errp);
893 if (*errp) {
894 error_prepend(errp, "CPU models are not available: ");
895 return;
896 }
897
898
899 cpu->model->lowest_ibc = max_model->lowest_ibc;
900 cpu->model->cpu_id = max_model->cpu_id;
901 cpu->model->cpu_id_format = max_model->cpu_id_format;
902 cpu->model->cpu_ver = max_model->cpu_ver;
903
904 check_consistency(cpu->model);
905 check_compatibility(max_model, cpu->model, errp);
906 if (*errp) {
907 return;
908 }
909
910 apply_cpu_model(cpu->model, errp);
911
912 cpu->env.cpuid = s390_cpuid_from_cpu_model(cpu->model);
913 if (tcg_enabled()) {
914
915 cpu->env.cpuid = deposit64(cpu->env.cpuid, 54, 4, cpu->env.cpu_num);
916 }
917}
918
919static void get_feature(Object *obj, Visitor *v, const char *name,
920 void *opaque, Error **errp)
921{
922 S390Feat feat = (S390Feat) opaque;
923 S390CPU *cpu = S390_CPU(obj);
924 bool value;
925
926 if (!cpu->model) {
927 error_setg(errp, "Details about the host CPU model are not available, "
928 "features cannot be queried.");
929 return;
930 }
931
932 value = test_bit(feat, cpu->model->features);
933 visit_type_bool(v, name, &value, errp);
934}
935
936static void set_feature(Object *obj, Visitor *v, const char *name,
937 void *opaque, Error **errp)
938{
939 S390Feat feat = (S390Feat) opaque;
940 DeviceState *dev = DEVICE(obj);
941 S390CPU *cpu = S390_CPU(obj);
942 bool value;
943
944 if (dev->realized) {
945 error_setg(errp, "Attempt to set property '%s' on '%s' after "
946 "it was realized", name, object_get_typename(obj));
947 return;
948 } else if (!cpu->model) {
949 error_setg(errp, "Details about the host CPU model are not available, "
950 "features cannot be changed.");
951 return;
952 }
953
954 visit_type_bool(v, name, &value, errp);
955 if (*errp) {
956 return;
957 }
958 if (value) {
959 if (!test_bit(feat, cpu->model->def->full_feat)) {
960 error_setg(errp, "Feature '%s' is not available for CPU model '%s',"
961 " it was introduced with later models.",
962 name, cpu->model->def->name);
963 return;
964 }
965 set_bit(feat, cpu->model->features);
966 } else {
967 clear_bit(feat, cpu->model->features);
968 }
969}
970
971static void get_feature_group(Object *obj, Visitor *v, const char *name,
972 void *opaque, Error **errp)
973{
974 S390FeatGroup group = (S390FeatGroup) opaque;
975 const S390FeatGroupDef *def = s390_feat_group_def(group);
976 S390CPU *cpu = S390_CPU(obj);
977 S390FeatBitmap tmp;
978 bool value;
979
980 if (!cpu->model) {
981 error_setg(errp, "Details about the host CPU model are not available, "
982 "features cannot be queried.");
983 return;
984 }
985
986
987 bitmap_and(tmp, cpu->model->features, def->feat, S390_FEAT_MAX);
988 value = bitmap_equal(tmp, def->feat, S390_FEAT_MAX);
989 visit_type_bool(v, name, &value, errp);
990}
991
992static void set_feature_group(Object *obj, Visitor *v, const char *name,
993 void *opaque, Error **errp)
994{
995 S390FeatGroup group = (S390FeatGroup) opaque;
996 const S390FeatGroupDef *def = s390_feat_group_def(group);
997 DeviceState *dev = DEVICE(obj);
998 S390CPU *cpu = S390_CPU(obj);
999 bool value;
1000
1001 if (dev->realized) {
1002 error_setg(errp, "Attempt to set property '%s' on '%s' after "
1003 "it was realized", name, object_get_typename(obj));
1004 return;
1005 } else if (!cpu->model) {
1006 error_setg(errp, "Details about the host CPU model are not available, "
1007 "features cannot be changed.");
1008 return;
1009 }
1010
1011 visit_type_bool(v, name, &value, errp);
1012 if (*errp) {
1013 return;
1014 }
1015 if (value) {
1016
1017 if (!bitmap_intersects(def->feat, cpu->model->def->full_feat,
1018 S390_FEAT_MAX)) {
1019 error_setg(errp, "Group '%s' is not available for CPU model '%s',"
1020 " it was introduced with later models.",
1021 name, cpu->model->def->name);
1022 return;
1023 }
1024 bitmap_or(cpu->model->features, cpu->model->features, def->feat,
1025 S390_FEAT_MAX);
1026 } else {
1027 bitmap_andnot(cpu->model->features, cpu->model->features, def->feat,
1028 S390_FEAT_MAX);
1029 }
1030}
1031
1032void s390_cpu_model_register_props(Object *obj)
1033{
1034 S390FeatGroup group;
1035 S390Feat feat;
1036
1037 for (feat = 0; feat < S390_FEAT_MAX; feat++) {
1038 const S390FeatDef *def = s390_feat_def(feat);
1039 object_property_add(obj, def->name, "bool", get_feature,
1040 set_feature, NULL, (void *) feat, NULL);
1041 object_property_set_description(obj, def->name, def->desc , NULL);
1042 }
1043 for (group = 0; group < S390_FEAT_GROUP_MAX; group++) {
1044 const S390FeatGroupDef *def = s390_feat_group_def(group);
1045 object_property_add(obj, def->name, "bool", get_feature_group,
1046 set_feature_group, NULL, (void *) group, NULL);
1047 object_property_set_description(obj, def->name, def->desc , NULL);
1048 }
1049}
1050
1051static void s390_cpu_model_initfn(Object *obj)
1052{
1053 S390CPU *cpu = S390_CPU(obj);
1054 S390CPUClass *xcc = S390_CPU_GET_CLASS(cpu);
1055
1056 cpu->model = g_malloc0(sizeof(*cpu->model));
1057
1058 cpu->model->def = xcc->cpu_def;
1059 if (xcc->is_static) {
1060
1061 bitmap_copy(cpu->model->features, cpu->model->def->base_feat,
1062 S390_FEAT_MAX);
1063 } else {
1064
1065 bitmap_copy(cpu->model->features,
1066 cpu->model->def->default_feat, S390_FEAT_MAX);
1067 }
1068}
1069
1070#ifdef CONFIG_KVM
1071static void s390_host_cpu_model_initfn(Object *obj)
1072{
1073 S390CPU *cpu = S390_CPU(obj);
1074 Error *err = NULL;
1075
1076 if (!kvm_enabled() || !kvm_s390_cpu_models_supported()) {
1077 return;
1078 }
1079
1080 cpu->model = g_malloc0(sizeof(*cpu->model));
1081 kvm_s390_get_host_cpu_model(cpu->model, &err);
1082 if (err) {
1083 error_report_err(err);
1084 g_free(cpu->model);
1085
1086 cpu->model = NULL;
1087 }
1088}
1089#endif
1090
1091static void s390_qemu_cpu_model_initfn(Object *obj)
1092{
1093 static S390CPUDef s390_qemu_cpu_defs;
1094 S390CPU *cpu = S390_CPU(obj);
1095
1096 cpu->model = g_malloc0(sizeof(*cpu->model));
1097
1098 memcpy(&s390_qemu_cpu_defs, &s390_cpu_defs[0], sizeof(s390_qemu_cpu_defs));
1099 add_qemu_cpu_model_features(s390_qemu_cpu_defs.full_feat);
1100 cpu->model->def = &s390_qemu_cpu_defs;
1101 bitmap_copy(cpu->model->features, cpu->model->def->default_feat,
1102 S390_FEAT_MAX);
1103}
1104
1105static void s390_cpu_model_finalize(Object *obj)
1106{
1107 S390CPU *cpu = S390_CPU(obj);
1108
1109 g_free(cpu->model);
1110 cpu->model = NULL;
1111}
1112
1113static bool get_is_migration_safe(Object *obj, Error **errp)
1114{
1115 return S390_CPU_GET_CLASS(obj)->is_migration_safe;
1116}
1117
1118static bool get_is_static(Object *obj, Error **errp)
1119{
1120 return S390_CPU_GET_CLASS(obj)->is_static;
1121}
1122
1123static char *get_description(Object *obj, Error **errp)
1124{
1125 return g_strdup(S390_CPU_GET_CLASS(obj)->desc);
1126}
1127
1128void s390_cpu_model_class_register_props(ObjectClass *oc)
1129{
1130 object_class_property_add_bool(oc, "migration-safe", get_is_migration_safe,
1131 NULL, NULL);
1132 object_class_property_add_bool(oc, "static", get_is_static,
1133 NULL, NULL);
1134 object_class_property_add_str(oc, "description", get_description, NULL,
1135 NULL);
1136}
1137
1138#ifdef CONFIG_KVM
1139static void s390_host_cpu_model_class_init(ObjectClass *oc, void *data)
1140{
1141 S390CPUClass *xcc = S390_CPU_CLASS(oc);
1142
1143 xcc->kvm_required = true;
1144 xcc->desc = "KVM only: All recognized features";
1145}
1146#endif
1147
1148static void s390_base_cpu_model_class_init(ObjectClass *oc, void *data)
1149{
1150 S390CPUClass *xcc = S390_CPU_CLASS(oc);
1151
1152
1153 xcc->cpu_def = (const S390CPUDef *) data;
1154 xcc->is_migration_safe = true;
1155 xcc->is_static = true;
1156 xcc->desc = xcc->cpu_def->desc;
1157}
1158
1159static void s390_cpu_model_class_init(ObjectClass *oc, void *data)
1160{
1161 S390CPUClass *xcc = S390_CPU_CLASS(oc);
1162
1163
1164 xcc->cpu_def = (const S390CPUDef *) data;
1165 xcc->is_migration_safe = true;
1166 xcc->desc = xcc->cpu_def->desc;
1167}
1168
1169static void s390_qemu_cpu_model_class_init(ObjectClass *oc, void *data)
1170{
1171 S390CPUClass *xcc = S390_CPU_CLASS(oc);
1172
1173 xcc->is_migration_safe = true;
1174 xcc->desc = g_strdup_printf("QEMU Virtual CPU version %s",
1175 qemu_hw_version());
1176}
1177
1178#define S390_CPU_TYPE_SUFFIX "-" TYPE_S390_CPU
1179#define S390_CPU_TYPE_NAME(name) (name S390_CPU_TYPE_SUFFIX)
1180
1181
1182static char *s390_cpu_type_name(const char *model_name)
1183{
1184 return g_strdup_printf(S390_CPU_TYPE_NAME("%s"), model_name);
1185}
1186
1187
1188static char *s390_base_cpu_type_name(const char *model_name)
1189{
1190 return g_strdup_printf(S390_CPU_TYPE_NAME("%s-base"), model_name);
1191}
1192
1193ObjectClass *s390_cpu_class_by_name(const char *name)
1194{
1195 char *typename = s390_cpu_type_name(name);
1196 ObjectClass *oc;
1197
1198 oc = object_class_by_name(typename);
1199 g_free(typename);
1200 return oc;
1201}
1202
1203static const TypeInfo qemu_s390_cpu_type_info = {
1204 .name = S390_CPU_TYPE_NAME("qemu"),
1205 .parent = TYPE_S390_CPU,
1206 .instance_init = s390_qemu_cpu_model_initfn,
1207 .instance_finalize = s390_cpu_model_finalize,
1208 .class_init = s390_qemu_cpu_model_class_init,
1209};
1210
1211#ifdef CONFIG_KVM
1212static const TypeInfo host_s390_cpu_type_info = {
1213 .name = S390_CPU_TYPE_NAME("host"),
1214 .parent = TYPE_S390_CPU,
1215 .instance_init = s390_host_cpu_model_initfn,
1216 .instance_finalize = s390_cpu_model_finalize,
1217 .class_init = s390_host_cpu_model_class_init,
1218};
1219#endif
1220
1221static void init_ignored_base_feat(void)
1222{
1223 static const int feats[] = {
1224
1225 S390_FEAT_KMAC_DEA,
1226 S390_FEAT_KMAC_TDEA_128,
1227 S390_FEAT_KMAC_TDEA_192,
1228 S390_FEAT_KMC_DEA,
1229 S390_FEAT_KMC_TDEA_128,
1230 S390_FEAT_KMC_TDEA_192,
1231 S390_FEAT_KM_DEA,
1232 S390_FEAT_KM_TDEA_128,
1233 S390_FEAT_KM_TDEA_192,
1234 S390_FEAT_KIMD_SHA_1,
1235 S390_FEAT_KLMD_SHA_1,
1236 };
1237 int i;
1238
1239 for (i = 0; i < ARRAY_SIZE(feats); i++) {
1240 set_bit(feats[i], ignored_base_feat);
1241 }
1242}
1243
1244static void register_types(void)
1245{
1246 int i;
1247
1248 init_ignored_base_feat();
1249
1250
1251 for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
1252 s390_init_feat_bitmap(s390_cpu_defs[i].base_init,
1253 s390_cpu_defs[i].base_feat);
1254 s390_init_feat_bitmap(s390_cpu_defs[i].default_init,
1255 s390_cpu_defs[i].default_feat);
1256 s390_init_feat_bitmap(s390_cpu_defs[i].full_init,
1257 s390_cpu_defs[i].full_feat);
1258 }
1259
1260 for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
1261 char *base_name = s390_base_cpu_type_name(s390_cpu_defs[i].name);
1262 TypeInfo ti_base = {
1263 .name = base_name,
1264 .parent = TYPE_S390_CPU,
1265 .instance_init = s390_cpu_model_initfn,
1266 .instance_finalize = s390_cpu_model_finalize,
1267 .class_init = s390_base_cpu_model_class_init,
1268 .class_data = (void *) &s390_cpu_defs[i],
1269 };
1270 char *name = s390_cpu_type_name(s390_cpu_defs[i].name);
1271 TypeInfo ti = {
1272 .name = name,
1273 .parent = TYPE_S390_CPU,
1274 .instance_init = s390_cpu_model_initfn,
1275 .instance_finalize = s390_cpu_model_finalize,
1276 .class_init = s390_cpu_model_class_init,
1277 .class_data = (void *) &s390_cpu_defs[i],
1278 };
1279
1280 type_register_static(&ti_base);
1281 type_register_static(&ti);
1282 g_free(base_name);
1283 g_free(name);
1284 }
1285
1286 type_register_static(&qemu_s390_cpu_type_info);
1287#ifdef CONFIG_KVM
1288 type_register_static(&host_s390_cpu_type_info);
1289#endif
1290}
1291
1292type_init(register_types)
1293