xref: /openbmc/qemu/hw/i386/x86.c (revision d74ec4d7dda6322bcc51d1b13ccbd993d3574795)
1549e984eSSergio Lopez /*
2549e984eSSergio Lopez  * Copyright (c) 2003-2004 Fabrice Bellard
3549e984eSSergio Lopez  * Copyright (c) 2019 Red Hat, Inc.
4549e984eSSergio Lopez  *
5549e984eSSergio Lopez  * Permission is hereby granted, free of charge, to any person obtaining a copy
6549e984eSSergio Lopez  * of this software and associated documentation files (the "Software"), to deal
7549e984eSSergio Lopez  * in the Software without restriction, including without limitation the rights
8549e984eSSergio Lopez  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9549e984eSSergio Lopez  * copies of the Software, and to permit persons to whom the Software is
10549e984eSSergio Lopez  * furnished to do so, subject to the following conditions:
11549e984eSSergio Lopez  *
12549e984eSSergio Lopez  * The above copyright notice and this permission notice shall be included in
13549e984eSSergio Lopez  * all copies or substantial portions of the Software.
14549e984eSSergio Lopez  *
15549e984eSSergio Lopez  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16549e984eSSergio Lopez  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17549e984eSSergio Lopez  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18549e984eSSergio Lopez  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19549e984eSSergio Lopez  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20549e984eSSergio Lopez  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21549e984eSSergio Lopez  * THE SOFTWARE.
22549e984eSSergio Lopez  */
23549e984eSSergio Lopez #include "qemu/osdep.h"
24549e984eSSergio Lopez #include "qemu/error-report.h"
25549e984eSSergio Lopez #include "qemu/units.h"
26549e984eSSergio Lopez #include "qapi/error.h"
27549e984eSSergio Lopez #include "qapi/qapi-visit-common.h"
28dfce81f1SSean Christopherson #include "qapi/qapi-visit-machine.h"
29549e984eSSergio Lopez #include "qapi/visitor.h"
30549e984eSSergio Lopez #include "sysemu/qtest.h"
31549e984eSSergio Lopez #include "sysemu/numa.h"
3289a289c7SPaolo Bonzini #include "trace.h"
33549e984eSSergio Lopez 
34b061f059SPaolo Bonzini #include "hw/acpi/aml-build.h"
35549e984eSSergio Lopez #include "hw/i386/x86.h"
36549e984eSSergio Lopez #include "hw/i386/topology.h"
37549e984eSSergio Lopez 
38549e984eSSergio Lopez #include "hw/nmi.h"
39a9dc68d9SClaudio Fontana #include "kvm/kvm_i386.h"
40549e984eSSergio Lopez 
414f81baa3SDavid Woodhouse 
init_topo_info(X86CPUTopoInfo * topo_info,const X86MachineState * x86ms)42b061f059SPaolo Bonzini void init_topo_info(X86CPUTopoInfo *topo_info,
4353a5e7bdSBabu Moger                     const X86MachineState *x86ms)
4453a5e7bdSBabu Moger {
4553a5e7bdSBabu Moger     MachineState *ms = MACHINE(x86ms);
4653a5e7bdSBabu Moger 
4767872eb8SPaolo Bonzini     topo_info->dies_per_pkg = ms->smp.dies;
483568adc9SZhao Liu     /*
493568adc9SZhao Liu      * Though smp.modules means the number of modules in one cluster,
503568adc9SZhao Liu      * i386 doesn't support cluster level so that the smp.clusters
513568adc9SZhao Liu      * always defaults to 1, therefore using smp.modules directly is
523568adc9SZhao Liu      * fine here.
533568adc9SZhao Liu      */
543568adc9SZhao Liu     topo_info->modules_per_die = ms->smp.modules;
553568adc9SZhao Liu     topo_info->cores_per_module = ms->smp.cores;
5653a5e7bdSBabu Moger     topo_info->threads_per_core = ms->smp.threads;
5753a5e7bdSBabu Moger }
5853a5e7bdSBabu Moger 
59549e984eSSergio Lopez /*
60549e984eSSergio Lopez  * Calculates initial APIC ID for a specific CPU index
61549e984eSSergio Lopez  *
62549e984eSSergio Lopez  * Currently we need to be able to calculate the APIC ID from the CPU index
63549e984eSSergio Lopez  * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces have
64549e984eSSergio Lopez  * no concept of "CPU index", and the NUMA tables on fw_cfg need the APIC ID of
65549e984eSSergio Lopez  * all CPUs up to max_cpus.
66549e984eSSergio Lopez  */
x86_cpu_apic_id_from_index(X86MachineState * x86ms,unsigned int cpu_index)67703a548aSSergio Lopez uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
68549e984eSSergio Lopez                                     unsigned int cpu_index)
69549e984eSSergio Lopez {
7053a5e7bdSBabu Moger     X86CPUTopoInfo topo_info;
71549e984eSSergio Lopez 
7253a5e7bdSBabu Moger     init_topo_info(&topo_info, x86ms);
7353a5e7bdSBabu Moger 
74e6895f04SIgor Mammedov     return x86_apicid_from_cpu_idx(&topo_info, cpu_index);
75549e984eSSergio Lopez }
76549e984eSSergio Lopez 
77b348fdcdSPaolo Bonzini static CpuInstanceProperties
x86_cpu_index_to_props(MachineState * ms,unsigned cpu_index)78549e984eSSergio Lopez x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
79549e984eSSergio Lopez {
80549e984eSSergio Lopez     MachineClass *mc = MACHINE_GET_CLASS(ms);
81549e984eSSergio Lopez     const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
82549e984eSSergio Lopez 
83549e984eSSergio Lopez     assert(cpu_index < possible_cpus->len);
84549e984eSSergio Lopez     return possible_cpus->cpus[cpu_index].props;
85549e984eSSergio Lopez }
86549e984eSSergio Lopez 
x86_get_default_cpu_node_id(const MachineState * ms,int idx)87b348fdcdSPaolo Bonzini static int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
88549e984eSSergio Lopez {
89dcf08bc6SBabu Moger    X86CPUTopoIDs topo_ids;
90f0bb276bSPaolo Bonzini    X86MachineState *x86ms = X86_MACHINE(ms);
9153a5e7bdSBabu Moger    X86CPUTopoInfo topo_info;
9253a5e7bdSBabu Moger 
9353a5e7bdSBabu Moger    init_topo_info(&topo_info, x86ms);
94549e984eSSergio Lopez 
95549e984eSSergio Lopez    assert(idx < ms->possible_cpus->len);
96dfe7ed0aSBabu Moger    x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id,
97dfe7ed0aSBabu Moger                             &topo_info, &topo_ids);
98dcf08bc6SBabu Moger    return topo_ids.pkg_id % ms->numa_state->num_nodes;
99549e984eSSergio Lopez }
100549e984eSSergio Lopez 
x86_possible_cpu_arch_ids(MachineState * ms)101b348fdcdSPaolo Bonzini static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
102549e984eSSergio Lopez {
103f0bb276bSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(ms);
104549e984eSSergio Lopez     unsigned int max_cpus = ms->smp.max_cpus;
10553a5e7bdSBabu Moger     X86CPUTopoInfo topo_info;
10653a5e7bdSBabu Moger     int i;
107549e984eSSergio Lopez 
108549e984eSSergio Lopez     if (ms->possible_cpus) {
109549e984eSSergio Lopez         /*
110549e984eSSergio Lopez          * make sure that max_cpus hasn't changed since the first use, i.e.
111549e984eSSergio Lopez          * -smp hasn't been parsed after it
112549e984eSSergio Lopez          */
113549e984eSSergio Lopez         assert(ms->possible_cpus->len == max_cpus);
114549e984eSSergio Lopez         return ms->possible_cpus;
115549e984eSSergio Lopez     }
116549e984eSSergio Lopez 
117549e984eSSergio Lopez     ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
118549e984eSSergio Lopez                                   sizeof(CPUArchId) * max_cpus);
119549e984eSSergio Lopez     ms->possible_cpus->len = max_cpus;
12053a5e7bdSBabu Moger 
12153a5e7bdSBabu Moger     init_topo_info(&topo_info, x86ms);
12253a5e7bdSBabu Moger 
123549e984eSSergio Lopez     for (i = 0; i < ms->possible_cpus->len; i++) {
124dcf08bc6SBabu Moger         X86CPUTopoIDs topo_ids;
125549e984eSSergio Lopez 
126549e984eSSergio Lopez         ms->possible_cpus->cpus[i].type = ms->cpu_type;
127549e984eSSergio Lopez         ms->possible_cpus->cpus[i].vcpus_count = 1;
128dfe7ed0aSBabu Moger         ms->possible_cpus->cpus[i].arch_id =
129dfe7ed0aSBabu Moger             x86_cpu_apic_id_from_index(x86ms, i);
130dfe7ed0aSBabu Moger         x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id,
131dfe7ed0aSBabu Moger                                  &topo_info, &topo_ids);
132549e984eSSergio Lopez         ms->possible_cpus->cpus[i].props.has_socket_id = true;
133dcf08bc6SBabu Moger         ms->possible_cpus->cpus[i].props.socket_id = topo_ids.pkg_id;
13467872eb8SPaolo Bonzini         if (ms->smp.dies > 1) {
135549e984eSSergio Lopez             ms->possible_cpus->cpus[i].props.has_die_id = true;
136dcf08bc6SBabu Moger             ms->possible_cpus->cpus[i].props.die_id = topo_ids.die_id;
137549e984eSSergio Lopez         }
138b17a26bcSZhao Liu         if (ms->smp.modules > 1) {
139b17a26bcSZhao Liu             ms->possible_cpus->cpus[i].props.has_module_id = true;
140b17a26bcSZhao Liu             ms->possible_cpus->cpus[i].props.module_id = topo_ids.module_id;
141b17a26bcSZhao Liu         }
142549e984eSSergio Lopez         ms->possible_cpus->cpus[i].props.has_core_id = true;
143dcf08bc6SBabu Moger         ms->possible_cpus->cpus[i].props.core_id = topo_ids.core_id;
144549e984eSSergio Lopez         ms->possible_cpus->cpus[i].props.has_thread_id = true;
145dcf08bc6SBabu Moger         ms->possible_cpus->cpus[i].props.thread_id = topo_ids.smt_id;
146549e984eSSergio Lopez     }
147549e984eSSergio Lopez     return ms->possible_cpus;
148549e984eSSergio Lopez }
149549e984eSSergio Lopez 
x86_nmi(NMIState * n,int cpu_index,Error ** errp)150f0bb276bSPaolo Bonzini static void x86_nmi(NMIState *n, int cpu_index, Error **errp)
151f0bb276bSPaolo Bonzini {
152f0bb276bSPaolo Bonzini     /* cpu index isn't used */
153f0bb276bSPaolo Bonzini     CPUState *cs;
154f0bb276bSPaolo Bonzini 
155f0bb276bSPaolo Bonzini     CPU_FOREACH(cs) {
156f0bb276bSPaolo Bonzini         X86CPU *cpu = X86_CPU(cs);
157f0bb276bSPaolo Bonzini 
158c2e6d7d8SBernhard Beschow         if (cpu_is_apic_enabled(cpu->apic_state)) {
159f0bb276bSPaolo Bonzini             apic_deliver_nmi(cpu->apic_state);
160f22f3a92SBernhard Beschow         } else {
161f22f3a92SBernhard Beschow             cpu_interrupt(cs, CPU_INTERRUPT_NMI);
162f0bb276bSPaolo Bonzini         }
163f0bb276bSPaolo Bonzini     }
164f0bb276bSPaolo Bonzini }
165f0bb276bSPaolo Bonzini 
x86_machine_is_smm_enabled(const X86MachineState * x86ms)1669927a632SGerd Hoffmann bool x86_machine_is_smm_enabled(const X86MachineState *x86ms)
167ed9e923cSPaolo Bonzini {
168ed9e923cSPaolo Bonzini     bool smm_available = false;
169ed9e923cSPaolo Bonzini 
170ed9e923cSPaolo Bonzini     if (x86ms->smm == ON_OFF_AUTO_OFF) {
171ed9e923cSPaolo Bonzini         return false;
172ed9e923cSPaolo Bonzini     }
173ed9e923cSPaolo Bonzini 
174ed9e923cSPaolo Bonzini     if (tcg_enabled() || qtest_enabled()) {
175ed9e923cSPaolo Bonzini         smm_available = true;
176ed9e923cSPaolo Bonzini     } else if (kvm_enabled()) {
177ed9e923cSPaolo Bonzini         smm_available = kvm_has_smm();
178ed9e923cSPaolo Bonzini     }
179ed9e923cSPaolo Bonzini 
180ed9e923cSPaolo Bonzini     if (smm_available) {
181ed9e923cSPaolo Bonzini         return true;
182ed9e923cSPaolo Bonzini     }
183ed9e923cSPaolo Bonzini 
184ed9e923cSPaolo Bonzini     if (x86ms->smm == ON_OFF_AUTO_ON) {
185ed9e923cSPaolo Bonzini         error_report("System Management Mode not supported by this hypervisor.");
186ed9e923cSPaolo Bonzini         exit(1);
187ed9e923cSPaolo Bonzini     }
188ed9e923cSPaolo Bonzini     return false;
189ed9e923cSPaolo Bonzini }
190ed9e923cSPaolo Bonzini 
x86_machine_get_smm(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)191ed9e923cSPaolo Bonzini static void x86_machine_get_smm(Object *obj, Visitor *v, const char *name,
192ed9e923cSPaolo Bonzini                                void *opaque, Error **errp)
193ed9e923cSPaolo Bonzini {
194ed9e923cSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(obj);
195ed9e923cSPaolo Bonzini     OnOffAuto smm = x86ms->smm;
196ed9e923cSPaolo Bonzini 
197ed9e923cSPaolo Bonzini     visit_type_OnOffAuto(v, name, &smm, errp);
198ed9e923cSPaolo Bonzini }
199ed9e923cSPaolo Bonzini 
x86_machine_set_smm(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)200ed9e923cSPaolo Bonzini static void x86_machine_set_smm(Object *obj, Visitor *v, const char *name,
201ed9e923cSPaolo Bonzini                                void *opaque, Error **errp)
202ed9e923cSPaolo Bonzini {
203ed9e923cSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(obj);
204ed9e923cSPaolo Bonzini 
205ed9e923cSPaolo Bonzini     visit_type_OnOffAuto(v, name, &x86ms->smm, errp);
206ed9e923cSPaolo Bonzini }
207ed9e923cSPaolo Bonzini 
x86_machine_is_acpi_enabled(const X86MachineState * x86ms)2089927a632SGerd Hoffmann bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms)
20917e89077SGerd Hoffmann {
21017e89077SGerd Hoffmann     if (x86ms->acpi == ON_OFF_AUTO_OFF) {
21117e89077SGerd Hoffmann         return false;
21217e89077SGerd Hoffmann     }
21317e89077SGerd Hoffmann     return true;
21417e89077SGerd Hoffmann }
21517e89077SGerd Hoffmann 
x86_machine_get_acpi(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)21617e89077SGerd Hoffmann static void x86_machine_get_acpi(Object *obj, Visitor *v, const char *name,
21717e89077SGerd Hoffmann                                  void *opaque, Error **errp)
21817e89077SGerd Hoffmann {
21917e89077SGerd Hoffmann     X86MachineState *x86ms = X86_MACHINE(obj);
22017e89077SGerd Hoffmann     OnOffAuto acpi = x86ms->acpi;
22117e89077SGerd Hoffmann 
22217e89077SGerd Hoffmann     visit_type_OnOffAuto(v, name, &acpi, errp);
22317e89077SGerd Hoffmann }
22417e89077SGerd Hoffmann 
x86_machine_set_acpi(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)22517e89077SGerd Hoffmann static void x86_machine_set_acpi(Object *obj, Visitor *v, const char *name,
22617e89077SGerd Hoffmann                                  void *opaque, Error **errp)
22717e89077SGerd Hoffmann {
22817e89077SGerd Hoffmann     X86MachineState *x86ms = X86_MACHINE(obj);
22917e89077SGerd Hoffmann 
23017e89077SGerd Hoffmann     visit_type_OnOffAuto(v, name, &x86ms->acpi, errp);
23117e89077SGerd Hoffmann }
23217e89077SGerd Hoffmann 
x86_machine_get_pit(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2339dee7e51SXiaoyao Li static void x86_machine_get_pit(Object *obj, Visitor *v, const char *name,
2349dee7e51SXiaoyao Li                                     void *opaque, Error **errp)
2359dee7e51SXiaoyao Li {
2369dee7e51SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);
2379dee7e51SXiaoyao Li     OnOffAuto pit = x86ms->pit;
2389dee7e51SXiaoyao Li 
2399dee7e51SXiaoyao Li     visit_type_OnOffAuto(v, name, &pit, errp);
2409dee7e51SXiaoyao Li }
2419dee7e51SXiaoyao Li 
x86_machine_set_pit(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2429dee7e51SXiaoyao Li static void x86_machine_set_pit(Object *obj, Visitor *v, const char *name,
2439dee7e51SXiaoyao Li                                     void *opaque, Error **errp)
2449dee7e51SXiaoyao Li {
245*eed52398SZhao Liu     X86MachineState *x86ms = X86_MACHINE(obj);
2469dee7e51SXiaoyao Li 
2479dee7e51SXiaoyao Li     visit_type_OnOffAuto(v, name, &x86ms->pit, errp);
2489dee7e51SXiaoyao Li }
2499dee7e51SXiaoyao Li 
x86_machine_get_pic(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)250c300bbe8SXiaoyao Li static void x86_machine_get_pic(Object *obj, Visitor *v, const char *name,
251c300bbe8SXiaoyao Li                                 void *opaque, Error **errp)
252c300bbe8SXiaoyao Li {
253c300bbe8SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);
254c300bbe8SXiaoyao Li     OnOffAuto pic = x86ms->pic;
255c300bbe8SXiaoyao Li 
256c300bbe8SXiaoyao Li     visit_type_OnOffAuto(v, name, &pic, errp);
257c300bbe8SXiaoyao Li }
258c300bbe8SXiaoyao Li 
x86_machine_set_pic(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)259c300bbe8SXiaoyao Li static void x86_machine_set_pic(Object *obj, Visitor *v, const char *name,
260c300bbe8SXiaoyao Li                                 void *opaque, Error **errp)
261c300bbe8SXiaoyao Li {
262c300bbe8SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);
263c300bbe8SXiaoyao Li 
264c300bbe8SXiaoyao Li     visit_type_OnOffAuto(v, name, &x86ms->pic, errp);
265c300bbe8SXiaoyao Li }
266c300bbe8SXiaoyao Li 
x86_machine_get_oem_id(Object * obj,Error ** errp)267d07b2286SMarian Postevca static char *x86_machine_get_oem_id(Object *obj, Error **errp)
268d07b2286SMarian Postevca {
269d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
270d07b2286SMarian Postevca 
271d07b2286SMarian Postevca     return g_strdup(x86ms->oem_id);
272d07b2286SMarian Postevca }
273d07b2286SMarian Postevca 
x86_machine_set_oem_id(Object * obj,const char * value,Error ** errp)274d07b2286SMarian Postevca static void x86_machine_set_oem_id(Object *obj, const char *value, Error **errp)
275d07b2286SMarian Postevca {
276d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
277d07b2286SMarian Postevca     size_t len = strlen(value);
278d07b2286SMarian Postevca 
279d07b2286SMarian Postevca     if (len > 6) {
280d07b2286SMarian Postevca         error_setg(errp,
281d07b2286SMarian Postevca                    "User specified "X86_MACHINE_OEM_ID" value is bigger than "
282d07b2286SMarian Postevca                    "6 bytes in size");
283d07b2286SMarian Postevca         return;
284d07b2286SMarian Postevca     }
285d07b2286SMarian Postevca 
286d07b2286SMarian Postevca     strncpy(x86ms->oem_id, value, 6);
287d07b2286SMarian Postevca }
288d07b2286SMarian Postevca 
x86_machine_get_oem_table_id(Object * obj,Error ** errp)289d07b2286SMarian Postevca static char *x86_machine_get_oem_table_id(Object *obj, Error **errp)
290d07b2286SMarian Postevca {
291d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
292d07b2286SMarian Postevca 
293d07b2286SMarian Postevca     return g_strdup(x86ms->oem_table_id);
294d07b2286SMarian Postevca }
295d07b2286SMarian Postevca 
x86_machine_set_oem_table_id(Object * obj,const char * value,Error ** errp)296d07b2286SMarian Postevca static void x86_machine_set_oem_table_id(Object *obj, const char *value,
297d07b2286SMarian Postevca                                          Error **errp)
298d07b2286SMarian Postevca {
299d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
300d07b2286SMarian Postevca     size_t len = strlen(value);
301d07b2286SMarian Postevca 
302d07b2286SMarian Postevca     if (len > 8) {
303d07b2286SMarian Postevca         error_setg(errp,
304d07b2286SMarian Postevca                    "User specified "X86_MACHINE_OEM_TABLE_ID
305d07b2286SMarian Postevca                    " value is bigger than "
306d07b2286SMarian Postevca                    "8 bytes in size");
307d07b2286SMarian Postevca         return;
308d07b2286SMarian Postevca     }
309d07b2286SMarian Postevca     strncpy(x86ms->oem_table_id, value, 8);
310d07b2286SMarian Postevca }
311d07b2286SMarian Postevca 
x86_machine_get_bus_lock_ratelimit(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)312035d1ef2SChenyi Qiang static void x86_machine_get_bus_lock_ratelimit(Object *obj, Visitor *v,
313035d1ef2SChenyi Qiang                                 const char *name, void *opaque, Error **errp)
314035d1ef2SChenyi Qiang {
315035d1ef2SChenyi Qiang     X86MachineState *x86ms = X86_MACHINE(obj);
316035d1ef2SChenyi Qiang     uint64_t bus_lock_ratelimit = x86ms->bus_lock_ratelimit;
317035d1ef2SChenyi Qiang 
318035d1ef2SChenyi Qiang     visit_type_uint64(v, name, &bus_lock_ratelimit, errp);
319035d1ef2SChenyi Qiang }
320035d1ef2SChenyi Qiang 
x86_machine_set_bus_lock_ratelimit(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)321035d1ef2SChenyi Qiang static void x86_machine_set_bus_lock_ratelimit(Object *obj, Visitor *v,
322035d1ef2SChenyi Qiang                                const char *name, void *opaque, Error **errp)
323035d1ef2SChenyi Qiang {
324035d1ef2SChenyi Qiang     X86MachineState *x86ms = X86_MACHINE(obj);
325035d1ef2SChenyi Qiang 
326035d1ef2SChenyi Qiang     visit_type_uint64(v, name, &x86ms->bus_lock_ratelimit, errp);
327035d1ef2SChenyi Qiang }
328035d1ef2SChenyi Qiang 
machine_get_sgx_epc(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)329dfce81f1SSean Christopherson static void machine_get_sgx_epc(Object *obj, Visitor *v, const char *name,
330dfce81f1SSean Christopherson                                 void *opaque, Error **errp)
331dfce81f1SSean Christopherson {
332dfce81f1SSean Christopherson     X86MachineState *x86ms = X86_MACHINE(obj);
333dfce81f1SSean Christopherson     SgxEPCList *list = x86ms->sgx_epc_list;
334dfce81f1SSean Christopherson 
335dfce81f1SSean Christopherson     visit_type_SgxEPCList(v, name, &list, errp);
336dfce81f1SSean Christopherson }
337dfce81f1SSean Christopherson 
machine_set_sgx_epc(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)338dfce81f1SSean Christopherson static void machine_set_sgx_epc(Object *obj, Visitor *v, const char *name,
339dfce81f1SSean Christopherson                                 void *opaque, Error **errp)
340dfce81f1SSean Christopherson {
341dfce81f1SSean Christopherson     X86MachineState *x86ms = X86_MACHINE(obj);
342dfce81f1SSean Christopherson     SgxEPCList *list;
343dfce81f1SSean Christopherson 
344dfce81f1SSean Christopherson     list = x86ms->sgx_epc_list;
345dfce81f1SSean Christopherson     visit_type_SgxEPCList(v, name, &x86ms->sgx_epc_list, errp);
346dfce81f1SSean Christopherson 
347dfce81f1SSean Christopherson     qapi_free_SgxEPCList(list);
348dfce81f1SSean Christopherson }
349dfce81f1SSean Christopherson 
x86_kvm_type(MachineState * ms,const char * vm_type)350ee88612dSPaolo Bonzini static int x86_kvm_type(MachineState *ms, const char *vm_type)
351ee88612dSPaolo Bonzini {
352ee88612dSPaolo Bonzini     /*
353ee88612dSPaolo Bonzini      * No x86 machine has a kvm-type property.  If one is added that has
354ee88612dSPaolo Bonzini      * it, it should call kvm_get_vm_type() directly or not use it at all.
355ee88612dSPaolo Bonzini      */
356ee88612dSPaolo Bonzini     assert(vm_type == NULL);
357ee88612dSPaolo Bonzini     return kvm_enabled() ? kvm_get_vm_type(ms) : 0;
358ee88612dSPaolo Bonzini }
359ee88612dSPaolo Bonzini 
x86_machine_initfn(Object * obj)360f0bb276bSPaolo Bonzini static void x86_machine_initfn(Object *obj)
361f0bb276bSPaolo Bonzini {
362f0bb276bSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(obj);
363f0bb276bSPaolo Bonzini 
364ed9e923cSPaolo Bonzini     x86ms->smm = ON_OFF_AUTO_AUTO;
36517e89077SGerd Hoffmann     x86ms->acpi = ON_OFF_AUTO_AUTO;
3669dee7e51SXiaoyao Li     x86ms->pit = ON_OFF_AUTO_AUTO;
367c300bbe8SXiaoyao Li     x86ms->pic = ON_OFF_AUTO_AUTO;
3681b2802c4SGerd Hoffmann     x86ms->pci_irq_mask = ACPI_BUILD_PCI_IRQS;
369d07b2286SMarian Postevca     x86ms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
370d07b2286SMarian Postevca     x86ms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
371035d1ef2SChenyi Qiang     x86ms->bus_lock_ratelimit = 0;
3724ab4c330SJoao Martins     x86ms->above_4g_mem_start = 4 * GiB;
373f0bb276bSPaolo Bonzini }
374f0bb276bSPaolo Bonzini 
x86_machine_class_init(ObjectClass * oc,void * data)375f0bb276bSPaolo Bonzini static void x86_machine_class_init(ObjectClass *oc, void *data)
376f0bb276bSPaolo Bonzini {
377f0bb276bSPaolo Bonzini     MachineClass *mc = MACHINE_CLASS(oc);
378f0bb276bSPaolo Bonzini     X86MachineClass *x86mc = X86_MACHINE_CLASS(oc);
379f0bb276bSPaolo Bonzini     NMIClass *nc = NMI_CLASS(oc);
380f0bb276bSPaolo Bonzini 
381f0bb276bSPaolo Bonzini     mc->cpu_index_to_instance_props = x86_cpu_index_to_props;
382f0bb276bSPaolo Bonzini     mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
383f0bb276bSPaolo Bonzini     mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
384ee88612dSPaolo Bonzini     mc->kvm_type = x86_kvm_type;
3852f34ebf2SLiam Merwick     x86mc->save_tsc_khz = true;
386f014c974SPaolo Bonzini     x86mc->fwcfg_dma_enabled = true;
387f0bb276bSPaolo Bonzini     nc->nmi_monitor_handler = x86_nmi;
388f0bb276bSPaolo Bonzini 
389ed9e923cSPaolo Bonzini     object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto",
390ed9e923cSPaolo Bonzini         x86_machine_get_smm, x86_machine_set_smm,
391d2623129SMarkus Armbruster         NULL, NULL);
392ed9e923cSPaolo Bonzini     object_class_property_set_description(oc, X86_MACHINE_SMM,
3937eecec7dSMarkus Armbruster         "Enable SMM");
39417e89077SGerd Hoffmann 
39517e89077SGerd Hoffmann     object_class_property_add(oc, X86_MACHINE_ACPI, "OnOffAuto",
39617e89077SGerd Hoffmann         x86_machine_get_acpi, x86_machine_set_acpi,
397d2623129SMarkus Armbruster         NULL, NULL);
39817e89077SGerd Hoffmann     object_class_property_set_description(oc, X86_MACHINE_ACPI,
3997eecec7dSMarkus Armbruster         "Enable ACPI");
400d07b2286SMarian Postevca 
4019dee7e51SXiaoyao Li     object_class_property_add(oc, X86_MACHINE_PIT, "OnOffAuto",
4029dee7e51SXiaoyao Li                               x86_machine_get_pit,
4039dee7e51SXiaoyao Li                               x86_machine_set_pit,
4049dee7e51SXiaoyao Li                               NULL, NULL);
4059dee7e51SXiaoyao Li     object_class_property_set_description(oc, X86_MACHINE_PIT,
4069dee7e51SXiaoyao Li         "Enable i8254 PIT");
4079dee7e51SXiaoyao Li 
408c300bbe8SXiaoyao Li     object_class_property_add(oc, X86_MACHINE_PIC, "OnOffAuto",
409c300bbe8SXiaoyao Li                               x86_machine_get_pic,
410c300bbe8SXiaoyao Li                               x86_machine_set_pic,
411c300bbe8SXiaoyao Li                               NULL, NULL);
412c300bbe8SXiaoyao Li     object_class_property_set_description(oc, X86_MACHINE_PIC,
413c300bbe8SXiaoyao Li         "Enable i8259 PIC");
414c300bbe8SXiaoyao Li 
415d07b2286SMarian Postevca     object_class_property_add_str(oc, X86_MACHINE_OEM_ID,
416d07b2286SMarian Postevca                                   x86_machine_get_oem_id,
417d07b2286SMarian Postevca                                   x86_machine_set_oem_id);
418d07b2286SMarian Postevca     object_class_property_set_description(oc, X86_MACHINE_OEM_ID,
419d07b2286SMarian Postevca                                           "Override the default value of field OEMID "
420d07b2286SMarian Postevca                                           "in ACPI table header."
421d07b2286SMarian Postevca                                           "The string may be up to 6 bytes in size");
422d07b2286SMarian Postevca 
423d07b2286SMarian Postevca 
424d07b2286SMarian Postevca     object_class_property_add_str(oc, X86_MACHINE_OEM_TABLE_ID,
425d07b2286SMarian Postevca                                   x86_machine_get_oem_table_id,
426d07b2286SMarian Postevca                                   x86_machine_set_oem_table_id);
427d07b2286SMarian Postevca     object_class_property_set_description(oc, X86_MACHINE_OEM_TABLE_ID,
428d07b2286SMarian Postevca                                           "Override the default value of field OEM Table ID "
429d07b2286SMarian Postevca                                           "in ACPI table header."
430d07b2286SMarian Postevca                                           "The string may be up to 8 bytes in size");
431035d1ef2SChenyi Qiang 
432035d1ef2SChenyi Qiang     object_class_property_add(oc, X86_MACHINE_BUS_LOCK_RATELIMIT, "uint64_t",
433035d1ef2SChenyi Qiang                                 x86_machine_get_bus_lock_ratelimit,
434035d1ef2SChenyi Qiang                                 x86_machine_set_bus_lock_ratelimit, NULL, NULL);
435035d1ef2SChenyi Qiang     object_class_property_set_description(oc, X86_MACHINE_BUS_LOCK_RATELIMIT,
436035d1ef2SChenyi Qiang             "Set the ratelimit for the bus locks acquired in VMs");
437dfce81f1SSean Christopherson 
438dfce81f1SSean Christopherson     object_class_property_add(oc, "sgx-epc", "SgxEPC",
439dfce81f1SSean Christopherson         machine_get_sgx_epc, machine_set_sgx_epc,
440dfce81f1SSean Christopherson         NULL, NULL);
441dfce81f1SSean Christopherson     object_class_property_set_description(oc, "sgx-epc",
442dfce81f1SSean Christopherson         "SGX EPC device");
443f0bb276bSPaolo Bonzini }
444f0bb276bSPaolo Bonzini 
445f0bb276bSPaolo Bonzini static const TypeInfo x86_machine_info = {
446f0bb276bSPaolo Bonzini     .name = TYPE_X86_MACHINE,
447f0bb276bSPaolo Bonzini     .parent = TYPE_MACHINE,
448f0bb276bSPaolo Bonzini     .abstract = true,
449f0bb276bSPaolo Bonzini     .instance_size = sizeof(X86MachineState),
450f0bb276bSPaolo Bonzini     .instance_init = x86_machine_initfn,
451f0bb276bSPaolo Bonzini     .class_size = sizeof(X86MachineClass),
452f0bb276bSPaolo Bonzini     .class_init = x86_machine_class_init,
453f0bb276bSPaolo Bonzini     .interfaces = (InterfaceInfo[]) {
454f0bb276bSPaolo Bonzini          { TYPE_NMI },
455f0bb276bSPaolo Bonzini          { }
456f0bb276bSPaolo Bonzini     },
457f0bb276bSPaolo Bonzini };
458f0bb276bSPaolo Bonzini 
x86_machine_register_types(void)459f0bb276bSPaolo Bonzini static void x86_machine_register_types(void)
460f0bb276bSPaolo Bonzini {
461f0bb276bSPaolo Bonzini     type_register_static(&x86_machine_info);
462f0bb276bSPaolo Bonzini }
463f0bb276bSPaolo Bonzini 
464f0bb276bSPaolo Bonzini type_init(x86_machine_register_types)
465