s390x/cpumodel: implement QMP interface "query-cpu-model-expansion"
In order to expand CPU models, we create temporary cpus that handle the feature/group parsing. Only CPU feature properties are expanded. When converting the data structure back, we always fall back to the static base CPU model, which is by definition migration-safe. Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Message-Id: <20160905085244.99980-29-dahi@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
		
							parent
							
								
									b18b604334
								
							
						
					
					
						commit
						137974cea3
					
				| @ -3143,7 +3143,8 @@ | |||||||
| #   global properties may affect expansion of CPU models. Using | #   global properties may affect expansion of CPU models. Using | ||||||
| #   query-cpu-model-expansion while using these is not advised. | #   query-cpu-model-expansion while using these is not advised. | ||||||
| # | # | ||||||
| # Some architectures may not support all expansion types. | # Some architectures may not support all expansion types. s390x supports | ||||||
|  | # "full" and "static". | ||||||
| # | # | ||||||
| # Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is | # Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is | ||||||
| #          not supported, if the model cannot be expanded, if the model contains | #          not supported, if the model cannot be expanded, if the model contains | ||||||
|  | |||||||
| @ -16,6 +16,9 @@ | |||||||
| #include "qapi/error.h" | #include "qapi/error.h" | ||||||
| #include "qapi/visitor.h" | #include "qapi/visitor.h" | ||||||
| #include "qemu/error-report.h" | #include "qemu/error-report.h" | ||||||
|  | #include "qapi/qmp/qerror.h" | ||||||
|  | #include "qapi/qmp-input-visitor.h" | ||||||
|  | #include "qapi/qmp/qbool.h" | ||||||
| #ifndef CONFIG_USER_ONLY | #ifndef CONFIG_USER_ONLY | ||||||
| #include "sysemu/arch_init.h" | #include "sysemu/arch_init.h" | ||||||
| #endif | #endif | ||||||
| @ -303,6 +306,150 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) | |||||||
| 
 | 
 | ||||||
