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