xref: /qemu/hw/i386/x86.c (revision b061f059)
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 
34*b061f059SPaolo 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)42*b061f059SPaolo 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;
4853a5e7bdSBabu Moger     topo_info->cores_per_die = ms->smp.cores;
4953a5e7bdSBabu Moger     topo_info->threads_per_core = ms->smp.threads;
5053a5e7bdSBabu Moger }
5153a5e7bdSBabu Moger 
52549e984eSSergio Lopez /*
53549e984eSSergio Lopez  * Calculates initial APIC ID for a specific CPU index
54549e984eSSergio Lopez  *
55549e984eSSergio Lopez  * Currently we need to be able to calculate the APIC ID from the CPU index
56549e984eSSergio Lopez  * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces have
57549e984eSSergio Lopez  * no concept of "CPU index", and the NUMA tables on fw_cfg need the APIC ID of
58549e984eSSergio Lopez  * all CPUs up to max_cpus.
59549e984eSSergio Lopez  */
x86_cpu_apic_id_from_index(X86MachineState * x86ms,unsigned int cpu_index)60703a548aSSergio Lopez uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
61549e984eSSergio Lopez                                     unsigned int cpu_index)
62549e984eSSergio Lopez {
6353a5e7bdSBabu Moger     X86CPUTopoInfo topo_info;
64549e984eSSergio Lopez 
6553a5e7bdSBabu Moger     init_topo_info(&topo_info, x86ms);
6653a5e7bdSBabu Moger 
67e6895f04SIgor Mammedov     return x86_apicid_from_cpu_idx(&topo_info, cpu_index);
68549e984eSSergio Lopez }
69549e984eSSergio Lopez 
70b348fdcdSPaolo Bonzini static CpuInstanceProperties
x86_cpu_index_to_props(MachineState * ms,unsigned cpu_index)71549e984eSSergio Lopez x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
72549e984eSSergio Lopez {
73549e984eSSergio Lopez     MachineClass *mc = MACHINE_GET_CLASS(ms);
74549e984eSSergio Lopez     const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
75549e984eSSergio Lopez 
76549e984eSSergio Lopez     assert(cpu_index < possible_cpus->len);
77549e984eSSergio Lopez     return possible_cpus->cpus[cpu_index].props;
78549e984eSSergio Lopez }
79549e984eSSergio Lopez 
x86_get_default_cpu_node_id(const MachineState * ms,int idx)80b348fdcdSPaolo Bonzini static int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
81549e984eSSergio Lopez {
82dcf08bc6SBabu Moger    X86CPUTopoIDs topo_ids;
83f0bb276bSPaolo Bonzini    X86MachineState *x86ms = X86_MACHINE(ms);
8453a5e7bdSBabu Moger    X86CPUTopoInfo topo_info;
8553a5e7bdSBabu Moger 
8653a5e7bdSBabu Moger    init_topo_info(&topo_info, x86ms);
87549e984eSSergio Lopez 
88549e984eSSergio Lopez    assert(idx < ms->possible_cpus->len);
89dfe7ed0aSBabu Moger    x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id,
90dfe7ed0aSBabu Moger                             &topo_info, &topo_ids);
91dcf08bc6SBabu Moger    return topo_ids.pkg_id % ms->numa_state->num_nodes;
92549e984eSSergio Lopez }
93549e984eSSergio Lopez 
x86_possible_cpu_arch_ids(MachineState * ms)94b348fdcdSPaolo Bonzini static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
95549e984eSSergio Lopez {
96f0bb276bSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(ms);
97549e984eSSergio Lopez     unsigned int max_cpus = ms->smp.max_cpus;
9853a5e7bdSBabu Moger     X86CPUTopoInfo topo_info;
9953a5e7bdSBabu Moger     int i;
100549e984eSSergio Lopez 
101549e984eSSergio Lopez     if (ms->possible_cpus) {
102549e984eSSergio Lopez         /*
103549e984eSSergio Lopez          * make sure that max_cpus hasn't changed since the first use, i.e.
104549e984eSSergio Lopez          * -smp hasn't been parsed after it
105549e984eSSergio Lopez          */
106549e984eSSergio Lopez         assert(ms->possible_cpus->len == max_cpus);
107549e984eSSergio Lopez         return ms->possible_cpus;
108549e984eSSergio Lopez     }
109549e984eSSergio Lopez 
110549e984eSSergio Lopez     ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
111549e984eSSergio Lopez                                   sizeof(CPUArchId) * max_cpus);
112549e984eSSergio Lopez     ms->possible_cpus->len = max_cpus;
11353a5e7bdSBabu Moger 
11453a5e7bdSBabu Moger     init_topo_info(&topo_info, x86ms);
11553a5e7bdSBabu Moger 
116549e984eSSergio Lopez     for (i = 0; i < ms->possible_cpus->len; i++) {
117dcf08bc6SBabu Moger         X86CPUTopoIDs topo_ids;
118549e984eSSergio Lopez 
119549e984eSSergio Lopez         ms->possible_cpus->cpus[i].type = ms->cpu_type;
120549e984eSSergio Lopez         ms->possible_cpus->cpus[i].vcpus_count = 1;
121dfe7ed0aSBabu Moger         ms->possible_cpus->cpus[i].arch_id =
122dfe7ed0aSBabu Moger             x86_cpu_apic_id_from_index(x86ms, i);
123dfe7ed0aSBabu Moger         x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id,
124dfe7ed0aSBabu Moger                                  &topo_info, &topo_ids);
125549e984eSSergio Lopez         ms->possible_cpus->cpus[i].props.has_socket_id = true;
126dcf08bc6SBabu Moger         ms->possible_cpus->cpus[i].props.socket_id = topo_ids.pkg_id;
12767872eb8SPaolo Bonzini         if (ms->smp.dies > 1) {
128549e984eSSergio Lopez             ms->possible_cpus->cpus[i].props.has_die_id = true;
129dcf08bc6SBabu Moger             ms->possible_cpus->cpus[i].props.die_id = topo_ids.die_id;
130549e984eSSergio Lopez         }
131549e984eSSergio Lopez         ms->possible_cpus->cpus[i].props.has_core_id = true;
132dcf08bc6SBabu Moger         ms->possible_cpus->cpus[i].props.core_id = topo_ids.core_id;
133549e984eSSergio Lopez         ms->possible_cpus->cpus[i].props.has_thread_id = true;
134dcf08bc6SBabu Moger         ms->possible_cpus->cpus[i].props.thread_id = topo_ids.smt_id;
135549e984eSSergio Lopez     }
136549e984eSSergio Lopez     return ms->possible_cpus;
137549e984eSSergio Lopez }
138549e984eSSergio Lopez 
x86_nmi(NMIState * n,int cpu_index,Error ** errp)139f0bb276bSPaolo Bonzini static void x86_nmi(NMIState *n, int cpu_index, Error **errp)
140f0bb276bSPaolo Bonzini {
141f0bb276bSPaolo Bonzini     /* cpu index isn't used */
142f0bb276bSPaolo Bonzini     CPUState *cs;
143f0bb276bSPaolo Bonzini 
144f0bb276bSPaolo Bonzini     CPU_FOREACH(cs) {
145f0bb276bSPaolo Bonzini         X86CPU *cpu = X86_CPU(cs);
146f0bb276bSPaolo Bonzini 
147c2e6d7d8SBernhard Beschow         if (cpu_is_apic_enabled(cpu->apic_state)) {
148f0bb276bSPaolo Bonzini             apic_deliver_nmi(cpu->apic_state);
149f22f3a92SBernhard Beschow         } else {
150f22f3a92SBernhard Beschow             cpu_interrupt(cs, CPU_INTERRUPT_NMI);
151f0bb276bSPaolo Bonzini         }
152f0bb276bSPaolo Bonzini     }
153f0bb276bSPaolo Bonzini }
154f0bb276bSPaolo Bonzini 
x86_machine_is_smm_enabled(const X86MachineState * x86ms)1559927a632SGerd Hoffmann bool x86_machine_is_smm_enabled(const X86MachineState *x86ms)
156ed9e923cSPaolo Bonzini {
157ed9e923cSPaolo Bonzini     bool smm_available = false;
158ed9e923cSPaolo Bonzini 
159ed9e923cSPaolo Bonzini     if (x86ms->smm == ON_OFF_AUTO_OFF) {
160ed9e923cSPaolo Bonzini         return false;
161ed9e923cSPaolo Bonzini     }
162ed9e923cSPaolo Bonzini 
163ed9e923cSPaolo Bonzini     if (tcg_enabled() || qtest_enabled()) {
164ed9e923cSPaolo Bonzini         smm_available = true;
165ed9e923cSPaolo Bonzini     } else if (kvm_enabled()) {
166ed9e923cSPaolo Bonzini         smm_available = kvm_has_smm();
167ed9e923cSPaolo Bonzini     }
168ed9e923cSPaolo Bonzini 
169ed9e923cSPaolo Bonzini     if (smm_available) {
170ed9e923cSPaolo Bonzini         return true;
171ed9e923cSPaolo Bonzini     }
172ed9e923cSPaolo Bonzini 
173ed9e923cSPaolo Bonzini     if (x86ms->smm == ON_OFF_AUTO_ON) {
174ed9e923cSPaolo Bonzini         error_report("System Management Mode not supported by this hypervisor.");
175ed9e923cSPaolo Bonzini         exit(1);
176ed9e923cSPaolo Bonzini     }
177ed9e923cSPaolo Bonzini     return false;
178ed9e923cSPaolo Bonzini }
179ed9e923cSPaolo Bonzini 
x86_machine_get_smm(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)180ed9e923cSPaolo Bonzini static void x86_machine_get_smm(Object *obj, Visitor *v, const char *name,
181ed9e923cSPaolo Bonzini                                void *opaque, Error **errp)
182ed9e923cSPaolo Bonzini {
183ed9e923cSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(obj);
184ed9e923cSPaolo Bonzini     OnOffAuto smm = x86ms->smm;
185ed9e923cSPaolo Bonzini 
186ed9e923cSPaolo Bonzini     visit_type_OnOffAuto(v, name, &smm, errp);
187ed9e923cSPaolo Bonzini }
188ed9e923cSPaolo Bonzini 
x86_machine_set_smm(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)189ed9e923cSPaolo Bonzini static void x86_machine_set_smm(Object *obj, Visitor *v, const char *name,
190ed9e923cSPaolo Bonzini                                void *opaque, Error **errp)
191ed9e923cSPaolo Bonzini {
192ed9e923cSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(obj);
193ed9e923cSPaolo Bonzini 
194ed9e923cSPaolo Bonzini     visit_type_OnOffAuto(v, name, &x86ms->smm, errp);
195ed9e923cSPaolo Bonzini }
196ed9e923cSPaolo Bonzini 
x86_machine_is_acpi_enabled(const X86MachineState * x86ms)1979927a632SGerd Hoffmann bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms)
19817e89077SGerd Hoffmann {
19917e89077SGerd Hoffmann     if (x86ms->acpi == ON_OFF_AUTO_OFF) {
20017e89077SGerd Hoffmann         return false;
20117e89077SGerd Hoffmann     }
20217e89077SGerd Hoffmann     return true;
20317e89077SGerd Hoffmann }
20417e89077SGerd Hoffmann 
x86_machine_get_acpi(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)20517e89077SGerd Hoffmann static void x86_machine_get_acpi(Object *obj, Visitor *v, const char *name,
20617e89077SGerd Hoffmann                                  void *opaque, Error **errp)
20717e89077SGerd Hoffmann {
20817e89077SGerd Hoffmann     X86MachineState *x86ms = X86_MACHINE(obj);
20917e89077SGerd Hoffmann     OnOffAuto acpi = x86ms->acpi;
21017e89077SGerd Hoffmann 
21117e89077SGerd Hoffmann     visit_type_OnOffAuto(v, name, &acpi, errp);
21217e89077SGerd Hoffmann }
21317e89077SGerd Hoffmann 
x86_machine_set_acpi(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)21417e89077SGerd Hoffmann static void x86_machine_set_acpi(Object *obj, Visitor *v, const char *name,
21517e89077SGerd Hoffmann                                  void *opaque, Error **errp)
21617e89077SGerd Hoffmann {
21717e89077SGerd Hoffmann     X86MachineState *x86ms = X86_MACHINE(obj);
21817e89077SGerd Hoffmann 
21917e89077SGerd Hoffmann     visit_type_OnOffAuto(v, name, &x86ms->acpi, errp);
22017e89077SGerd Hoffmann }
22117e89077SGerd Hoffmann 
x86_machine_get_pit(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2229dee7e51SXiaoyao Li static void x86_machine_get_pit(Object *obj, Visitor *v, const char *name,
2239dee7e51SXiaoyao Li                                     void *opaque, Error **errp)
2249dee7e51SXiaoyao Li {
2259dee7e51SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);
2269dee7e51SXiaoyao Li     OnOffAuto pit = x86ms->pit;
2279dee7e51SXiaoyao Li 
2289dee7e51SXiaoyao Li     visit_type_OnOffAuto(v, name, &pit, errp);
2299dee7e51SXiaoyao Li }
2309dee7e51SXiaoyao Li 
x86_machine_set_pit(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2319dee7e51SXiaoyao Li static void x86_machine_set_pit(Object *obj, Visitor *v, const char *name,
2329dee7e51SXiaoyao Li                                     void *opaque, Error **errp)
2339dee7e51SXiaoyao Li {
2349dee7e51SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);;
2359dee7e51SXiaoyao Li 
2369dee7e51SXiaoyao Li     visit_type_OnOffAuto(v, name, &x86ms->pit, errp);
2379dee7e51SXiaoyao Li }
2389dee7e51SXiaoyao Li 
x86_machine_get_pic(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)239c300bbe8SXiaoyao Li static void x86_machine_get_pic(Object *obj, Visitor *v, const char *name,
240c300bbe8SXiaoyao Li                                 void *opaque, Error **errp)
241c300bbe8SXiaoyao Li {
242c300bbe8SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);
243c300bbe8SXiaoyao Li     OnOffAuto pic = x86ms->pic;
244c300bbe8SXiaoyao Li 
245c300bbe8SXiaoyao Li     visit_type_OnOffAuto(v, name, &pic, errp);
246c300bbe8SXiaoyao Li }
247c300bbe8SXiaoyao Li 
x86_machine_set_pic(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)248c300bbe8SXiaoyao Li static void x86_machine_set_pic(Object *obj, Visitor *v, const char *name,
249c300bbe8SXiaoyao Li                                 void *opaque, Error **errp)
250c300bbe8SXiaoyao Li {
251c300bbe8SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);
252c300bbe8SXiaoyao Li 
253c300bbe8SXiaoyao Li     visit_type_OnOffAuto(v, name, &x86ms->pic, errp);
254c300bbe8SXiaoyao Li }
255c300bbe8SXiaoyao Li 
x86_machine_get_oem_id(Object * obj,Error ** errp)256d07b2286SMarian Postevca static char *x86_machine_get_oem_id(Object *obj, Error **errp)
257d07b2286SMarian Postevca {
258d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
259d07b2286SMarian Postevca 
260d07b2286SMarian Postevca     return g_strdup(x86ms->oem_id);
261d07b2286SMarian Postevca }
262d07b2286SMarian Postevca 
x86_machine_set_oem_id(Object * obj,const char * value,Error ** errp)263d07b2286SMarian Postevca static void x86_machine_set_oem_id(Object *obj, const char *value, Error **errp)
264d07b2286SMarian Postevca {
265d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
266d07b2286SMarian Postevca     size_t len = strlen(value);
267d07b2286SMarian Postevca 
268d07b2286SMarian Postevca     if (len > 6) {
269d07b2286SMarian Postevca         error_setg(errp,
270d07b2286SMarian Postevca                    "User specified "X86_MACHINE_OEM_ID" value is bigger than "
271d07b2286SMarian Postevca                    "6 bytes in size");
272d07b2286SMarian Postevca         return;
273d07b2286SMarian Postevca     }
274d07b2286SMarian Postevca 
275d07b2286SMarian Postevca     strncpy(x86ms->oem_id, value, 6);
276d07b2286SMarian Postevca }
277d07b2286SMarian Postevca 
x86_machine_get_oem_table_id(Object * obj,Error ** errp)278d07b2286SMarian Postevca static char *x86_machine_get_oem_table_id(Object *obj, Error **errp)
279d07b2286SMarian Postevca {
280d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
281d07b2286SMarian Postevca 
282d07b2286SMarian Postevca     return g_strdup(x86ms->oem_table_id);
283d07b2286SMarian Postevca }
284d07b2286SMarian Postevca 
x86_machine_set_oem_table_id(Object * obj,const char * value,Error ** errp)285d07b2286SMarian Postevca static void x86_machine_set_oem_table_id(Object *obj, const char *value,
286d07b2286SMarian Postevca                                          Error **errp)
287d07b2286SMarian Postevca {
288d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
289d07b2286SMarian Postevca     size_t len = strlen(value);
290d07b2286SMarian Postevca 
291d07b2286SMarian Postevca     if (len > 8) {
292d07b2286SMarian Postevca         error_setg(errp,
293d07b2286SMarian Postevca                    "User specified "X86_MACHINE_OEM_TABLE_ID
294d07b2286SMarian Postevca                    " value is bigger than "
295d07b2286SMarian Postevca                    "8 bytes in size");
296d07b2286SMarian Postevca         return;
297d07b2286SMarian Postevca     }
298d07b2286SMarian Postevca     strncpy(x86ms->oem_table_id, value, 8);
299d07b2286SMarian Postevca }
300d07b2286SMarian Postevca 
x86_machine_get_bus_lock_ratelimit(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)301035d1ef2SChenyi Qiang static void x86_machine_get_bus_lock_ratelimit(Object *obj, Visitor *v,
302035d1ef2SChenyi Qiang                                 const char *name, void *opaque, Error **errp)
303035d1ef2SChenyi Qiang {
304035d1ef2SChenyi Qiang     X86MachineState *x86ms = X86_MACHINE(obj);
305035d1ef2SChenyi Qiang     uint64_t bus_lock_ratelimit = x86ms->bus_lock_ratelimit;
306035d1ef2SChenyi Qiang 
307035d1ef2SChenyi Qiang     visit_type_uint64(v, name, &bus_lock_ratelimit, errp);
308035d1ef2SChenyi Qiang }
309035d1ef2SChenyi Qiang 
x86_machine_set_bus_lock_ratelimit(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)310035d1ef2SChenyi Qiang static void x86_machine_set_bus_lock_ratelimit(Object *obj, Visitor *v,
311035d1ef2SChenyi Qiang                                const char *name, void *opaque, Error **errp)
312035d1ef2SChenyi Qiang {
313035d1ef2SChenyi Qiang     X86MachineState *x86ms = X86_MACHINE(obj);
314035d1ef2SChenyi Qiang 
315035d1ef2SChenyi Qiang     visit_type_uint64(v, name, &x86ms->bus_lock_ratelimit, errp);
316035d1ef2SChenyi Qiang }
317035d1ef2SChenyi Qiang 
machine_get_sgx_epc(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)318dfce81f1SSean Christopherson static void machine_get_sgx_epc(Object *obj, Visitor *v, const char *name,
319dfce81f1SSean Christopherson                                 void *opaque, Error **errp)
320dfce81f1SSean Christopherson {
321dfce81f1SSean Christopherson     X86MachineState *x86ms = X86_MACHINE(obj);
322dfce81f1SSean Christopherson     SgxEPCList *list = x86ms->sgx_epc_list;
323dfce81f1SSean Christopherson 
324dfce81f1SSean Christopherson     visit_type_SgxEPCList(v, name, &list, errp);
325dfce81f1SSean Christopherson }
326dfce81f1SSean Christopherson 
machine_set_sgx_epc(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)327dfce81f1SSean Christopherson static void machine_set_sgx_epc(Object *obj, Visitor *v, const char *name,
328dfce81f1SSean Christopherson                                 void *opaque, Error **errp)
329dfce81f1SSean Christopherson {
330dfce81f1SSean Christopherson     X86MachineState *x86ms = X86_MACHINE(obj);
331dfce81f1SSean Christopherson     SgxEPCList *list;
332dfce81f1SSean Christopherson 
333dfce81f1SSean Christopherson     list = x86ms->sgx_epc_list;
334dfce81f1SSean Christopherson     visit_type_SgxEPCList(v, name, &x86ms->sgx_epc_list, errp);
335dfce81f1SSean Christopherson 
336dfce81f1SSean Christopherson     qapi_free_SgxEPCList(list);
337dfce81f1SSean Christopherson }
338dfce81f1SSean Christopherson 
x86_kvm_type(MachineState * ms,const char * vm_type)339ee88612dSPaolo Bonzini static int x86_kvm_type(MachineState *ms, const char *vm_type)
340ee88612dSPaolo Bonzini {
341ee88612dSPaolo Bonzini     /*
342ee88612dSPaolo Bonzini      * No x86 machine has a kvm-type property.  If one is added that has
343ee88612dSPaolo Bonzini      * it, it should call kvm_get_vm_type() directly or not use it at all.
344ee88612dSPaolo Bonzini      */
345ee88612dSPaolo Bonzini     assert(vm_type == NULL);
346ee88612dSPaolo Bonzini     return kvm_enabled() ? kvm_get_vm_type(ms) : 0;
347ee88612dSPaolo Bonzini }
348ee88612dSPaolo Bonzini 
x86_machine_initfn(Object * obj)349f0bb276bSPaolo Bonzini static void x86_machine_initfn(Object *obj)
350f0bb276bSPaolo Bonzini {
351f0bb276bSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(obj);
352f0bb276bSPaolo Bonzini 
353ed9e923cSPaolo Bonzini     x86ms->smm = ON_OFF_AUTO_AUTO;
35417e89077SGerd Hoffmann     x86ms->acpi = ON_OFF_AUTO_AUTO;
3559dee7e51SXiaoyao Li     x86ms->pit = ON_OFF_AUTO_AUTO;
356c300bbe8SXiaoyao Li     x86ms->pic = ON_OFF_AUTO_AUTO;
3571b2802c4SGerd Hoffmann     x86ms->pci_irq_mask = ACPI_BUILD_PCI_IRQS;
358d07b2286SMarian Postevca     x86ms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
359d07b2286SMarian Postevca     x86ms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
360035d1ef2SChenyi Qiang     x86ms->bus_lock_ratelimit = 0;
3614ab4c330SJoao Martins     x86ms->above_4g_mem_start = 4 * GiB;
362f0bb276bSPaolo Bonzini }
363f0bb276bSPaolo Bonzini 
x86_machine_class_init(ObjectClass * oc,void * data)364f0bb276bSPaolo Bonzini static void x86_machine_class_init(ObjectClass *oc, void *data)
365f0bb276bSPaolo Bonzini {
366f0bb276bSPaolo Bonzini     MachineClass *mc = MACHINE_CLASS(oc);
367f0bb276bSPaolo Bonzini     X86MachineClass *x86mc = X86_MACHINE_CLASS(oc);
368f0bb276bSPaolo Bonzini     NMIClass *nc = NMI_CLASS(oc);
369f0bb276bSPaolo Bonzini 
370f0bb276bSPaolo Bonzini     mc->cpu_index_to_instance_props = x86_cpu_index_to_props;
371f0bb276bSPaolo Bonzini     mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
372f0bb276bSPaolo Bonzini     mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
373ee88612dSPaolo Bonzini     mc->kvm_type = x86_kvm_type;
3742f34ebf2SLiam Merwick     x86mc->save_tsc_khz = true;
375f014c974SPaolo Bonzini     x86mc->fwcfg_dma_enabled = true;
376f0bb276bSPaolo Bonzini     nc->nmi_monitor_handler = x86_nmi;
377f0bb276bSPaolo Bonzini 
378ed9e923cSPaolo Bonzini     object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto",
379ed9e923cSPaolo Bonzini         x86_machine_get_smm, x86_machine_set_smm,
380d2623129SMarkus Armbruster         NULL, NULL);
381ed9e923cSPaolo Bonzini     object_class_property_set_description(oc, X86_MACHINE_SMM,
3827eecec7dSMarkus Armbruster         "Enable SMM");
38317e89077SGerd Hoffmann 
38417e89077SGerd Hoffmann     object_class_property_add(oc, X86_MACHINE_ACPI, "OnOffAuto",
38517e89077SGerd Hoffmann         x86_machine_get_acpi, x86_machine_set_acpi,
386d2623129SMarkus Armbruster         NULL, NULL);
38717e89077SGerd Hoffmann     object_class_property_set_description(oc, X86_MACHINE_ACPI,
3887eecec7dSMarkus Armbruster         "Enable ACPI");
389d07b2286SMarian Postevca 
3909dee7e51SXiaoyao Li     object_class_property_add(oc, X86_MACHINE_PIT, "OnOffAuto",
3919dee7e51SXiaoyao Li                               x86_machine_get_pit,
3929dee7e51SXiaoyao Li                               x86_machine_set_pit,
3939dee7e51SXiaoyao Li                               NULL, NULL);
3949dee7e51SXiaoyao Li     object_class_property_set_description(oc, X86_MACHINE_PIT,
3959dee7e51SXiaoyao Li         "Enable i8254 PIT");
3969dee7e51SXiaoyao Li 
397c300bbe8SXiaoyao Li     object_class_property_add(oc, X86_MACHINE_PIC, "OnOffAuto",
398c300bbe8SXiaoyao Li                               x86_machine_get_pic,
399c300bbe8SXiaoyao Li                               x86_machine_set_pic,
400c300bbe8SXiaoyao Li                               NULL, NULL);
401c300bbe8SXiaoyao Li     object_class_property_set_description(oc, X86_MACHINE_PIC,
402c300bbe8SXiaoyao Li         "Enable i8259 PIC");
403c300bbe8SXiaoyao Li 
404d07b2286SMarian Postevca     object_class_property_add_str(oc, X86_MACHINE_OEM_ID,
405d07b2286SMarian Postevca                                   x86_machine_get_oem_id,
406d07b2286SMarian Postevca                                   x86_machine_set_oem_id);
407d07b2286SMarian Postevca     object_class_property_set_description(oc, X86_MACHINE_OEM_ID,
408d07b2286SMarian Postevca                                           "Override the default value of field OEMID "
409d07b2286SMarian Postevca                                           "in ACPI table header."
410d07b2286SMarian Postevca                                           "The string may be up to 6 bytes in size");
411d07b2286SMarian Postevca 
412d07b2286SMarian Postevca 
413d07b2286SMarian Postevca     object_class_property_add_str(oc, X86_MACHINE_OEM_TABLE_ID,
414d07b2286SMarian Postevca                                   x86_machine_get_oem_table_id,
415d07b2286SMarian Postevca                                   x86_machine_set_oem_table_id);
416d07b2286SMarian Postevca     object_class_property_set_description(oc, X86_MACHINE_OEM_TABLE_ID,
417d07b2286SMarian Postevca                                           "Override the default value of field OEM Table ID "
418d07b2286SMarian Postevca                                           "in ACPI table header."
419d07b2286SMarian Postevca                                           "The string may be up to 8 bytes in size");
420035d1ef2SChenyi Qiang 
421035d1ef2SChenyi Qiang     object_class_property_add(oc, X86_MACHINE_BUS_LOCK_RATELIMIT, "uint64_t",
422035d1ef2SChenyi Qiang                                 x86_machine_get_bus_lock_ratelimit,
423035d1ef2SChenyi Qiang                                 x86_machine_set_bus_lock_ratelimit, NULL, NULL);
424035d1ef2SChenyi Qiang     object_class_property_set_description(oc, X86_MACHINE_BUS_LOCK_RATELIMIT,
425035d1ef2SChenyi Qiang             "Set the ratelimit for the bus locks acquired in VMs");
426dfce81f1SSean Christopherson 
427dfce81f1SSean Christopherson     object_class_property_add(oc, "sgx-epc", "SgxEPC",
428dfce81f1SSean Christopherson         machine_get_sgx_epc, machine_set_sgx_epc,
429dfce81f1SSean Christopherson         NULL, NULL);
430dfce81f1SSean Christopherson     object_class_property_set_description(oc, "sgx-epc",
431dfce81f1SSean Christopherson         "SGX EPC device");
432f0bb276bSPaolo Bonzini }
433f0bb276bSPaolo Bonzini 
434f0bb276bSPaolo Bonzini static const TypeInfo x86_machine_info = {
435f0bb276bSPaolo Bonzini     .name = TYPE_X86_MACHINE,
436f0bb276bSPaolo Bonzini     .parent = TYPE_MACHINE,
437f0bb276bSPaolo Bonzini     .abstract = true,
438f0bb276bSPaolo Bonzini     .instance_size = sizeof(X86MachineState),
439f0bb276bSPaolo Bonzini     .instance_init = x86_machine_initfn,
440f0bb276bSPaolo Bonzini     .class_size = sizeof(X86MachineClass),
441f0bb276bSPaolo Bonzini     .class_init = x86_machine_class_init,
442f0bb276bSPaolo Bonzini     .interfaces = (InterfaceInfo[]) {
443f0bb276bSPaolo Bonzini          { TYPE_NMI },
444f0bb276bSPaolo Bonzini          { }
445f0bb276bSPaolo Bonzini     },
446f0bb276bSPaolo Bonzini };
447f0bb276bSPaolo Bonzini 
x86_machine_register_types(void)448f0bb276bSPaolo Bonzini static void x86_machine_register_types(void)
449f0bb276bSPaolo Bonzini {
450f0bb276bSPaolo Bonzini     type_register_static(&x86_machine_info);
451f0bb276bSPaolo Bonzini }
452f0bb276bSPaolo Bonzini 
453f0bb276bSPaolo Bonzini type_init(x86_machine_register_types)
454