xref: /qemu/hw/i386/x86.c (revision 3568adc995b3906b5cc134753a829363f08bf6e1)
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 
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;
48*3568adc9SZhao Liu     /*
49*3568adc9SZhao Liu      * Though smp.modules means the number of modules in one cluster,
50*3568adc9SZhao Liu      * i386 doesn't support cluster level so that the smp.clusters
51*3568adc9SZhao Liu      * always defaults to 1, therefore using smp.modules directly is
52*3568adc9SZhao Liu      * fine here.
53*3568adc9SZhao Liu      */
54*3568adc9SZhao Liu     topo_info->modules_per_die = ms->smp.modules;
55*3568adc9SZhao 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  */
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
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 
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 
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         }
138549e984eSSergio Lopez         ms->possible_cpus->cpus[i].props.has_core_id = true;
139dcf08bc6SBabu Moger         ms->possible_cpus->cpus[i].props.core_id = topo_ids.core_id;
140549e984eSSergio Lopez         ms->possible_cpus->cpus[i].props.has_thread_id = true;
141dcf08bc6SBabu Moger         ms->possible_cpus->cpus[i].props.thread_id = topo_ids.smt_id;
142549e984eSSergio Lopez     }
143549e984eSSergio Lopez     return ms->possible_cpus;
144549e984eSSergio Lopez }
145549e984eSSergio Lopez 
146f0bb276bSPaolo Bonzini static void x86_nmi(NMIState *n, int cpu_index, Error **errp)
147f0bb276bSPaolo Bonzini {
148f0bb276bSPaolo Bonzini     /* cpu index isn't used */
149f0bb276bSPaolo Bonzini     CPUState *cs;
150f0bb276bSPaolo Bonzini 
151f0bb276bSPaolo Bonzini     CPU_FOREACH(cs) {
152f0bb276bSPaolo Bonzini         X86CPU *cpu = X86_CPU(cs);
153f0bb276bSPaolo Bonzini 
154c2e6d7d8SBernhard Beschow         if (cpu_is_apic_enabled(cpu->apic_state)) {
155f0bb276bSPaolo Bonzini             apic_deliver_nmi(cpu->apic_state);
156f22f3a92SBernhard Beschow         } else {
157f22f3a92SBernhard Beschow             cpu_interrupt(cs, CPU_INTERRUPT_NMI);
158f0bb276bSPaolo Bonzini         }
159f0bb276bSPaolo Bonzini     }
160f0bb276bSPaolo Bonzini }
161f0bb276bSPaolo Bonzini 
1629927a632SGerd Hoffmann bool x86_machine_is_smm_enabled(const X86MachineState *x86ms)
163ed9e923cSPaolo Bonzini {
164ed9e923cSPaolo Bonzini     bool smm_available = false;
165ed9e923cSPaolo Bonzini 
166ed9e923cSPaolo Bonzini     if (x86ms->smm == ON_OFF_AUTO_OFF) {
167ed9e923cSPaolo Bonzini         return false;
168ed9e923cSPaolo Bonzini     }
169ed9e923cSPaolo Bonzini 
170ed9e923cSPaolo Bonzini     if (tcg_enabled() || qtest_enabled()) {
171ed9e923cSPaolo Bonzini         smm_available = true;
172ed9e923cSPaolo Bonzini     } else if (kvm_enabled()) {
173ed9e923cSPaolo Bonzini         smm_available = kvm_has_smm();
174ed9e923cSPaolo Bonzini     }
175ed9e923cSPaolo Bonzini 
176ed9e923cSPaolo Bonzini     if (smm_available) {
177ed9e923cSPaolo Bonzini         return true;
178ed9e923cSPaolo Bonzini     }
179ed9e923cSPaolo Bonzini 
180ed9e923cSPaolo Bonzini     if (x86ms->smm == ON_OFF_AUTO_ON) {
181ed9e923cSPaolo Bonzini         error_report("System Management Mode not supported by this hypervisor.");
182ed9e923cSPaolo Bonzini         exit(1);
183ed9e923cSPaolo Bonzini     }
184ed9e923cSPaolo Bonzini     return false;
185ed9e923cSPaolo Bonzini }
186ed9e923cSPaolo Bonzini 
187ed9e923cSPaolo Bonzini static void x86_machine_get_smm(Object *obj, Visitor *v, const char *name,
188ed9e923cSPaolo Bonzini                                void *opaque, Error **errp)
189ed9e923cSPaolo Bonzini {
190ed9e923cSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(obj);
191ed9e923cSPaolo Bonzini     OnOffAuto smm = x86ms->smm;
192ed9e923cSPaolo Bonzini 
193ed9e923cSPaolo Bonzini     visit_type_OnOffAuto(v, name, &smm, errp);
194ed9e923cSPaolo Bonzini }
195ed9e923cSPaolo Bonzini 
196ed9e923cSPaolo Bonzini static void x86_machine_set_smm(Object *obj, Visitor *v, const char *name,
197ed9e923cSPaolo Bonzini                                void *opaque, Error **errp)
198ed9e923cSPaolo Bonzini {
199ed9e923cSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(obj);
200ed9e923cSPaolo Bonzini 
201ed9e923cSPaolo Bonzini     visit_type_OnOffAuto(v, name, &x86ms->smm, errp);
202ed9e923cSPaolo Bonzini }
203ed9e923cSPaolo Bonzini 
2049927a632SGerd Hoffmann bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms)
20517e89077SGerd Hoffmann {
20617e89077SGerd Hoffmann     if (x86ms->acpi == ON_OFF_AUTO_OFF) {
20717e89077SGerd Hoffmann         return false;
20817e89077SGerd Hoffmann     }
20917e89077SGerd Hoffmann     return true;
21017e89077SGerd Hoffmann }
21117e89077SGerd Hoffmann 
21217e89077SGerd Hoffmann static void x86_machine_get_acpi(Object *obj, Visitor *v, const char *name,
21317e89077SGerd Hoffmann                                  void *opaque, Error **errp)
21417e89077SGerd Hoffmann {
21517e89077SGerd Hoffmann     X86MachineState *x86ms = X86_MACHINE(obj);
21617e89077SGerd Hoffmann     OnOffAuto acpi = x86ms->acpi;
21717e89077SGerd Hoffmann 
21817e89077SGerd Hoffmann     visit_type_OnOffAuto(v, name, &acpi, errp);
21917e89077SGerd Hoffmann }
22017e89077SGerd Hoffmann 
22117e89077SGerd Hoffmann static void x86_machine_set_acpi(Object *obj, Visitor *v, const char *name,
22217e89077SGerd Hoffmann                                  void *opaque, Error **errp)
22317e89077SGerd Hoffmann {
22417e89077SGerd Hoffmann     X86MachineState *x86ms = X86_MACHINE(obj);
22517e89077SGerd Hoffmann 
22617e89077SGerd Hoffmann     visit_type_OnOffAuto(v, name, &x86ms->acpi, errp);
22717e89077SGerd Hoffmann }
22817e89077SGerd Hoffmann 
2299dee7e51SXiaoyao Li static void x86_machine_get_pit(Object *obj, Visitor *v, const char *name,
2309dee7e51SXiaoyao Li                                     void *opaque, Error **errp)
2319dee7e51SXiaoyao Li {
2329dee7e51SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);
2339dee7e51SXiaoyao Li     OnOffAuto pit = x86ms->pit;
2349dee7e51SXiaoyao Li 
2359dee7e51SXiaoyao Li     visit_type_OnOffAuto(v, name, &pit, errp);
2369dee7e51SXiaoyao Li }
2379dee7e51SXiaoyao Li 
2389dee7e51SXiaoyao Li static void x86_machine_set_pit(Object *obj, Visitor *v, const char *name,
2399dee7e51SXiaoyao Li                                     void *opaque, Error **errp)
2409dee7e51SXiaoyao Li {
2419dee7e51SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);;
2429dee7e51SXiaoyao Li 
2439dee7e51SXiaoyao Li     visit_type_OnOffAuto(v, name, &x86ms->pit, errp);
2449dee7e51SXiaoyao Li }
2459dee7e51SXiaoyao Li 
246c300bbe8SXiaoyao Li static void x86_machine_get_pic(Object *obj, Visitor *v, const char *name,
247c300bbe8SXiaoyao Li                                 void *opaque, Error **errp)
248c300bbe8SXiaoyao Li {
249c300bbe8SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);
250c300bbe8SXiaoyao Li     OnOffAuto pic = x86ms->pic;
251c300bbe8SXiaoyao Li 
252c300bbe8SXiaoyao Li     visit_type_OnOffAuto(v, name, &pic, errp);
253c300bbe8SXiaoyao Li }
254c300bbe8SXiaoyao Li 
255c300bbe8SXiaoyao Li static void x86_machine_set_pic(Object *obj, Visitor *v, const char *name,
256c300bbe8SXiaoyao Li                                 void *opaque, Error **errp)
257c300bbe8SXiaoyao Li {
258c300bbe8SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(obj);
259c300bbe8SXiaoyao Li 
260c300bbe8SXiaoyao Li     visit_type_OnOffAuto(v, name, &x86ms->pic, errp);
261c300bbe8SXiaoyao Li }
262c300bbe8SXiaoyao Li 
263d07b2286SMarian Postevca static char *x86_machine_get_oem_id(Object *obj, Error **errp)
264d07b2286SMarian Postevca {
265d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
266d07b2286SMarian Postevca 
267d07b2286SMarian Postevca     return g_strdup(x86ms->oem_id);
268d07b2286SMarian Postevca }
269d07b2286SMarian Postevca 
270d07b2286SMarian Postevca static void x86_machine_set_oem_id(Object *obj, const char *value, Error **errp)
271d07b2286SMarian Postevca {
272d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
273d07b2286SMarian Postevca     size_t len = strlen(value);
274d07b2286SMarian Postevca 
275d07b2286SMarian Postevca     if (len > 6) {
276d07b2286SMarian Postevca         error_setg(errp,
277d07b2286SMarian Postevca                    "User specified "X86_MACHINE_OEM_ID" value is bigger than "
278d07b2286SMarian Postevca                    "6 bytes in size");
279d07b2286SMarian Postevca         return;
280d07b2286SMarian Postevca     }
281d07b2286SMarian Postevca 
282d07b2286SMarian Postevca     strncpy(x86ms->oem_id, value, 6);
283d07b2286SMarian Postevca }
284d07b2286SMarian Postevca 
285d07b2286SMarian Postevca static char *x86_machine_get_oem_table_id(Object *obj, Error **errp)
286d07b2286SMarian Postevca {
287d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
288d07b2286SMarian Postevca 
289d07b2286SMarian Postevca     return g_strdup(x86ms->oem_table_id);
290d07b2286SMarian Postevca }
291d07b2286SMarian Postevca 
292d07b2286SMarian Postevca static void x86_machine_set_oem_table_id(Object *obj, const char *value,
293d07b2286SMarian Postevca                                          Error **errp)
294d07b2286SMarian Postevca {
295d07b2286SMarian Postevca     X86MachineState *x86ms = X86_MACHINE(obj);
296d07b2286SMarian Postevca     size_t len = strlen(value);
297d07b2286SMarian Postevca 
298d07b2286SMarian Postevca     if (len > 8) {
299d07b2286SMarian Postevca         error_setg(errp,
300d07b2286SMarian Postevca                    "User specified "X86_MACHINE_OEM_TABLE_ID
301d07b2286SMarian Postevca                    " value is bigger than "
302d07b2286SMarian Postevca                    "8 bytes in size");
303d07b2286SMarian Postevca         return;
304d07b2286SMarian Postevca     }
305d07b2286SMarian Postevca     strncpy(x86ms->oem_table_id, value, 8);
306d07b2286SMarian Postevca }
307d07b2286SMarian Postevca 
308035d1ef2SChenyi Qiang static void x86_machine_get_bus_lock_ratelimit(Object *obj, Visitor *v,
309035d1ef2SChenyi Qiang                                 const char *name, void *opaque, Error **errp)
310035d1ef2SChenyi Qiang {
311035d1ef2SChenyi Qiang     X86MachineState *x86ms = X86_MACHINE(obj);
312035d1ef2SChenyi Qiang     uint64_t bus_lock_ratelimit = x86ms->bus_lock_ratelimit;
313035d1ef2SChenyi Qiang 
314035d1ef2SChenyi Qiang     visit_type_uint64(v, name, &bus_lock_ratelimit, errp);
315035d1ef2SChenyi Qiang }
316035d1ef2SChenyi Qiang 
317035d1ef2SChenyi Qiang static void x86_machine_set_bus_lock_ratelimit(Object *obj, Visitor *v,
318035d1ef2SChenyi Qiang                                const char *name, void *opaque, Error **errp)
319035d1ef2SChenyi Qiang {
320035d1ef2SChenyi Qiang     X86MachineState *x86ms = X86_MACHINE(obj);
321035d1ef2SChenyi Qiang 
322035d1ef2SChenyi Qiang     visit_type_uint64(v, name, &x86ms->bus_lock_ratelimit, errp);
323035d1ef2SChenyi Qiang }
324035d1ef2SChenyi Qiang 
325dfce81f1SSean Christopherson static void machine_get_sgx_epc(Object *obj, Visitor *v, const char *name,
326dfce81f1SSean Christopherson                                 void *opaque, Error **errp)
327dfce81f1SSean Christopherson {
328dfce81f1SSean Christopherson     X86MachineState *x86ms = X86_MACHINE(obj);
329dfce81f1SSean Christopherson     SgxEPCList *list = x86ms->sgx_epc_list;
330dfce81f1SSean Christopherson 
331dfce81f1SSean Christopherson     visit_type_SgxEPCList(v, name, &list, errp);
332dfce81f1SSean Christopherson }
333dfce81f1SSean Christopherson 
334dfce81f1SSean Christopherson static void machine_set_sgx_epc(Object *obj, Visitor *v, const char *name,
335dfce81f1SSean Christopherson                                 void *opaque, Error **errp)
336dfce81f1SSean Christopherson {
337dfce81f1SSean Christopherson     X86MachineState *x86ms = X86_MACHINE(obj);
338dfce81f1SSean Christopherson     SgxEPCList *list;
339dfce81f1SSean Christopherson 
340dfce81f1SSean Christopherson     list = x86ms->sgx_epc_list;
341dfce81f1SSean Christopherson     visit_type_SgxEPCList(v, name, &x86ms->sgx_epc_list, errp);
342dfce81f1SSean Christopherson 
343dfce81f1SSean Christopherson     qapi_free_SgxEPCList(list);
344dfce81f1SSean Christopherson }
345dfce81f1SSean Christopherson 
346ee88612dSPaolo Bonzini static int x86_kvm_type(MachineState *ms, const char *vm_type)
347ee88612dSPaolo Bonzini {
348ee88612dSPaolo Bonzini     /*
349ee88612dSPaolo Bonzini      * No x86 machine has a kvm-type property.  If one is added that has
350ee88612dSPaolo Bonzini      * it, it should call kvm_get_vm_type() directly or not use it at all.
351ee88612dSPaolo Bonzini      */
352ee88612dSPaolo Bonzini     assert(vm_type == NULL);
353ee88612dSPaolo Bonzini     return kvm_enabled() ? kvm_get_vm_type(ms) : 0;
354ee88612dSPaolo Bonzini }
355ee88612dSPaolo Bonzini 
356f0bb276bSPaolo Bonzini static void x86_machine_initfn(Object *obj)
357f0bb276bSPaolo Bonzini {
358f0bb276bSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(obj);
359f0bb276bSPaolo Bonzini 
360ed9e923cSPaolo Bonzini     x86ms->smm = ON_OFF_AUTO_AUTO;
36117e89077SGerd Hoffmann     x86ms->acpi = ON_OFF_AUTO_AUTO;
3629dee7e51SXiaoyao Li     x86ms->pit = ON_OFF_AUTO_AUTO;
363c300bbe8SXiaoyao Li     x86ms->pic = ON_OFF_AUTO_AUTO;
3641b2802c4SGerd Hoffmann     x86ms->pci_irq_mask = ACPI_BUILD_PCI_IRQS;
365d07b2286SMarian Postevca     x86ms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
366d07b2286SMarian Postevca     x86ms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
367035d1ef2SChenyi Qiang     x86ms->bus_lock_ratelimit = 0;
3684ab4c330SJoao Martins     x86ms->above_4g_mem_start = 4 * GiB;
369f0bb276bSPaolo Bonzini }
370f0bb276bSPaolo Bonzini 
371f0bb276bSPaolo Bonzini static void x86_machine_class_init(ObjectClass *oc, void *data)
372f0bb276bSPaolo Bonzini {
373f0bb276bSPaolo Bonzini     MachineClass *mc = MACHINE_CLASS(oc);
374f0bb276bSPaolo Bonzini     X86MachineClass *x86mc = X86_MACHINE_CLASS(oc);
375f0bb276bSPaolo Bonzini     NMIClass *nc = NMI_CLASS(oc);
376f0bb276bSPaolo Bonzini 
377f0bb276bSPaolo Bonzini     mc->cpu_index_to_instance_props = x86_cpu_index_to_props;
378f0bb276bSPaolo Bonzini     mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
379f0bb276bSPaolo Bonzini     mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
380ee88612dSPaolo Bonzini     mc->kvm_type = x86_kvm_type;
3812f34ebf2SLiam Merwick     x86mc->save_tsc_khz = true;
382f014c974SPaolo Bonzini     x86mc->fwcfg_dma_enabled = true;
383f0bb276bSPaolo Bonzini     nc->nmi_monitor_handler = x86_nmi;
384f0bb276bSPaolo Bonzini 
385ed9e923cSPaolo Bonzini     object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto",
386ed9e923cSPaolo Bonzini         x86_machine_get_smm, x86_machine_set_smm,
387d2623129SMarkus Armbruster         NULL, NULL);
388ed9e923cSPaolo Bonzini     object_class_property_set_description(oc, X86_MACHINE_SMM,
3897eecec7dSMarkus Armbruster         "Enable SMM");
39017e89077SGerd Hoffmann 
39117e89077SGerd Hoffmann     object_class_property_add(oc, X86_MACHINE_ACPI, "OnOffAuto",
39217e89077SGerd Hoffmann         x86_machine_get_acpi, x86_machine_set_acpi,
393d2623129SMarkus Armbruster         NULL, NULL);
39417e89077SGerd Hoffmann     object_class_property_set_description(oc, X86_MACHINE_ACPI,
3957eecec7dSMarkus Armbruster         "Enable ACPI");
396d07b2286SMarian Postevca 
3979dee7e51SXiaoyao Li     object_class_property_add(oc, X86_MACHINE_PIT, "OnOffAuto",
3989dee7e51SXiaoyao Li                               x86_machine_get_pit,
3999dee7e51SXiaoyao Li                               x86_machine_set_pit,
4009dee7e51SXiaoyao Li                               NULL, NULL);
4019dee7e51SXiaoyao Li     object_class_property_set_description(oc, X86_MACHINE_PIT,
4029dee7e51SXiaoyao Li         "Enable i8254 PIT");
4039dee7e51SXiaoyao Li 
404c300bbe8SXiaoyao Li     object_class_property_add(oc, X86_MACHINE_PIC, "OnOffAuto",
405c300bbe8SXiaoyao Li                               x86_machine_get_pic,
406c300bbe8SXiaoyao Li                               x86_machine_set_pic,
407c300bbe8SXiaoyao Li                               NULL, NULL);
408c300bbe8SXiaoyao Li     object_class_property_set_description(oc, X86_MACHINE_PIC,
409c300bbe8SXiaoyao Li         "Enable i8259 PIC");
410c300bbe8SXiaoyao Li 
411d07b2286SMarian Postevca     object_class_property_add_str(oc, X86_MACHINE_OEM_ID,
412d07b2286SMarian Postevca                                   x86_machine_get_oem_id,
413d07b2286SMarian Postevca                                   x86_machine_set_oem_id);
414d07b2286SMarian Postevca     object_class_property_set_description(oc, X86_MACHINE_OEM_ID,
415d07b2286SMarian Postevca                                           "Override the default value of field OEMID "
416d07b2286SMarian Postevca                                           "in ACPI table header."
417d07b2286SMarian Postevca                                           "The string may be up to 6 bytes in size");
418d07b2286SMarian Postevca 
419d07b2286SMarian Postevca 
420d07b2286SMarian Postevca     object_class_property_add_str(oc, X86_MACHINE_OEM_TABLE_ID,
421d07b2286SMarian Postevca                                   x86_machine_get_oem_table_id,
422d07b2286SMarian Postevca                                   x86_machine_set_oem_table_id);
423d07b2286SMarian Postevca     object_class_property_set_description(oc, X86_MACHINE_OEM_TABLE_ID,
424d07b2286SMarian Postevca                                           "Override the default value of field OEM Table ID "
425d07b2286SMarian Postevca                                           "in ACPI table header."
426d07b2286SMarian Postevca                                           "The string may be up to 8 bytes in size");
427035d1ef2SChenyi Qiang 
428035d1ef2SChenyi Qiang     object_class_property_add(oc, X86_MACHINE_BUS_LOCK_RATELIMIT, "uint64_t",
429035d1ef2SChenyi Qiang                                 x86_machine_get_bus_lock_ratelimit,
430035d1ef2SChenyi Qiang                                 x86_machine_set_bus_lock_ratelimit, NULL, NULL);
431035d1ef2SChenyi Qiang     object_class_property_set_description(oc, X86_MACHINE_BUS_LOCK_RATELIMIT,
432035d1ef2SChenyi Qiang             "Set the ratelimit for the bus locks acquired in VMs");
433dfce81f1SSean Christopherson 
434dfce81f1SSean Christopherson     object_class_property_add(oc, "sgx-epc", "SgxEPC",
435dfce81f1SSean Christopherson         machine_get_sgx_epc, machine_set_sgx_epc,
436dfce81f1SSean Christopherson         NULL, NULL);
437dfce81f1SSean Christopherson     object_class_property_set_description(oc, "sgx-epc",
438dfce81f1SSean Christopherson         "SGX EPC device");
439f0bb276bSPaolo Bonzini }
440f0bb276bSPaolo Bonzini 
441f0bb276bSPaolo Bonzini static const TypeInfo x86_machine_info = {
442f0bb276bSPaolo Bonzini     .name = TYPE_X86_MACHINE,
443f0bb276bSPaolo Bonzini     .parent = TYPE_MACHINE,
444f0bb276bSPaolo Bonzini     .abstract = true,
445f0bb276bSPaolo Bonzini     .instance_size = sizeof(X86MachineState),
446f0bb276bSPaolo Bonzini     .instance_init = x86_machine_initfn,
447f0bb276bSPaolo Bonzini     .class_size = sizeof(X86MachineClass),
448f0bb276bSPaolo Bonzini     .class_init = x86_machine_class_init,
449f0bb276bSPaolo Bonzini     .interfaces = (InterfaceInfo[]) {
450f0bb276bSPaolo Bonzini          { TYPE_NMI },
451f0bb276bSPaolo Bonzini          { }
452f0bb276bSPaolo Bonzini     },
453f0bb276bSPaolo Bonzini };
454f0bb276bSPaolo Bonzini 
455f0bb276bSPaolo Bonzini static void x86_machine_register_types(void)
456f0bb276bSPaolo Bonzini {
457f0bb276bSPaolo Bonzini     type_register_static(&x86_machine_info);
458f0bb276bSPaolo Bonzini }
459f0bb276bSPaolo Bonzini 
460f0bb276bSPaolo Bonzini type_init(x86_machine_register_types)
461