2 * i386 CPUID, CPU class, definitions, models: sysemu-only code
4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "qapi/qapi-visit-run-state.h"
24 #include "qapi/qmp/qdict.h"
25 #include "qapi/qobject-input-visitor.h"
26 #include "qom/qom-qobject.h"
27 #include "qapi/qapi-commands-machine-target.h"
29 #include "cpu-internal.h"
31 /* Return a QDict containing keys for all properties that can be included
32 * in static expansion of CPU models. All properties set by x86_cpu_load_model()
33 * must be included in the dictionary.
35 static QDict
*x86_cpu_static_props(void)
39 static const char *props
[] = {
57 for (i
= 0; props
[i
]; i
++) {
58 qdict_put_null(d
, props
[i
]);
61 for (w
= 0; w
< FEATURE_WORDS
; w
++) {
62 FeatureWordInfo
*fi
= &feature_word_info
[w
];
64 for (bit
= 0; bit
< 64; bit
++) {
65 if (!fi
->feat_names
[bit
]) {
68 qdict_put_null(d
, fi
->feat_names
[bit
]);
75 /* Add an entry to @props dict, with the value for property. */
76 static void x86_cpu_expand_prop(X86CPU
*cpu
, QDict
*props
, const char *prop
)
78 QObject
*value
= object_property_get_qobject(OBJECT(cpu
), prop
,
81 qdict_put_obj(props
, prop
, value
);
84 /* Convert CPU model data from X86CPU object to a property dictionary
85 * that can recreate exactly the same CPU model.
87 static void x86_cpu_to_dict(X86CPU
*cpu
, QDict
*props
)
89 QDict
*sprops
= x86_cpu_static_props();
92 for (e
= qdict_first(sprops
); e
; e
= qdict_next(sprops
, e
)) {
93 const char *prop
= qdict_entry_key(e
);
94 x86_cpu_expand_prop(cpu
, props
, prop
);
98 /* Convert CPU model data from X86CPU object to a property dictionary
99 * that can recreate exactly the same CPU model, including every
100 * writable QOM property.
102 static void x86_cpu_to_dict_full(X86CPU
*cpu
, QDict
*props
)
104 ObjectPropertyIterator iter
;
105 ObjectProperty
*prop
;
107 object_property_iter_init(&iter
, OBJECT(cpu
));
108 while ((prop
= object_property_iter_next(&iter
))) {
109 /* skip read-only or write-only properties */
110 if (!prop
->get
|| !prop
->set
) {
114 /* "hotplugged" is the only property that is configurable
115 * on the command-line but will be set differently on CPUs
116 * created using "-cpu ... -smp ..." and by CPUs created
117 * on the fly by x86_cpu_from_model() for querying. Skip it.
119 if (!strcmp(prop
->name
, "hotplugged")) {
122 x86_cpu_expand_prop(cpu
, props
, prop
->name
);
126 static void object_apply_props(Object
*obj
, QObject
*props
,
127 const char *props_arg_name
, Error
**errp
)
131 const QDictEntry
*prop
;
133 visitor
= qobject_input_visitor_new(props
);
134 if (!visit_start_struct(visitor
, props_arg_name
, NULL
, 0, errp
)) {
139 qdict
= qobject_to(QDict
, props
);
140 for (prop
= qdict_first(qdict
); prop
; prop
= qdict_next(qdict
, prop
)) {
141 if (!object_property_set(obj
, qdict_entry_key(prop
),
147 visit_check_struct(visitor
, errp
);
149 visit_end_struct(visitor
, NULL
);
153 /* Create X86CPU object according to model+props specification */
154 static X86CPU
*x86_cpu_from_model(const char *model
, QObject
*props
,
155 const char *props_arg_name
, Error
**errp
)
161 xcc
= X86_CPU_CLASS(cpu_class_by_name(TYPE_X86_CPU
, model
));
163 error_setg(&err
, "CPU model '%s' not found", model
);
167 xc
= X86_CPU(object_new_with_class(OBJECT_CLASS(xcc
)));
169 object_apply_props(OBJECT(xc
), props
, props_arg_name
, &err
);
175 x86_cpu_expand_features(xc
, &err
);
182 error_propagate(errp
, err
);
183 object_unref(OBJECT(xc
));
189 CpuModelExpansionInfo
*
190 qmp_query_cpu_model_expansion(CpuModelExpansionType type
,
196 CpuModelExpansionInfo
*ret
= g_new0(CpuModelExpansionInfo
, 1);
198 const char *base_name
;
200 xc
= x86_cpu_from_model(model
->name
, model
->props
, "model.props", &err
);
206 ret
->model
= g_new0(CpuModelInfo
, 1);
207 ret
->model
->props
= QOBJECT(props
);
210 case CPU_MODEL_EXPANSION_TYPE_STATIC
:
211 /* Static expansion will be based on "base" only */
213 x86_cpu_to_dict(xc
, props
);
215 case CPU_MODEL_EXPANSION_TYPE_FULL
:
216 /* As we don't return every single property, full expansion needs
217 * to keep the original model name+props, and add extra
218 * properties on top of that.
220 base_name
= model
->name
;
221 x86_cpu_to_dict_full(xc
, props
);
224 error_setg(&err
, "Unsupported expansion type");
228 x86_cpu_to_dict(xc
, props
);
230 ret
->model
->name
= g_strdup(base_name
);
233 object_unref(OBJECT(xc
));
235 error_propagate(errp
, err
);
236 qapi_free_CpuModelExpansionInfo(ret
);
242 void cpu_clear_apic_feature(CPUX86State
*env
)
244 env
->features
[FEAT_1_EDX
] &= ~CPUID_APIC
;
247 void cpu_set_apic_feature(CPUX86State
*env
)
249 env
->features
[FEAT_1_EDX
] |= CPUID_APIC
;
252 bool cpu_has_x2apic_feature(CPUX86State
*env
)
254 return env
->features
[FEAT_1_ECX
] & CPUID_EXT_X2APIC
;
257 bool cpu_is_bsp(X86CPU
*cpu
)
259 return cpu_get_apic_base(cpu
->apic_state
) & MSR_IA32_APICBASE_BSP
;
262 /* TODO: remove me, when reset over QOM tree is implemented */
263 void x86_cpu_machine_reset_cb(void *opaque
)
265 X86CPU
*cpu
= opaque
;
269 GuestPanicInformation
*x86_cpu_get_crash_info(CPUState
*cs
)
271 X86CPU
*cpu
= X86_CPU(cs
);
272 CPUX86State
*env
= &cpu
->env
;
273 GuestPanicInformation
*panic_info
= NULL
;
275 if (hyperv_feat_enabled(cpu
, HYPERV_FEAT_CRASH
)) {
276 panic_info
= g_new0(GuestPanicInformation
, 1);
278 panic_info
->type
= GUEST_PANIC_INFORMATION_TYPE_HYPER_V
;
280 assert(HV_CRASH_PARAMS
>= 5);
281 panic_info
->u
.hyper_v
.arg1
= env
->msr_hv_crash_params
[0];
282 panic_info
->u
.hyper_v
.arg2
= env
->msr_hv_crash_params
[1];
283 panic_info
->u
.hyper_v
.arg3
= env
->msr_hv_crash_params
[2];
284 panic_info
->u
.hyper_v
.arg4
= env
->msr_hv_crash_params
[3];
285 panic_info
->u
.hyper_v
.arg5
= env
->msr_hv_crash_params
[4];
290 void x86_cpu_get_crash_info_qom(Object
*obj
, Visitor
*v
,
291 const char *name
, void *opaque
,
294 CPUState
*cs
= CPU(obj
);
295 GuestPanicInformation
*panic_info
;
297 if (!cs
->crash_occurred
) {
298 error_setg(errp
, "No crash occurred");
302 panic_info
= x86_cpu_get_crash_info(cs
);
303 if (panic_info
== NULL
) {
304 error_setg(errp
, "No crash information");
308 visit_type_GuestPanicInformation(v
, "crash-information", &panic_info
,
310 qapi_free_GuestPanicInformation(panic_info
);