|     return list; |     return list; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info, | ||||||
|  |                                 Error **errp) | ||||||
|  | { | ||||||
|  |     const QDict *qdict = NULL; | ||||||
|  |     const QDictEntry *e; | ||||||
|  |     Visitor *visitor; | ||||||
|  |     ObjectClass *oc; | ||||||
|  |     S390CPU *cpu; | ||||||
|  |     Object *obj; | ||||||
|  | 
 | ||||||
|  |     if (info->props) { | ||||||
|  |         qdict = qobject_to_qdict(info->props); | ||||||
|  |         if (!qdict) { | ||||||
|  |             error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     oc = cpu_class_by_name(TYPE_S390_CPU, info->name); | ||||||
|  |     if (!oc) { | ||||||
|  |         error_setg(errp, "The CPU definition \'%s\' is unknown.", info->name); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     if (S390_CPU_CLASS(oc)->kvm_required && !kvm_enabled()) { | ||||||
|  |         error_setg(errp, "The CPU definition '%s' requires KVM", info->name); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     obj = object_new(object_class_get_name(oc)); | ||||||
|  |     cpu = S390_CPU(obj); | ||||||
|  | 
 | ||||||
|  |     if (!cpu->model) { | ||||||
|  |         error_setg(errp, "Details about the host CPU model are not available, " | ||||||
|  |                          "it cannot be used."); | ||||||
|  |         object_unref(obj); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (qdict) { | ||||||
|  |         visitor = qmp_input_visitor_new(info->props, true); | ||||||
|  |         visit_start_struct(visitor, NULL, NULL, 0, errp); | ||||||
|  |         if (*errp) { | ||||||
|  |             object_unref(obj); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { | ||||||
|  |             object_property_set(obj, visitor, e->key, errp); | ||||||
|  |             if (*errp) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (!*errp) { | ||||||
|  |             visit_check_struct(visitor, errp); | ||||||
|  |         } | ||||||
|  |         visit_end_struct(visitor, NULL); | ||||||
|  |         visit_free(visitor); | ||||||
|  |         if (*errp) { | ||||||
|  |             object_unref(obj); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* copy the model and throw the cpu away */ | ||||||
|  |     memcpy(model, cpu->model, sizeof(*model)); | ||||||
|  |     object_unref(obj); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void qdict_add_disabled_feat(const char *name, void *opaque) | ||||||
|  | { | ||||||
|  |     qdict_put((QDict *) opaque, name, qbool_from_bool(false)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void qdict_add_enabled_feat(const char *name, void *opaque) | ||||||
|  | { | ||||||
|  |     qdict_put((QDict *) opaque, name, qbool_from_bool(true)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* convert S390CPUDef into a static CpuModelInfo */ | ||||||
|  | static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model, | ||||||
|  |                                 bool delta_changes) | ||||||
|  | { | ||||||
|  |     QDict *qdict = qdict_new(); | ||||||
|  |     S390FeatBitmap bitmap; | ||||||
|  | 
 | ||||||
|  |     /* always fallback to the static base model */ | ||||||
|  |     info->name = g_strdup_printf("%s-base", model->def->name); | ||||||
|  | 
 | ||||||
|  |     if (delta_changes) { | ||||||
|  |         /* features deleted from the base feature set */ | ||||||
|  |         bitmap_andnot(bitmap, model->def->base_feat, model->features, | ||||||
|  |                       S390_FEAT_MAX); | ||||||
|  |         if (!bitmap_empty(bitmap, S390_FEAT_MAX)) { | ||||||
|  |             s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_disabled_feat); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /* features added to the base feature set */ | ||||||
|  |         bitmap_andnot(bitmap, model->features, model->def->base_feat, | ||||||
|  |                       S390_FEAT_MAX); | ||||||
|  |         if (!bitmap_empty(bitmap, S390_FEAT_MAX)) { | ||||||
|  |             s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_enabled_feat); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         /* expand all features */ | ||||||
|  |         s390_feat_bitmap_to_ascii(model->features, qdict, | ||||||
|  |                                   qdict_add_enabled_feat); | ||||||
|  |         bitmap_complement(bitmap, model->features, S390_FEAT_MAX); | ||||||
|  |         s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_disabled_feat); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!qdict_size(qdict)) { | ||||||
|  |         QDECREF(qdict); | ||||||
|  |     } else { | ||||||
|  |         info->props = QOBJECT(qdict); | ||||||
|  |         info->has_props = true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type, | ||||||
|  |                                                       CpuModelInfo *model, | ||||||
|  |                                                       Error **errp) | ||||||
|  | { | ||||||
|  |     CpuModelExpansionInfo *expansion_info = NULL; | ||||||
|  |     S390CPUModel s390_model; | ||||||
|  |     bool delta_changes = false; | ||||||
|  | 
 | ||||||
|  |     /* convert it to our internal representation */ | ||||||
|  |     cpu_model_from_info(&s390_model, model, errp); | ||||||
|  |     if (*errp) { | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (type == CPU_MODEL_EXPANSION_TYPE_STATIC) { | ||||||
|  |         delta_changes = true; | ||||||
|  |     } else if (type != CPU_MODEL_EXPANSION_TYPE_FULL) { | ||||||
|  |         error_setg(errp, "The requested expansion type is not supported."); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* convert it back to a static representation */ | ||||||
|  |     expansion_info = g_malloc0(sizeof(*expansion_info)); | ||||||
|  |     expansion_info->model = g_malloc0(sizeof(*expansion_info->model)); | ||||||
|  |     cpu_info_from_model(expansion_info->model, &s390_model, delta_changes); | ||||||
|  |     return expansion_info; | ||||||
|  | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| static void check_consistency(const S390CPUModel *model) | static void check_consistency(const S390CPUModel *model) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 David Hildenbrand
						David Hildenbrand