xref: /openbmc/qemu/hw/i386/pc.c (revision 5eeb09d63e081d516f7d33b353a5179d58e1f9b6)
153018216SPaolo Bonzini /*
253018216SPaolo Bonzini  * QEMU PC System Emulator
353018216SPaolo Bonzini  *
453018216SPaolo Bonzini  * Copyright (c) 2003-2004 Fabrice Bellard
553018216SPaolo Bonzini  *
653018216SPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
753018216SPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
853018216SPaolo Bonzini  * in the Software without restriction, including without limitation the rights
953018216SPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1053018216SPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
1153018216SPaolo Bonzini  * furnished to do so, subject to the following conditions:
1253018216SPaolo Bonzini  *
1353018216SPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
1453018216SPaolo Bonzini  * all copies or substantial portions of the Software.
1553018216SPaolo Bonzini  *
1653018216SPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1753018216SPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1853018216SPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1953018216SPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2053018216SPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2153018216SPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2253018216SPaolo Bonzini  * THE SOFTWARE.
2353018216SPaolo Bonzini  */
24e688df6bSMarkus Armbruster 
25b6a0aa05SPeter Maydell #include "qemu/osdep.h"
26d471bf3eSPaolo Bonzini #include "qemu/units.h"
270d09e41aSPaolo Bonzini #include "hw/i386/pc.h"
2837b724cdSBernhard Beschow #include "hw/char/serial-isa.h"
29bb3d5ea8SPhilippe Mathieu-Daudé #include "hw/char/parallel.h"
309a52aa40SMaciej S. Szmigiero #include "hw/hyperv/hv-balloon.h"
3187abaa5dSPhilippe Mathieu-Daudé #include "hw/i386/fw_cfg.h"
32d8f23d61SLiran Alon #include "hw/i386/vmport.h"
3354a40293SEduardo Habkost #include "sysemu/cpus.h"
34a11f439aSThomas Huth #include "hw/ide/ide-bus.h"
350d09e41aSPaolo Bonzini #include "hw/timer/hpet.h"
3653018216SPaolo Bonzini #include "hw/loader.h"
37bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
38852c27e2SPaolo Bonzini #include "hw/intc/i8259.h"
390d09e41aSPaolo Bonzini #include "hw/timer/i8254.h"
4047973a2dSPhilippe Mathieu-Daudé #include "hw/input/i8042.h"
410d09e41aSPaolo Bonzini #include "hw/audio/pcspk.h"
4253018216SPaolo Bonzini #include "sysemu/sysemu.h"
43da278d58SPhilippe Mathieu-Daudé #include "sysemu/xen.h"
4471e8a915SMarkus Armbruster #include "sysemu/reset.h"
45a9dc68d9SClaudio Fontana #include "kvm/kvm_i386.h"
460d09e41aSPaolo Bonzini #include "hw/xen/xen.h"
4733f0c061SKevin Wolf #include "qapi/qmp/qlist.h"
48d49b6836SMarkus Armbruster #include "qemu/error-report.h"
495ff020b7SEduardo Habkost #include "hw/acpi/cpu_hotplug.h"
5072c194f7SMichael S. Tsirkin #include "acpi-build.h"
514b997690SPhilippe Mathieu-Daudé #include "hw/mem/nvdimm.h"
5203b39fcfSJonathan Cameron #include "hw/cxl/cxl_host.h"
53a310e653SMarc-André Lureau #include "hw/usb.h"
5460c5e104SIgor Mammedov #include "hw/i386/intel_iommu.h"
55489983d6SPhilippe Mathieu-Daudé #include "hw/net/ne2000-isa.h"
5636efa250SJean-Philippe Brucker #include "hw/virtio/virtio-iommu.h"
57dbdf841bSDavid Hildenbrand #include "hw/virtio/virtio-md-pci.h"
58e21be724SDavid Woodhouse #include "hw/i386/kvm/xen_overlay.h"
5991cce756SDavid Woodhouse #include "hw/i386/kvm/xen_evtchn.h"
60a28b0fc0SDavid Woodhouse #include "hw/i386/kvm/xen_gnttab.h"
61c08f5d0eSDavid Woodhouse #include "hw/i386/kvm/xen_xenstore.h"
629a52aa40SMaciej S. Szmigiero #include "hw/mem/memory-device.h"
63d6d059caSPhilippe Mathieu-Daudé #include "e820_memory_layout.h"
644ca8dabdSPhilippe Mathieu-Daudé #include "trace.h"
65413a6745SMichael Roth #include "sev.h"
662becc36aSPaolo Bonzini #include CONFIG_DEVICES
6753018216SPaolo Bonzini 
68a78c54c4SDavid Woodhouse #ifdef CONFIG_XEN_EMU
69a78c54c4SDavid Woodhouse #include "hw/xen/xen-legacy-backend.h"
70a78c54c4SDavid Woodhouse #include "hw/xen/xen-bus.h"
71a78c54c4SDavid Woodhouse #endif
72a78c54c4SDavid Woodhouse 
73fc5f8923SBernhard Beschow /*
74fc5f8923SBernhard Beschow  * Helper for setting model-id for CPU models that changed model-id
75fc5f8923SBernhard Beschow  * depending on QEMU versions up to QEMU 2.4.
76fc5f8923SBernhard Beschow  */
77fc5f8923SBernhard Beschow #define PC_CPU_MODEL_IDS(v) \
78fc5f8923SBernhard Beschow     { "qemu32-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\
79fc5f8923SBernhard Beschow     { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\
80fc5f8923SBernhard Beschow     { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },
81fc5f8923SBernhard Beschow 
826e3c2d58SDominic Prinz GlobalProperty pc_compat_9_1[] = {
836e3c2d58SDominic Prinz     { "ICH9-LPC", "x-smi-swsmi-timer", "off" },
846e3c2d58SDominic Prinz     { "ICH9-LPC", "x-smi-periodic-timer", "off" },
856ce12bd2SZhenzhong Duan     { TYPE_INTEL_IOMMU_DEVICE, "stale-tm", "on" },
866e3c2d58SDominic Prinz };
87fb6051e7SCornelia Huck const size_t pc_compat_9_1_len = G_N_ELEMENTS(pc_compat_9_1);
88fb6051e7SCornelia Huck 
89513ba32dSGerd Hoffmann GlobalProperty pc_compat_9_0[] = {
9029a51b2bSPaolo Bonzini     { TYPE_X86_CPU, "x-amd-topoext-features-only", "false" },
9112f6b828SZhao Liu     { TYPE_X86_CPU, "x-l1-cache-per-thread", "false" },
92513ba32dSGerd Hoffmann     { TYPE_X86_CPU, "guest-phys-bits", "0" },
939d38d9dcSMichael Roth     { "sev-guest", "legacy-vm-type", "on" },
94b776569aSBabu Moger     { TYPE_X86_CPU, "legacy-multi-node", "on" },
95513ba32dSGerd Hoffmann };
9685fa9acdSPaolo Bonzini const size_t pc_compat_9_0_len = G_N_ELEMENTS(pc_compat_9_0);
9785fa9acdSPaolo Bonzini 
982b10a676SCornelia Huck GlobalProperty pc_compat_8_2[] = {};
992b10a676SCornelia Huck const size_t pc_compat_8_2_len = G_N_ELEMENTS(pc_compat_8_2);
1002b10a676SCornelia Huck 
10195f5c89eSCornelia Huck GlobalProperty pc_compat_8_1[] = {};
10295f5c89eSCornelia Huck const size_t pc_compat_8_1_len = G_N_ELEMENTS(pc_compat_8_1);
10395f5c89eSCornelia Huck 
104d5cef025SDavid Hildenbrand GlobalProperty pc_compat_8_0[] = {
105d5cef025SDavid Hildenbrand     { "virtio-mem", "unplugged-inaccessible", "auto" },
106d5cef025SDavid Hildenbrand };
1070259dd3eSCornelia Huck const size_t pc_compat_8_0_len = G_N_ELEMENTS(pc_compat_8_0);
1080259dd3eSCornelia Huck 
109a6b6414fSDaniel P. Berrangé GlobalProperty pc_compat_7_2[] = {
110a6b6414fSDaniel P. Berrangé     { "ICH9-LPC", "noreboot", "true" },
111a6b6414fSDaniel P. Berrangé };
112db723c80SCornelia Huck const size_t pc_compat_7_2_len = G_N_ELEMENTS(pc_compat_7_2);
113db723c80SCornelia Huck 
114f514e147SCornelia Huck GlobalProperty pc_compat_7_1[] = {};
115f514e147SCornelia Huck const size_t pc_compat_7_1_len = G_N_ELEMENTS(pc_compat_7_1);
116f514e147SCornelia Huck 
1170ca70366SCornelia Huck GlobalProperty pc_compat_7_0[] = {};
1180ca70366SCornelia Huck const size_t pc_compat_7_0_len = G_N_ELEMENTS(pc_compat_7_0);
1190ca70366SCornelia Huck 
12060f1f77cSDavid Hildenbrand GlobalProperty pc_compat_6_2[] = {
12160f1f77cSDavid Hildenbrand     { "virtio-mem", "unplugged-inaccessible", "off" },
12260f1f77cSDavid Hildenbrand };
12301854af2SCornelia Huck const size_t pc_compat_6_2_len = G_N_ELEMENTS(pc_compat_6_2);
12401854af2SCornelia Huck 
125f701ececSVitaly Kuznetsov GlobalProperty pc_compat_6_1[] = {
126f701ececSVitaly Kuznetsov     { TYPE_X86_CPU, "hv-version-id-build", "0x1bbc" },
127f701ececSVitaly Kuznetsov     { TYPE_X86_CPU, "hv-version-id-major", "0x0006" },
128f701ececSVitaly Kuznetsov     { TYPE_X86_CPU, "hv-version-id-minor", "0x0001" },
129c318bef7SJulia Suvorova     { "ICH9-LPC", "x-keep-pci-slot-hpc", "false" },
130f701ececSVitaly Kuznetsov };
13152e64f5bSYanan Wang const size_t pc_compat_6_1_len = G_N_ELEMENTS(pc_compat_6_1);
13252e64f5bSYanan Wang 
133b7c29017SDaniel P. Berrangé GlobalProperty pc_compat_6_0[] = {
134b7c29017SDaniel P. Berrangé     { "qemu64" "-" TYPE_X86_CPU, "family", "6" },
135b7c29017SDaniel P. Berrangé     { "qemu64" "-" TYPE_X86_CPU, "model", "6" },
136b7c29017SDaniel P. Berrangé     { "qemu64" "-" TYPE_X86_CPU, "stepping", "3" },
137a7a0da84SMichael Roth     { TYPE_X86_CPU, "x-vendor-cpuid-only", "off" },
138aa29466bSAni Sinha     { "ICH9-LPC", ACPI_PM_PROP_ACPI_PCIHP_BRIDGE, "off" },
139c318bef7SJulia Suvorova     { "ICH9-LPC", "x-keep-pci-slot-hpc", "true" },
140b7c29017SDaniel P. Berrangé };
141da7e13c0SCornelia Huck const size_t pc_compat_6_0_len = G_N_ELEMENTS(pc_compat_6_0);
142da7e13c0SCornelia Huck 
1437ed3e1ebSIgor Mammedov GlobalProperty pc_compat_5_2[] = {
1447ed3e1ebSIgor Mammedov     { "ICH9-LPC", "x-smi-cpu-hotunplug", "off" },
1457ed3e1ebSIgor Mammedov };
146576a00bdSCornelia Huck const size_t pc_compat_5_2_len = G_N_ELEMENTS(pc_compat_5_2);
147576a00bdSCornelia Huck 
14800dc02d2SIgor Mammedov GlobalProperty pc_compat_5_1[] = {
14900dc02d2SIgor Mammedov     { "ICH9-LPC", "x-smi-cpu-hotplug", "off" },
150c1bb5418SDavid Woodhouse     { TYPE_X86_CPU, "kvm-msi-ext-dest-id", "off" },
15100dc02d2SIgor Mammedov };
1523ff3c5d3SCornelia Huck const size_t pc_compat_5_1_len = G_N_ELEMENTS(pc_compat_5_1);
1533ff3c5d3SCornelia Huck 
1542ebc2121SHogan Wang GlobalProperty pc_compat_5_0[] = {
1552ebc2121SHogan Wang };
156541aaa1dSCornelia Huck const size_t pc_compat_5_0_len = G_N_ELEMENTS(pc_compat_5_0);
157541aaa1dSCornelia Huck 
158f404220eSIgor Mammedov GlobalProperty pc_compat_4_2[] = {
159f404220eSIgor Mammedov     { "mch", "smbase-smram", "off" },
160f404220eSIgor Mammedov };
1613eb74d20SCornelia Huck const size_t pc_compat_4_2_len = G_N_ELEMENTS(pc_compat_4_2);
1623eb74d20SCornelia Huck 
1639aec2e52SCornelia Huck GlobalProperty pc_compat_4_1[] = {};
1649aec2e52SCornelia Huck const size_t pc_compat_4_1_len = G_N_ELEMENTS(pc_compat_4_1);
1659aec2e52SCornelia Huck 
1669bf2650bSCornelia Huck GlobalProperty pc_compat_4_0[] = {};
1679bf2650bSCornelia Huck const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0);
1689bf2650bSCornelia Huck 
169abd93cc7SMarc-André Lureau GlobalProperty pc_compat_3_1[] = {
1706c36bddfSEduardo Habkost     { "intel-iommu", "dma-drain", "off" },
171483c6ad4SBorislav Petkov     { "Opteron_G3" "-" TYPE_X86_CPU, "rdtscp", "off" },
172483c6ad4SBorislav Petkov     { "Opteron_G4" "-" TYPE_X86_CPU, "rdtscp", "off" },
1739fe8b7beSVitaly Kuznetsov     { "Opteron_G4" "-" TYPE_X86_CPU, "npt", "off" },
1749fe8b7beSVitaly Kuznetsov     { "Opteron_G4" "-" TYPE_X86_CPU, "nrip-save", "off" },
175483c6ad4SBorislav Petkov     { "Opteron_G5" "-" TYPE_X86_CPU, "rdtscp", "off" },
1769fe8b7beSVitaly Kuznetsov     { "Opteron_G5" "-" TYPE_X86_CPU, "npt", "off" },
1779fe8b7beSVitaly Kuznetsov     { "Opteron_G5" "-" TYPE_X86_CPU, "nrip-save", "off" },
1789fe8b7beSVitaly Kuznetsov     { "EPYC" "-" TYPE_X86_CPU, "npt", "off" },
1799fe8b7beSVitaly Kuznetsov     { "EPYC" "-" TYPE_X86_CPU, "nrip-save", "off" },
1809fe8b7beSVitaly Kuznetsov     { "EPYC-IBPB" "-" TYPE_X86_CPU, "npt", "off" },
1819fe8b7beSVitaly Kuznetsov     { "EPYC-IBPB" "-" TYPE_X86_CPU, "nrip-save", "off" },
182ecb85fe4SPaolo Bonzini     { "Skylake-Client" "-" TYPE_X86_CPU,      "mpx", "on" },
183ecb85fe4SPaolo Bonzini     { "Skylake-Client-IBRS" "-" TYPE_X86_CPU, "mpx", "on" },
184ecb85fe4SPaolo Bonzini     { "Skylake-Server" "-" TYPE_X86_CPU,      "mpx", "on" },
185ecb85fe4SPaolo Bonzini     { "Skylake-Server-IBRS" "-" TYPE_X86_CPU, "mpx", "on" },
186ecb85fe4SPaolo Bonzini     { "Cascadelake-Server" "-" TYPE_X86_CPU,  "mpx", "on" },
187ecb85fe4SPaolo Bonzini     { "Icelake-Client" "-" TYPE_X86_CPU,      "mpx", "on" },
188ecb85fe4SPaolo Bonzini     { "Icelake-Server" "-" TYPE_X86_CPU,      "mpx", "on" },
189b0a19803STao Xu     { "Cascadelake-Server" "-" TYPE_X86_CPU, "stepping", "5" },
190f24c3a79SLuwei Kang     { TYPE_X86_CPU, "x-intel-pt-auto-level", "off" },
191abd93cc7SMarc-André Lureau };
192abd93cc7SMarc-André Lureau const size_t pc_compat_3_1_len = G_N_ELEMENTS(pc_compat_3_1);
193abd93cc7SMarc-André Lureau 
194ddb3235dSMarc-André Lureau GlobalProperty pc_compat_3_0[] = {
1956c36bddfSEduardo Habkost     { TYPE_X86_CPU, "x-hv-synic-kvm-only", "on" },
1966c36bddfSEduardo Habkost     { "Skylake-Server" "-" TYPE_X86_CPU, "pku", "off" },
1976c36bddfSEduardo Habkost     { "Skylake-Server-IBRS" "-" TYPE_X86_CPU, "pku", "off" },
198ddb3235dSMarc-André Lureau };
199ddb3235dSMarc-André Lureau const size_t pc_compat_3_0_len = G_N_ELEMENTS(pc_compat_3_0);
200ddb3235dSMarc-André Lureau 
2010d47310bSMarc-André Lureau GlobalProperty pc_compat_2_12[] = {
2026c36bddfSEduardo Habkost     { TYPE_X86_CPU, "legacy-cache", "on" },
2036c36bddfSEduardo Habkost     { TYPE_X86_CPU, "topoext", "off" },
2046c36bddfSEduardo Habkost     { "EPYC-" TYPE_X86_CPU, "xlevel", "0x8000000a" },
2056c36bddfSEduardo Habkost     { "EPYC-IBPB-" TYPE_X86_CPU, "xlevel", "0x8000000a" },
2060d47310bSMarc-André Lureau };
2070d47310bSMarc-André Lureau const size_t pc_compat_2_12_len = G_N_ELEMENTS(pc_compat_2_12);
2080d47310bSMarc-André Lureau 
20943df70a9SMarc-André Lureau GlobalProperty pc_compat_2_11[] = {
2106c36bddfSEduardo Habkost     { TYPE_X86_CPU, "x-migrate-smi-count", "off" },
2116c36bddfSEduardo Habkost     { "Skylake-Server" "-" TYPE_X86_CPU, "clflushopt", "off" },
21243df70a9SMarc-André Lureau };
21343df70a9SMarc-André Lureau const size_t pc_compat_2_11_len = G_N_ELEMENTS(pc_compat_2_11);
21443df70a9SMarc-André Lureau 
215503224f4SMarc-André Lureau GlobalProperty pc_compat_2_10[] = {
2166c36bddfSEduardo Habkost     { TYPE_X86_CPU, "x-hv-max-vps", "0x40" },
2176c36bddfSEduardo Habkost     { "i440FX-pcihost", "x-pci-hole64-fix", "off" },
2186c36bddfSEduardo Habkost     { "q35-pcihost", "x-pci-hole64-fix", "off" },
219503224f4SMarc-André Lureau };
220503224f4SMarc-André Lureau const size_t pc_compat_2_10_len = G_N_ELEMENTS(pc_compat_2_10);
221503224f4SMarc-André Lureau 
2223e803152SMarc-André Lureau GlobalProperty pc_compat_2_9[] = {
2236c36bddfSEduardo Habkost     { "mch", "extended-tseg-mbytes", "0" },
2243e803152SMarc-André Lureau };
2253e803152SMarc-André Lureau const size_t pc_compat_2_9_len = G_N_ELEMENTS(pc_compat_2_9);
2263e803152SMarc-André Lureau 
227edc24ccdSMarc-André Lureau GlobalProperty pc_compat_2_8[] = {
2286c36bddfSEduardo Habkost     { TYPE_X86_CPU, "tcg-cpuid", "off" },
2296c36bddfSEduardo Habkost     { "kvmclock", "x-mach-use-reliable-get-clock", "off" },
2306c36bddfSEduardo Habkost     { "ICH9-LPC", "x-smi-broadcast", "off" },
2316c36bddfSEduardo Habkost     { TYPE_X86_CPU, "vmware-cpuid-freq", "off" },
2326c36bddfSEduardo Habkost     { "Haswell-" TYPE_X86_CPU, "stepping", "1" },
233edc24ccdSMarc-André Lureau };
234edc24ccdSMarc-André Lureau const size_t pc_compat_2_8_len = G_N_ELEMENTS(pc_compat_2_8);
235edc24ccdSMarc-André Lureau 
2365a995064SMarc-André Lureau GlobalProperty pc_compat_2_7[] = {
2376c36bddfSEduardo Habkost     { TYPE_X86_CPU, "l3-cache", "off" },
2386c36bddfSEduardo Habkost     { TYPE_X86_CPU, "full-cpuid-auto-level", "off" },
2396c36bddfSEduardo Habkost     { "Opteron_G3" "-" TYPE_X86_CPU, "family", "15" },
2406c36bddfSEduardo Habkost     { "Opteron_G3" "-" TYPE_X86_CPU, "model", "6" },
2416c36bddfSEduardo Habkost     { "Opteron_G3" "-" TYPE_X86_CPU, "stepping", "1" },
2426c36bddfSEduardo Habkost     { "isa-pcspk", "migrate", "off" },
2435a995064SMarc-André Lureau };
2445a995064SMarc-André Lureau const size_t pc_compat_2_7_len = G_N_ELEMENTS(pc_compat_2_7);
2455a995064SMarc-André Lureau 
246ff8f261fSMarc-André Lureau GlobalProperty pc_compat_2_6[] = {
2476c36bddfSEduardo Habkost     { TYPE_X86_CPU, "cpuid-0xb", "off" },
2486c36bddfSEduardo Habkost     { "vmxnet3", "romfile", "" },
2496c36bddfSEduardo Habkost     { TYPE_X86_CPU, "fill-mtrr-mask", "off" },
2506c36bddfSEduardo Habkost     { "apic-common", "legacy-instance-id", "on", }
251ff8f261fSMarc-André Lureau };
252ff8f261fSMarc-André Lureau const size_t pc_compat_2_6_len = G_N_ELEMENTS(pc_compat_2_6);
253ff8f261fSMarc-André Lureau 
254fe759610SMarc-André Lureau GlobalProperty pc_compat_2_5[] = {};
255fe759610SMarc-André Lureau const size_t pc_compat_2_5_len = G_N_ELEMENTS(pc_compat_2_5);
256fe759610SMarc-André Lureau 
2572f99b9c2SMarc-André Lureau GlobalProperty pc_compat_2_4[] = {
2582f99b9c2SMarc-André Lureau     PC_CPU_MODEL_IDS("2.4.0")
2596c36bddfSEduardo Habkost     { "Haswell-" TYPE_X86_CPU, "abm", "off" },
2606c36bddfSEduardo Habkost     { "Haswell-noTSX-" TYPE_X86_CPU, "abm", "off" },
2616c36bddfSEduardo Habkost     { "Broadwell-" TYPE_X86_CPU, "abm", "off" },
2626c36bddfSEduardo Habkost     { "Broadwell-noTSX-" TYPE_X86_CPU, "abm", "off" },
2636c36bddfSEduardo Habkost     { "host" "-" TYPE_X86_CPU, "host-cache-info", "on" },
2646c36bddfSEduardo Habkost     { TYPE_X86_CPU, "check", "off" },
2656c36bddfSEduardo Habkost     { "qemu64" "-" TYPE_X86_CPU, "sse4a", "on" },
2666c36bddfSEduardo Habkost     { "qemu64" "-" TYPE_X86_CPU, "abm", "on" },
2676c36bddfSEduardo Habkost     { "qemu64" "-" TYPE_X86_CPU, "popcnt", "on" },
2686c36bddfSEduardo Habkost     { "qemu32" "-" TYPE_X86_CPU, "popcnt", "on" },
2696c36bddfSEduardo Habkost     { "Opteron_G2" "-" TYPE_X86_CPU, "rdtscp", "on" },
2706c36bddfSEduardo Habkost     { "Opteron_G3" "-" TYPE_X86_CPU, "rdtscp", "on" },
2716c36bddfSEduardo Habkost     { "Opteron_G4" "-" TYPE_X86_CPU, "rdtscp", "on" },
2726c36bddfSEduardo Habkost     { "Opteron_G5" "-" TYPE_X86_CPU, "rdtscp", "on", }
2732f99b9c2SMarc-André Lureau };
2742f99b9c2SMarc-André Lureau const size_t pc_compat_2_4_len = G_N_ELEMENTS(pc_compat_2_4);
2752f99b9c2SMarc-André Lureau 
276e6115657SPhilippe Mathieu-Daudé /*
277e6115657SPhilippe Mathieu-Daudé  * @PC_FW_DATA:
278e6115657SPhilippe Mathieu-Daudé  * Size of the chunk of memory at the top of RAM for the BIOS ACPI tables
279e6115657SPhilippe Mathieu-Daudé  * and other BIOS datastructures.
280e6115657SPhilippe Mathieu-Daudé  *
281e6115657SPhilippe Mathieu-Daudé  * BIOS ACPI tables: 128K. Other BIOS datastructures: less than 4K
282e6115657SPhilippe Mathieu-Daudé  * reported to be used at the moment, 32K should be enough for a while.
283e6115657SPhilippe Mathieu-Daudé  */
284e6115657SPhilippe Mathieu-Daudé #define PC_FW_DATA (0x20000 + 0x8000)
285e6115657SPhilippe Mathieu-Daudé 
pc_gsi_create(qemu_irq ** irqs,bool pci_enabled)286417258f1SPhilippe Mathieu-Daudé GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled)
287417258f1SPhilippe Mathieu-Daudé {
288417258f1SPhilippe Mathieu-Daudé     GSIState *s;
289417258f1SPhilippe Mathieu-Daudé 
290417258f1SPhilippe Mathieu-Daudé     s = g_new0(GSIState, 1);
291417258f1SPhilippe Mathieu-Daudé     if (kvm_ioapic_in_kernel()) {
292417258f1SPhilippe Mathieu-Daudé         kvm_pc_setup_irq_routing(pci_enabled);
293417258f1SPhilippe Mathieu-Daudé     }
294e3e3a8adSBernhard Beschow     *irqs = qemu_allocate_irqs(gsi_handler, s, IOAPIC_NUM_PINS);
295417258f1SPhilippe Mathieu-Daudé 
296417258f1SPhilippe Mathieu-Daudé     return s;
297417258f1SPhilippe Mathieu-Daudé }
298417258f1SPhilippe Mathieu-Daudé 
ioport80_write(void * opaque,hwaddr addr,uint64_t data,unsigned size)29953018216SPaolo Bonzini static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
30053018216SPaolo Bonzini                            unsigned size)
30153018216SPaolo Bonzini {
30253018216SPaolo Bonzini }
30353018216SPaolo Bonzini 
ioport80_read(void * opaque,hwaddr addr,unsigned size)30453018216SPaolo Bonzini static uint64_t ioport80_read(void *opaque, hwaddr addr, unsigned size)
30553018216SPaolo Bonzini {
30653018216SPaolo Bonzini     return 0xffffffffffffffffULL;
30753018216SPaolo Bonzini }
30853018216SPaolo Bonzini 
309bad5cfcdSMichael Tokarev /* MS-DOS compatibility mode FPU exception support */
ioportF0_write(void * opaque,hwaddr addr,uint64_t data,unsigned size)31053018216SPaolo Bonzini static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
31153018216SPaolo Bonzini                            unsigned size)
31253018216SPaolo Bonzini {
3136f529b75SPaolo Bonzini     if (tcg_enabled()) {
314bf13bfabSPaolo Bonzini         cpu_set_ignne();
3156f529b75SPaolo Bonzini     }
31653018216SPaolo Bonzini }
31753018216SPaolo Bonzini 
ioportF0_read(void * opaque,hwaddr addr,unsigned size)31853018216SPaolo Bonzini static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size)
31953018216SPaolo Bonzini {
32053018216SPaolo Bonzini     return 0xffffffffffffffffULL;
32153018216SPaolo Bonzini }
32253018216SPaolo Bonzini 
32353018216SPaolo Bonzini /* PC cmos mappings */
32453018216SPaolo Bonzini 
32553018216SPaolo Bonzini #define REG_EQUIPMENT_BYTE          0x14
32653018216SPaolo Bonzini 
cmos_init_hd(MC146818RtcState * s,int type_ofs,int info_ofs,int16_t cylinders,int8_t heads,int8_t sectors)32755c86cb8SPhilippe Mathieu-Daudé static void cmos_init_hd(MC146818RtcState *s, int type_ofs, int info_ofs,
32853018216SPaolo Bonzini                          int16_t cylinders, int8_t heads, int8_t sectors)
32953018216SPaolo Bonzini {
3302d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, type_ofs, 47);
3312d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, info_ofs, cylinders);
3322d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, info_ofs + 1, cylinders >> 8);
3332d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, info_ofs + 2, heads);
3342d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, info_ofs + 3, 0xff);
3352d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, info_ofs + 4, 0xff);
3362d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
3372d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, info_ofs + 6, cylinders);
3382d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, info_ofs + 7, cylinders >> 8);
3392d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, info_ofs + 8, sectors);
34053018216SPaolo Bonzini }
34153018216SPaolo Bonzini 
34253018216SPaolo Bonzini /* convert boot_device letter to something recognizable by the bios */
boot_device2nibble(char boot_device)34353018216SPaolo Bonzini static int boot_device2nibble(char boot_device)
34453018216SPaolo Bonzini {
34553018216SPaolo Bonzini     switch(boot_device) {
34653018216SPaolo Bonzini     case 'a':
34753018216SPaolo Bonzini     case 'b':
34853018216SPaolo Bonzini         return 0x01; /* floppy boot */
34953018216SPaolo Bonzini     case 'c':
35053018216SPaolo Bonzini         return 0x02; /* hard drive boot */
35153018216SPaolo Bonzini     case 'd':
35253018216SPaolo Bonzini         return 0x03; /* CD-ROM boot */
35353018216SPaolo Bonzini     case 'n':
35453018216SPaolo Bonzini         return 0x04; /* Network boot */
35553018216SPaolo Bonzini     }
35653018216SPaolo Bonzini     return 0;
35753018216SPaolo Bonzini }
35853018216SPaolo Bonzini 
set_boot_dev(PCMachineState * pcms,MC146818RtcState * s,const char * boot_device,Error ** errp)35984e945aaSPaolo Bonzini static void set_boot_dev(PCMachineState *pcms, MC146818RtcState *s,
36084e945aaSPaolo Bonzini                          const char *boot_device, Error **errp)
36153018216SPaolo Bonzini {
36253018216SPaolo Bonzini #define PC_MAX_BOOT_DEVICES 3
36353018216SPaolo Bonzini     int nbds, bds[3] = { 0, };
36453018216SPaolo Bonzini     int i;
36553018216SPaolo Bonzini 
36653018216SPaolo Bonzini     nbds = strlen(boot_device);
36753018216SPaolo Bonzini     if (nbds > PC_MAX_BOOT_DEVICES) {
368ddcd5531SGonglei         error_setg(errp, "Too many boot devices for PC");
369ddcd5531SGonglei         return;
37053018216SPaolo Bonzini     }
37153018216SPaolo Bonzini     for (i = 0; i < nbds; i++) {
37253018216SPaolo Bonzini         bds[i] = boot_device2nibble(boot_device[i]);
37353018216SPaolo Bonzini         if (bds[i] == 0) {
374ddcd5531SGonglei             error_setg(errp, "Invalid boot device for PC: '%c'",
37553018216SPaolo Bonzini                        boot_device[i]);
376ddcd5531SGonglei             return;
37753018216SPaolo Bonzini         }
37853018216SPaolo Bonzini     }
3792d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x3d, (bds[1] << 4) | bds[0]);
38084e945aaSPaolo Bonzini     mc146818rtc_set_cmos_data(s, 0x38, (bds[2] << 4) | !pcms->fd_bootchk);
38153018216SPaolo Bonzini }
38253018216SPaolo Bonzini 
pc_boot_set(void * opaque,const char * boot_device,Error ** errp)383ddcd5531SGonglei static void pc_boot_set(void *opaque, const char *boot_device, Error **errp)
38453018216SPaolo Bonzini {
3856605d097SBernhard Beschow     PCMachineState *pcms = opaque;
3866605d097SBernhard Beschow     X86MachineState *x86ms = X86_MACHINE(pcms);
38784e945aaSPaolo Bonzini 
3886605d097SBernhard Beschow     set_boot_dev(pcms, MC146818_RTC(x86ms->rtc), boot_device, errp);
38953018216SPaolo Bonzini }
39053018216SPaolo Bonzini 
pc_cmos_init_floppy(MC146818RtcState * rtc_state,ISADevice * floppy)39155c86cb8SPhilippe Mathieu-Daudé static void pc_cmos_init_floppy(MC146818RtcState *rtc_state, ISADevice *floppy)
3927444ca4eSLaszlo Ersek {
39364436c5cSThomas Huth     int val, nb;
3942da44dd0SJohn Snow     FloppyDriveType fd_type[2] = { FLOPPY_DRIVE_TYPE_NONE,
3952da44dd0SJohn Snow                                    FLOPPY_DRIVE_TYPE_NONE };
3967444ca4eSLaszlo Ersek 
39764436c5cSThomas Huth #ifdef CONFIG_FDC_ISA
3987444ca4eSLaszlo Ersek     /* floppy type */
3997444ca4eSLaszlo Ersek     if (floppy) {
40064436c5cSThomas Huth         for (int i = 0; i < 2; i++) {
4017444ca4eSLaszlo Ersek             fd_type[i] = isa_fdc_get_drive_type(floppy, i);
4027444ca4eSLaszlo Ersek         }
4037444ca4eSLaszlo Ersek     }
40464436c5cSThomas Huth #endif
40564436c5cSThomas Huth 
4067444ca4eSLaszlo Ersek     val = (cmos_get_fd_drive_type(fd_type[0]) << 4) |
4077444ca4eSLaszlo Ersek         cmos_get_fd_drive_type(fd_type[1]);
4082d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(rtc_state, 0x10, val);
4097444ca4eSLaszlo Ersek 
4102d4bd81eSPhilippe Mathieu-Daudé     val = mc146818rtc_get_cmos_data(rtc_state, REG_EQUIPMENT_BYTE);
4117444ca4eSLaszlo Ersek     nb = 0;
4122da44dd0SJohn Snow     if (fd_type[0] != FLOPPY_DRIVE_TYPE_NONE) {
4137444ca4eSLaszlo Ersek         nb++;
4147444ca4eSLaszlo Ersek     }
4152da44dd0SJohn Snow     if (fd_type[1] != FLOPPY_DRIVE_TYPE_NONE) {
4167444ca4eSLaszlo Ersek         nb++;
4177444ca4eSLaszlo Ersek     }
4187444ca4eSLaszlo Ersek     switch (nb) {
4197444ca4eSLaszlo Ersek     case 0:
4207444ca4eSLaszlo Ersek         break;
4217444ca4eSLaszlo Ersek     case 1:
4227444ca4eSLaszlo Ersek         val |= 0x01; /* 1 drive, ready for boot */
4237444ca4eSLaszlo Ersek         break;
4247444ca4eSLaszlo Ersek     case 2:
4257444ca4eSLaszlo Ersek         val |= 0x41; /* 2 drives, ready for boot */
4267444ca4eSLaszlo Ersek         break;
4277444ca4eSLaszlo Ersek     }
4282d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(rtc_state, REG_EQUIPMENT_BYTE, val);
4297444ca4eSLaszlo Ersek }
4307444ca4eSLaszlo Ersek 
431b86f4613SLaszlo Ersek typedef struct check_fdc_state {
432b86f4613SLaszlo Ersek     ISADevice *floppy;
433b86f4613SLaszlo Ersek     bool multiple;
434b86f4613SLaszlo Ersek } CheckFdcState;
435b86f4613SLaszlo Ersek 
check_fdc(Object * obj,void * opaque)436b86f4613SLaszlo Ersek static int check_fdc(Object *obj, void *opaque)
437b86f4613SLaszlo Ersek {
438b86f4613SLaszlo Ersek     CheckFdcState *state = opaque;
439b86f4613SLaszlo Ersek     Object *fdc;
440b86f4613SLaszlo Ersek     uint32_t iobase;
441b86f4613SLaszlo Ersek     Error *local_err = NULL;
442b86f4613SLaszlo Ersek 
443b86f4613SLaszlo Ersek     fdc = object_dynamic_cast(obj, TYPE_ISA_FDC);
444b86f4613SLaszlo Ersek     if (!fdc) {
445b86f4613SLaszlo Ersek         return 0;
446b86f4613SLaszlo Ersek     }
447b86f4613SLaszlo Ersek 
4481ea1572aSMarc-André Lureau     iobase = object_property_get_uint(obj, "iobase", &local_err);
449b86f4613SLaszlo Ersek     if (local_err || iobase != 0x3f0) {
450b86f4613SLaszlo Ersek         error_free(local_err);
451b86f4613SLaszlo Ersek         return 0;
452b86f4613SLaszlo Ersek     }
453b86f4613SLaszlo Ersek 
454b86f4613SLaszlo Ersek     if (state->floppy) {
455b86f4613SLaszlo Ersek         state->multiple = true;
456b86f4613SLaszlo Ersek     } else {
457b86f4613SLaszlo Ersek         state->floppy = ISA_DEVICE(obj);
458b86f4613SLaszlo Ersek     }
459b86f4613SLaszlo Ersek     return 0;
460b86f4613SLaszlo Ersek }
461b86f4613SLaszlo Ersek 
462b86f4613SLaszlo Ersek static const char * const fdc_container_path[] = {
463b86f4613SLaszlo Ersek     "/unattached", "/peripheral", "/peripheral-anon"
464b86f4613SLaszlo Ersek };
465b86f4613SLaszlo Ersek 
466424e4a87SRoman Kagan /*
467424e4a87SRoman Kagan  * Locate the FDC at IO address 0x3f0, in order to configure the CMOS registers
468424e4a87SRoman Kagan  * and ACPI objects.
469424e4a87SRoman Kagan  */
pc_find_fdc0(void)470cb76321eSBernhard Beschow static ISADevice *pc_find_fdc0(void)
471424e4a87SRoman Kagan {
472424e4a87SRoman Kagan     int i;
473424e4a87SRoman Kagan     Object *container;
474424e4a87SRoman Kagan     CheckFdcState state = { 0 };
475424e4a87SRoman Kagan 
476424e4a87SRoman Kagan     for (i = 0; i < ARRAY_SIZE(fdc_container_path); i++) {
477424e4a87SRoman Kagan         container = container_get(qdev_get_machine(), fdc_container_path[i]);
478424e4a87SRoman Kagan         object_child_foreach(container, check_fdc, &state);
479424e4a87SRoman Kagan     }
480424e4a87SRoman Kagan 
481424e4a87SRoman Kagan     if (state.multiple) {
4823dc6f869SAlistair Francis         warn_report("multiple floppy disk controllers with "
483433672b0SMarkus Armbruster                     "iobase=0x3f0 have been found");
484433672b0SMarkus Armbruster         error_printf("the one being picked for CMOS setup might not reflect "
4859e5d2c52SAlistair Francis                      "your intent");
486424e4a87SRoman Kagan     }
487424e4a87SRoman Kagan 
488424e4a87SRoman Kagan     return state.floppy;
489424e4a87SRoman Kagan }
490424e4a87SRoman Kagan 
pc_cmos_init_late(PCMachineState * pcms)491859eb5eeSPeter Maydell static void pc_cmos_init_late(PCMachineState *pcms)
49253018216SPaolo Bonzini {
493859eb5eeSPeter Maydell     X86MachineState *x86ms = X86_MACHINE(pcms);
494859eb5eeSPeter Maydell     MC146818RtcState *s = MC146818_RTC(x86ms->rtc);
49553018216SPaolo Bonzini     int16_t cylinders;
49653018216SPaolo Bonzini     int8_t heads, sectors;
49753018216SPaolo Bonzini     int val;
49853018216SPaolo Bonzini     int i, trans;
49953018216SPaolo Bonzini 
50053018216SPaolo Bonzini     val = 0;
501859eb5eeSPeter Maydell     if (pcms->idebus[0] &&
502859eb5eeSPeter Maydell         ide_get_geometry(pcms->idebus[0], 0,
50353018216SPaolo Bonzini                          &cylinders, &heads, &sectors) >= 0) {
50453018216SPaolo Bonzini         cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors);
50553018216SPaolo Bonzini         val |= 0xf0;
50653018216SPaolo Bonzini     }
507859eb5eeSPeter Maydell     if (pcms->idebus[0] &&
508859eb5eeSPeter Maydell         ide_get_geometry(pcms->idebus[0], 1,
50953018216SPaolo Bonzini                          &cylinders, &heads, &sectors) >= 0) {
51053018216SPaolo Bonzini         cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors);
51153018216SPaolo Bonzini         val |= 0x0f;
51253018216SPaolo Bonzini     }
5132d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x12, val);
51453018216SPaolo Bonzini 
51553018216SPaolo Bonzini     val = 0;
51653018216SPaolo Bonzini     for (i = 0; i < 4; i++) {
51753018216SPaolo Bonzini         /* NOTE: ide_get_geometry() returns the physical
51853018216SPaolo Bonzini            geometry.  It is always such that: 1 <= sects <= 63, 1
51953018216SPaolo Bonzini            <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
52053018216SPaolo Bonzini            geometry can be different if a translation is done. */
521859eb5eeSPeter Maydell         BusState *idebus = pcms->idebus[i / 2];
522859eb5eeSPeter Maydell         if (idebus &&
523859eb5eeSPeter Maydell             ide_get_geometry(idebus, i % 2,
52453018216SPaolo Bonzini                              &cylinders, &heads, &sectors) >= 0) {
525859eb5eeSPeter Maydell             trans = ide_get_bios_chs_trans(idebus, i % 2) - 1;
52653018216SPaolo Bonzini             assert((trans & ~3) == 0);
52753018216SPaolo Bonzini             val |= trans << (i * 2);
52853018216SPaolo Bonzini         }
52953018216SPaolo Bonzini     }
5302d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x39, val);
53153018216SPaolo Bonzini 
532424e4a87SRoman Kagan     pc_cmos_init_floppy(s, pc_find_fdc0());
53353018216SPaolo Bonzini 
53453018216SPaolo Bonzini     /* various important CMOS locations needed by PC/Bochs bios */
53553018216SPaolo Bonzini 
53653018216SPaolo Bonzini     /* memory size */
53753018216SPaolo Bonzini     /* base memory (first MiB) */
538f0bb276bSPaolo Bonzini     val = MIN(x86ms->below_4g_mem_size / KiB, 640);
5392d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x15, val);
5402d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x16, val >> 8);
54153018216SPaolo Bonzini     /* extended memory (next 64MiB) */
542f0bb276bSPaolo Bonzini     if (x86ms->below_4g_mem_size > 1 * MiB) {
543f0bb276bSPaolo Bonzini         val = (x86ms->below_4g_mem_size - 1 * MiB) / KiB;
54453018216SPaolo Bonzini     } else {
54553018216SPaolo Bonzini         val = 0;
54653018216SPaolo Bonzini     }
54753018216SPaolo Bonzini     if (val > 65535)
54853018216SPaolo Bonzini         val = 65535;
5492d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x17, val);
5502d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x18, val >> 8);
5512d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x30, val);
5522d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x31, val >> 8);
55353018216SPaolo Bonzini     /* memory between 16MiB and 4GiB */
554f0bb276bSPaolo Bonzini     if (x86ms->below_4g_mem_size > 16 * MiB) {
555f0bb276bSPaolo Bonzini         val = (x86ms->below_4g_mem_size - 16 * MiB) / (64 * KiB);
55653018216SPaolo Bonzini     } else {
55753018216SPaolo Bonzini         val = 0;
55853018216SPaolo Bonzini     }
55953018216SPaolo Bonzini     if (val > 65535)
56053018216SPaolo Bonzini         val = 65535;
5612d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x34, val);
5622d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x35, val >> 8);
56353018216SPaolo Bonzini     /* memory above 4GiB */
564f0bb276bSPaolo Bonzini     val = x86ms->above_4g_mem_size / 65536;
5652d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x5b, val);
5662d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x5c, val >> 8);
5672d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, 0x5d, val >> 16);
56853018216SPaolo Bonzini 
56953018216SPaolo Bonzini     val = 0;
57053018216SPaolo Bonzini     val |= 0x02; /* FPU is there */
57153018216SPaolo Bonzini     val |= 0x04; /* PS/2 mouse installed */
5722d4bd81eSPhilippe Mathieu-Daudé     mc146818rtc_set_cmos_data(s, REG_EQUIPMENT_BYTE, val);
57353018216SPaolo Bonzini }
57453018216SPaolo Bonzini 
handle_a20_line_change(void * opaque,int irq,int level)57553018216SPaolo Bonzini static void handle_a20_line_change(void *opaque, int irq, int level)
57653018216SPaolo Bonzini {
57753018216SPaolo Bonzini     X86CPU *cpu = opaque;
57853018216SPaolo Bonzini 
57953018216SPaolo Bonzini     /* XXX: send to all CPUs ? */
58053018216SPaolo Bonzini     /* XXX: add logic to handle multiple A20 line sources */
58153018216SPaolo Bonzini     x86_cpu_set_a20(cpu, level);
58253018216SPaolo Bonzini }
58353018216SPaolo Bonzini 
58453018216SPaolo Bonzini #define NE2000_NB_MAX 6
58553018216SPaolo Bonzini 
58653018216SPaolo Bonzini static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
58753018216SPaolo Bonzini                                               0x280, 0x380 };
58853018216SPaolo Bonzini static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
58953018216SPaolo Bonzini 
pc_init_ne2k_isa(ISABus * bus,NICInfo * nd,Error ** errp)5908d39f9baSDavid Woodhouse static gboolean pc_init_ne2k_isa(ISABus *bus, NICInfo *nd, Error **errp)
59153018216SPaolo Bonzini {
59253018216SPaolo Bonzini     static int nb_ne2k = 0;
59353018216SPaolo Bonzini 
5948d39f9baSDavid Woodhouse     if (nb_ne2k == NE2000_NB_MAX) {
5958d39f9baSDavid Woodhouse         error_setg(errp,
5968d39f9baSDavid Woodhouse                    "maximum number of ISA NE2000 devices exceeded");
5978d39f9baSDavid Woodhouse         return false;
5988d39f9baSDavid Woodhouse     }
59953018216SPaolo Bonzini     isa_ne2000_init(bus, ne2000_io[nb_ne2k],
60053018216SPaolo Bonzini                     ne2000_irq[nb_ne2k], nd);
60153018216SPaolo Bonzini     nb_ne2k++;
6028d39f9baSDavid Woodhouse     return true;
60353018216SPaolo Bonzini }
60453018216SPaolo Bonzini 
pc_acpi_smi_interrupt(void * opaque,int irq,int level)60553018216SPaolo Bonzini void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
60653018216SPaolo Bonzini {
607c3affe56SAndreas Färber     X86CPU *cpu = opaque;
60853018216SPaolo Bonzini 
60953018216SPaolo Bonzini     if (level) {
610c3affe56SAndreas Färber         cpu_interrupt(CPU(cpu), CPU_INTERRUPT_SMI);
61153018216SPaolo Bonzini     }
61253018216SPaolo Bonzini }
61353018216SPaolo Bonzini 
6143459a625SMichael S. Tsirkin static
pc_machine_done(Notifier * notifier,void * data)6159ebeed0cSEduardo Habkost void pc_machine_done(Notifier *notifier, void *data)
6163459a625SMichael S. Tsirkin {
6179ebeed0cSEduardo Habkost     PCMachineState *pcms = container_of(notifier,
6189ebeed0cSEduardo Habkost                                         PCMachineState, machine_done);
619f0bb276bSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(pcms);
620dab390ffSJonathan Cameron 
621b54a9d46SBernhard Beschow     cxl_hook_up_pxb_registers(pcms->pcibus, &pcms->cxl_devices_state,
6227bd1900bSJonathan Cameron                               &error_fatal);
6231ebf9001SJonathan Cameron 
6241ebf9001SJonathan Cameron     if (pcms->cxl_devices_state.is_enabled) {
6251ebf9001SJonathan Cameron         cxl_fmws_link_targets(&pcms->cxl_devices_state, &error_fatal);
626dab390ffSJonathan Cameron     }
6272118196bSMarcel Apfelbaum 
628ba157b69SIgor Mammedov     /* set the number of CPUs */
6290cca1a91SGerd Hoffmann     x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus);
630ba157b69SIgor Mammedov 
631b54a9d46SBernhard Beschow     fw_cfg_add_extra_pci_roots(pcms->pcibus, x86ms->fw_cfg);
6322118196bSMarcel Apfelbaum 
633bb292f5aSEduardo Habkost     acpi_setup();
634f0bb276bSPaolo Bonzini     if (x86ms->fw_cfg) {
63569ea07a5SIgor Mammedov         fw_cfg_build_smbios(pcms, x86ms->fw_cfg, pcms->smbios_entry_point_type);
63693c76555SDavid Woodhouse         fw_cfg_add_e820(x86ms->fw_cfg);
637f0bb276bSPaolo Bonzini         fw_cfg_build_feature_control(MACHINE(pcms), x86ms->fw_cfg);
638e3cadac0SIgor Mammedov         /* update FW_CFG_NB_CPUS to account for -device added CPUs */
639f0bb276bSPaolo Bonzini         fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus);
6406d42eefaSCorey Minyard     }
641859eb5eeSPeter Maydell 
642859eb5eeSPeter Maydell     pc_cmos_init_late(pcms);
64360c5e104SIgor Mammedov }
6443459a625SMichael S. Tsirkin 
64583d08f26SMichael S. Tsirkin /* setup pci memory address space mapping into system address space */
pc_pci_as_mapping_init(MemoryRegion * system_memory,MemoryRegion * pci_address_space)64609aa7be1SPhilippe Mathieu-Daudé void pc_pci_as_mapping_init(MemoryRegion *system_memory,
64783d08f26SMichael S. Tsirkin                             MemoryRegion *pci_address_space)
64839848901SIgor Mammedov {
64983d08f26SMichael S. Tsirkin     /* Set to lower priority than RAM */
65083d08f26SMichael S. Tsirkin     memory_region_add_subregion_overlap(system_memory, 0x0,
65183d08f26SMichael S. Tsirkin                                         pci_address_space, -1);
6523459a625SMichael S. Tsirkin }
6533459a625SMichael S. Tsirkin 
xen_load_linux(PCMachineState * pcms)6547bc35e0fSEduardo Habkost void xen_load_linux(PCMachineState *pcms)
655b33a5bbfSChunyan Liu {
656b33a5bbfSChunyan Liu     int i;
657b33a5bbfSChunyan Liu     FWCfgState *fw_cfg;
658703a548aSSergio Lopez     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
659f0bb276bSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(pcms);
660b33a5bbfSChunyan Liu 
661df1f79fdSEduardo Habkost     assert(MACHINE(pcms)->kernel_filename != NULL);
662b33a5bbfSChunyan Liu 
663918a7f70SMarek Marczykowski-Górecki     fw_cfg = fw_cfg_init_io_dma(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4,
664918a7f70SMarek Marczykowski-Górecki                                 &address_space_memory);
665f0bb276bSPaolo Bonzini     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus);
666b33a5bbfSChunyan Liu     rom_set_fw(fw_cfg);
667b33a5bbfSChunyan Liu 
668e6115657SPhilippe Mathieu-Daudé     x86_load_linux(x86ms, fw_cfg, PC_FW_DATA, pcmc->pvh_enabled);
669b33a5bbfSChunyan Liu     for (i = 0; i < nb_option_roms; i++) {
670b33a5bbfSChunyan Liu         assert(!strcmp(option_rom[i].name, "linuxboot.bin") ||
671b2a575a1SMarc Marí                !strcmp(option_rom[i].name, "linuxboot_dma.bin") ||
6721fb0d709SStefano Garzarella                !strcmp(option_rom[i].name, "pvh.bin") ||
6733ca8ce72SPaolo Bonzini                !strcmp(option_rom[i].name, "multiboot.bin") ||
6743ca8ce72SPaolo Bonzini                !strcmp(option_rom[i].name, "multiboot_dma.bin"));
675b33a5bbfSChunyan Liu         rom_add_option(option_rom[i].name, option_rom[i].bootindex);
676b33a5bbfSChunyan Liu     }
677f0bb276bSPaolo Bonzini     x86ms->fw_cfg = fw_cfg;
678b33a5bbfSChunyan Liu }
679b33a5bbfSChunyan Liu 
68072686c58SPhilippe Mathieu-Daudé #define PC_ROM_MIN_VGA     0xc0000
68172686c58SPhilippe Mathieu-Daudé #define PC_ROM_MIN_OPTION  0xc8000
68272686c58SPhilippe Mathieu-Daudé #define PC_ROM_MAX         0xe0000
68372686c58SPhilippe Mathieu-Daudé #define PC_ROM_ALIGN       0x800
68472686c58SPhilippe Mathieu-Daudé #define PC_ROM_SIZE        (PC_ROM_MAX - PC_ROM_MIN_VGA)
68572686c58SPhilippe Mathieu-Daudé 
pc_above_4g_end(PCMachineState * pcms)6865ff62e2aSJoao Martins static hwaddr pc_above_4g_end(PCMachineState *pcms)
6875ff62e2aSJoao Martins {
6885ff62e2aSJoao Martins     X86MachineState *x86ms = X86_MACHINE(pcms);
6895ff62e2aSJoao Martins 
6905ff62e2aSJoao Martins     if (pcms->sgx_epc.size != 0) {
6915ff62e2aSJoao Martins         return sgx_epc_above_4g_end(&pcms->sgx_epc);
6925ff62e2aSJoao Martins     }
6935ff62e2aSJoao Martins 
6945ff62e2aSJoao Martins     return x86ms->above_4g_mem_start + x86ms->above_4g_mem_size;
6955ff62e2aSJoao Martins }
6965ff62e2aSJoao Martins 
pc_get_device_memory_range(PCMachineState * pcms,hwaddr * base,ram_addr_t * device_mem_size)6978288a828SJoao Martins static void pc_get_device_memory_range(PCMachineState *pcms,
6988288a828SJoao Martins                                        hwaddr *base,
6998288a828SJoao Martins                                        ram_addr_t *device_mem_size)
70042bed071SJoao Martins {
70142bed071SJoao Martins     MachineState *machine = MACHINE(pcms);
7028288a828SJoao Martins     ram_addr_t size;
7038288a828SJoao Martins     hwaddr addr;
70442bed071SJoao Martins 
7058288a828SJoao Martins     size = machine->maxram_size - machine->ram_size;
7068288a828SJoao Martins     addr = ROUND_UP(pc_above_4g_end(pcms), 1 * GiB);
7078288a828SJoao Martins 
7088288a828SJoao Martins     /* size device region assuming 1G page max alignment per slot */
7098288a828SJoao Martins     size += (1 * GiB) * machine->ram_slots;
7108288a828SJoao Martins 
7118288a828SJoao Martins     *base = addr;
7128288a828SJoao Martins     *device_mem_size = size;
7138288a828SJoao Martins }
7148288a828SJoao Martins 
pc_get_cxl_range_start(PCMachineState * pcms)7158288a828SJoao Martins static uint64_t pc_get_cxl_range_start(PCMachineState *pcms)
7168288a828SJoao Martins {
7178288a828SJoao Martins     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
7184076bc86SAni Sinha     MachineState *ms = MACHINE(pcms);
7198288a828SJoao Martins     hwaddr cxl_base;
7208288a828SJoao Martins     ram_addr_t size;
7218288a828SJoao Martins 
7224076bc86SAni Sinha     if (pcmc->has_reserved_memory &&
7234076bc86SAni Sinha         (ms->ram_size < ms->maxram_size)) {
7248288a828SJoao Martins         pc_get_device_memory_range(pcms, &cxl_base, &size);
7258288a828SJoao Martins         cxl_base += size;
72642bed071SJoao Martins     } else {
72742bed071SJoao Martins         cxl_base = pc_above_4g_end(pcms);
72842bed071SJoao Martins     }
72942bed071SJoao Martins 
73042bed071SJoao Martins     return cxl_base;
73142bed071SJoao Martins }
73242bed071SJoao Martins 
pc_get_cxl_range_end(PCMachineState * pcms)73355668e40SJoao Martins static uint64_t pc_get_cxl_range_end(PCMachineState *pcms)
73455668e40SJoao Martins {
7351065b219SJoao Martins     uint64_t start = pc_get_cxl_range_start(pcms) + MiB;
73655668e40SJoao Martins 
73755668e40SJoao Martins     if (pcms->cxl_devices_state.fixed_windows) {
73855668e40SJoao Martins         GList *it;
7391065b219SJoao Martins 
7401065b219SJoao Martins         start = ROUND_UP(start, 256 * MiB);
74155668e40SJoao Martins         for (it = pcms->cxl_devices_state.fixed_windows; it; it = it->next) {
74255668e40SJoao Martins             CXLFixedWindow *fw = it->data;
7431065b219SJoao Martins             start += fw->size;
74455668e40SJoao Martins         }
74555668e40SJoao Martins     }
74655668e40SJoao Martins 
74755668e40SJoao Martins     return start;
74855668e40SJoao Martins }
74955668e40SJoao Martins 
pc_max_used_gpa(PCMachineState * pcms,uint64_t pci_hole64_size)7501caab5cfSJoao Martins static hwaddr pc_max_used_gpa(PCMachineState *pcms, uint64_t pci_hole64_size)
7511caab5cfSJoao Martins {
7521caab5cfSJoao Martins     X86CPU *cpu = X86_CPU(first_cpu);
753cf038650SAni Sinha     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
754cf038650SAni Sinha     MachineState *ms = MACHINE(pcms);
7551caab5cfSJoao Martins 
756cf038650SAni Sinha     if (cpu->env.features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
757cf038650SAni Sinha         /* 64-bit systems */
758cf038650SAni Sinha         return pc_pci_hole64_start() + pci_hole64_size - 1;
759cf038650SAni Sinha     }
760cf038650SAni Sinha 
761cf038650SAni Sinha     /* 32-bit systems */
762cf038650SAni Sinha     if (pcmc->broken_32bit_mem_addr_check) {
763cf038650SAni Sinha         /* old value for compatibility reasons */
7641caab5cfSJoao Martins         return ((hwaddr)1 << cpu->phys_bits) - 1;
7651caab5cfSJoao Martins     }
7661caab5cfSJoao Martins 
767cf038650SAni Sinha     /*
768cf038650SAni Sinha      * 32-bit systems don't have hole64 but they might have a region for
769cf038650SAni Sinha      * memory devices. Even if additional hotplugged memory devices might
770cf038650SAni Sinha      * not be usable by most guest OSes, we need to still consider them for
771cf038650SAni Sinha      * calculating the highest possible GPA so that we can properly report
772cf038650SAni Sinha      * if someone configures them on a CPU that cannot possibly address them.
773cf038650SAni Sinha      */
774cf038650SAni Sinha     if (pcmc->has_reserved_memory &&
775cf038650SAni Sinha         (ms->ram_size < ms->maxram_size)) {
776cf038650SAni Sinha         hwaddr devmem_start;
777cf038650SAni Sinha         ram_addr_t devmem_size;
778cf038650SAni Sinha 
779cf038650SAni Sinha         pc_get_device_memory_range(pcms, &devmem_start, &devmem_size);
780cf038650SAni Sinha         devmem_start += devmem_size;
781cf038650SAni Sinha         return devmem_start - 1;
782cf038650SAni Sinha     }
783cf038650SAni Sinha 
784cf038650SAni Sinha     /* configuration without any memory hotplug */
785cf038650SAni Sinha     return pc_above_4g_end(pcms) - 1;
7861caab5cfSJoao Martins }
7871caab5cfSJoao Martins 
7888504f129SJoao Martins /*
7898504f129SJoao Martins  * AMD systems with an IOMMU have an additional hole close to the
7908504f129SJoao Martins  * 1Tb, which are special GPAs that cannot be DMA mapped. Depending
7918504f129SJoao Martins  * on kernel version, VFIO may or may not let you DMA map those ranges.
7928504f129SJoao Martins  * Starting Linux v5.4 we validate it, and can't create guests on AMD machines
7938504f129SJoao Martins  * with certain memory sizes. It's also wrong to use those IOVA ranges
7948504f129SJoao Martins  * in detriment of leading to IOMMU INVALID_DEVICE_REQUEST or worse.
7958504f129SJoao Martins  * The ranges reserved for Hyper-Transport are:
7968504f129SJoao Martins  *
7978504f129SJoao Martins  * FD_0000_0000h - FF_FFFF_FFFFh
7988504f129SJoao Martins  *
7998504f129SJoao Martins  * The ranges represent the following:
8008504f129SJoao Martins  *
8018504f129SJoao Martins  * Base Address   Top Address  Use
8028504f129SJoao Martins  *
8038504f129SJoao Martins  * FD_0000_0000h FD_F7FF_FFFFh Reserved interrupt address space
8048504f129SJoao Martins  * FD_F800_0000h FD_F8FF_FFFFh Interrupt/EOI IntCtl
8058504f129SJoao Martins  * FD_F900_0000h FD_F90F_FFFFh Legacy PIC IACK
8068504f129SJoao Martins  * FD_F910_0000h FD_F91F_FFFFh System Management
8078504f129SJoao Martins  * FD_F920_0000h FD_FAFF_FFFFh Reserved Page Tables
8088504f129SJoao Martins  * FD_FB00_0000h FD_FBFF_FFFFh Address Translation
8098504f129SJoao Martins  * FD_FC00_0000h FD_FDFF_FFFFh I/O Space
8108504f129SJoao Martins  * FD_FE00_0000h FD_FFFF_FFFFh Configuration
8118504f129SJoao Martins  * FE_0000_0000h FE_1FFF_FFFFh Extended Configuration/Device Messages
8128504f129SJoao Martins  * FE_2000_0000h FF_FFFF_FFFFh Reserved
8138504f129SJoao Martins  *
8148504f129SJoao Martins  * See AMD IOMMU spec, section 2.1.2 "IOMMU Logical Topology",
8158504f129SJoao Martins  * Table 3: Special Address Controls (GPA) for more information.
8168504f129SJoao Martins  */
8178504f129SJoao Martins #define AMD_HT_START         0xfd00000000UL
8188504f129SJoao Martins #define AMD_HT_END           0xffffffffffUL
8198504f129SJoao Martins #define AMD_ABOVE_1TB_START  (AMD_HT_END + 1)
8208504f129SJoao Martins #define AMD_HT_SIZE          (AMD_ABOVE_1TB_START - AMD_HT_START)
8218504f129SJoao Martins 
pc_memory_init(PCMachineState * pcms,MemoryRegion * system_memory,MemoryRegion * rom_memory,uint64_t pci_hole64_size)8225934e216SEduardo Habkost void pc_memory_init(PCMachineState *pcms,
8239521d42bSPaolo Bonzini                     MemoryRegion *system_memory,
82453018216SPaolo Bonzini                     MemoryRegion *rom_memory,
825c48eb7a4SJoao Martins                     uint64_t pci_hole64_size)
82653018216SPaolo Bonzini {
82753018216SPaolo Bonzini     int linux_boot, i;
828bd457782SIgor Mammedov     MemoryRegion *option_rom_mr;
82953018216SPaolo Bonzini     MemoryRegion *ram_below_4g, *ram_above_4g;
830a88b362cSLaszlo Ersek     FWCfgState *fw_cfg;
83162b160c0SEduardo Habkost     MachineState *machine = MACHINE(pcms);
832264b4857SPhilippe Mathieu-Daudé     MachineClass *mc = MACHINE_GET_CLASS(machine);
83316a9e8a5SEduardo Habkost     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
834f0bb276bSPaolo Bonzini     X86MachineState *x86ms = X86_MACHINE(pcms);
8351caab5cfSJoao Martins     hwaddr maxphysaddr, maxusedaddr;
8366d302cf4SJonathan Cameron     hwaddr cxl_base, cxl_resv_end = 0;
8371caab5cfSJoao Martins     X86CPU *cpu = X86_CPU(first_cpu);
83853018216SPaolo Bonzini 
839f0bb276bSPaolo Bonzini     assert(machine->ram_size == x86ms->below_4g_mem_size +
840f0bb276bSPaolo Bonzini                                 x86ms->above_4g_mem_size);
8419521d42bSPaolo Bonzini 
8429521d42bSPaolo Bonzini     linux_boot = (machine->kernel_filename != NULL);
84353018216SPaolo Bonzini 
844bd457782SIgor Mammedov     /*
8458504f129SJoao Martins      * The HyperTransport range close to the 1T boundary is unique to AMD
8468504f129SJoao Martins      * hosts with IOMMUs enabled. Restrict the ram-above-4g relocation
847b3e6982bSJoao Martins      * to above 1T to AMD vCPUs only. @enforce_amd_1tb_hole is only false in
848b3e6982bSJoao Martins      * older machine types (<= 7.0) for compatibility purposes.
8498504f129SJoao Martins      */
850b3e6982bSJoao Martins     if (IS_AMD_CPU(&cpu->env) && pcmc->enforce_amd_1tb_hole) {
8518504f129SJoao Martins         /* Bail out if max possible address does not cross HT range */
8528504f129SJoao Martins         if (pc_max_used_gpa(pcms, pci_hole64_size) >= AMD_HT_START) {
8538504f129SJoao Martins             x86ms->above_4g_mem_start = AMD_ABOVE_1TB_START;
8548504f129SJoao Martins         }
8558504f129SJoao Martins 
8568504f129SJoao Martins         /*
8578504f129SJoao Martins          * Advertise the HT region if address space covers the reserved
8588504f129SJoao Martins          * region or if we relocate.
8598504f129SJoao Martins          */
8608504f129SJoao Martins         if (cpu->phys_bits >= 40) {
8618504f129SJoao Martins             e820_add_entry(AMD_HT_START, AMD_HT_SIZE, E820_RESERVED);
8628504f129SJoao Martins         }
8638504f129SJoao Martins     }
8648504f129SJoao Martins 
8658504f129SJoao Martins     /*
8661caab5cfSJoao Martins      * phys-bits is required to be appropriately configured
8671caab5cfSJoao Martins      * to make sure max used GPA is reachable.
8681caab5cfSJoao Martins      */
8691caab5cfSJoao Martins     maxusedaddr = pc_max_used_gpa(pcms, pci_hole64_size);
8701caab5cfSJoao Martins     maxphysaddr = ((hwaddr)1 << cpu->phys_bits) - 1;
8711caab5cfSJoao Martins     if (maxphysaddr < maxusedaddr) {
8721caab5cfSJoao Martins         error_report("Address space limit 0x%"PRIx64" < 0x%"PRIx64
8731caab5cfSJoao Martins                      " phys-bits too low (%u)",
8741caab5cfSJoao Martins                      maxphysaddr, maxusedaddr, cpu->phys_bits);
8751caab5cfSJoao Martins         exit(EXIT_FAILURE);
8761caab5cfSJoao Martins     }
8771caab5cfSJoao Martins 
8781caab5cfSJoao Martins     /*
879bd457782SIgor Mammedov      * Split single memory region and use aliases to address portions of it,
880bd457782SIgor Mammedov      * done for backwards compatibility with older qemus.
88153018216SPaolo Bonzini      */
88253018216SPaolo Bonzini     ram_below_4g = g_malloc(sizeof(*ram_below_4g));
883bd457782SIgor Mammedov     memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", machine->ram,
884f0bb276bSPaolo Bonzini                              0, x86ms->below_4g_mem_size);
88553018216SPaolo Bonzini     memory_region_add_subregion(system_memory, 0, ram_below_4g);
886f0bb276bSPaolo Bonzini     e820_add_entry(0, x86ms->below_4g_mem_size, E820_RAM);
887f0bb276bSPaolo Bonzini     if (x86ms->above_4g_mem_size > 0) {
88853018216SPaolo Bonzini         ram_above_4g = g_malloc(sizeof(*ram_above_4g));
889bd457782SIgor Mammedov         memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g",
890bd457782SIgor Mammedov                                  machine->ram,
891f0bb276bSPaolo Bonzini                                  x86ms->below_4g_mem_size,
892f0bb276bSPaolo Bonzini                                  x86ms->above_4g_mem_size);
8934ab4c330SJoao Martins         memory_region_add_subregion(system_memory, x86ms->above_4g_mem_start,
89453018216SPaolo Bonzini                                     ram_above_4g);
8954ab4c330SJoao Martins         e820_add_entry(x86ms->above_4g_mem_start, x86ms->above_4g_mem_size,
8964ab4c330SJoao Martins                        E820_RAM);
89753018216SPaolo Bonzini     }
89853018216SPaolo Bonzini 
8991ed1ccc5SSean Christopherson     if (pcms->sgx_epc.size != 0) {
9001ed1ccc5SSean Christopherson         e820_add_entry(pcms->sgx_epc.base, pcms->sgx_epc.size, E820_RESERVED);
9011ed1ccc5SSean Christopherson     }
9021ed1ccc5SSean Christopherson 
903bb292f5aSEduardo Habkost     if (!pcmc->has_reserved_memory &&
904ca8336f3SIgor Mammedov         (machine->ram_slots ||
9059521d42bSPaolo Bonzini          (machine->maxram_size > machine->ram_size))) {
906ca8336f3SIgor Mammedov 
907ca8336f3SIgor Mammedov         error_report("\"-memory 'slots|maxmem'\" is not supported by: %s",
908ca8336f3SIgor Mammedov                      mc->name);
909ca8336f3SIgor Mammedov         exit(EXIT_FAILURE);
910ca8336f3SIgor Mammedov     }
911ca8336f3SIgor Mammedov 
912f2ffbe2bSDavid Hildenbrand     /* initialize device memory address space */
913bb292f5aSEduardo Habkost     if (pcmc->has_reserved_memory &&
9149521d42bSPaolo Bonzini         (machine->ram_size < machine->maxram_size)) {
9158288a828SJoao Martins         ram_addr_t device_mem_size;
91678732a76SDavid Hildenbrand         hwaddr device_mem_base;
917619d11e4SIgor Mammedov 
918a0cc8856SIgor Mammedov         if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) {
919a0cc8856SIgor Mammedov             error_report("unsupported amount of memory slots: %"PRIu64,
920a0cc8856SIgor Mammedov                          machine->ram_slots);
921a0cc8856SIgor Mammedov             exit(EXIT_FAILURE);
922a0cc8856SIgor Mammedov         }
923a0cc8856SIgor Mammedov 
924f2c38522SPeter Krempa         if (QEMU_ALIGN_UP(machine->maxram_size,
925f2c38522SPeter Krempa                           TARGET_PAGE_SIZE) != machine->maxram_size) {
926f2c38522SPeter Krempa             error_report("maximum memory size must by aligned to multiple of "
927f2c38522SPeter Krempa                          "%d bytes", TARGET_PAGE_SIZE);
928f2c38522SPeter Krempa             exit(EXIT_FAILURE);
929f2c38522SPeter Krempa         }
930f2c38522SPeter Krempa 
93178732a76SDavid Hildenbrand         pc_get_device_memory_range(pcms, &device_mem_base, &device_mem_size);
932085f8e88SIgor Mammedov 
93378732a76SDavid Hildenbrand         if (device_mem_base + device_mem_size < device_mem_size) {
934619d11e4SIgor Mammedov             error_report("unsupported amount of maximum memory: " RAM_ADDR_FMT,
935619d11e4SIgor Mammedov                          machine->maxram_size);
936619d11e4SIgor Mammedov             exit(EXIT_FAILURE);
937619d11e4SIgor Mammedov         }
93878732a76SDavid Hildenbrand         machine_memory_devices_init(machine, device_mem_base, device_mem_size);
939619d11e4SIgor Mammedov     }
94053018216SPaolo Bonzini 
9411ebf9001SJonathan Cameron     if (pcms->cxl_devices_state.is_enabled) {
9421ebf9001SJonathan Cameron         MemoryRegion *mr = &pcms->cxl_devices_state.host_mr;
9436e4e3ae9SBen Widawsky         hwaddr cxl_size = MiB;
9446e4e3ae9SBen Widawsky 
94542bed071SJoao Martins         cxl_base = pc_get_cxl_range_start(pcms);
9466e4e3ae9SBen Widawsky         memory_region_init(mr, OBJECT(machine), "cxl_host_reg", cxl_size);
9476e4e3ae9SBen Widawsky         memory_region_add_subregion(system_memory, cxl_base, mr);
9486d302cf4SJonathan Cameron         cxl_resv_end = cxl_base + cxl_size;
9491ebf9001SJonathan Cameron         if (pcms->cxl_devices_state.fixed_windows) {
9506d302cf4SJonathan Cameron             hwaddr cxl_fmw_base;
9516d302cf4SJonathan Cameron             GList *it;
9526d302cf4SJonathan Cameron 
9536d302cf4SJonathan Cameron             cxl_fmw_base = ROUND_UP(cxl_base + cxl_size, 256 * MiB);
9541ebf9001SJonathan Cameron             for (it = pcms->cxl_devices_state.fixed_windows; it; it = it->next) {
9556d302cf4SJonathan Cameron                 CXLFixedWindow *fw = it->data;
9566d302cf4SJonathan Cameron 
9576d302cf4SJonathan Cameron                 fw->base = cxl_fmw_base;
9586d302cf4SJonathan Cameron                 memory_region_init_io(&fw->mr, OBJECT(machine), &cfmws_ops, fw,
9596d302cf4SJonathan Cameron                                       "cxl-fixed-memory-region", fw->size);
9606d302cf4SJonathan Cameron                 memory_region_add_subregion(system_memory, fw->base, &fw->mr);
9616d302cf4SJonathan Cameron                 cxl_fmw_base += fw->size;
9626d302cf4SJonathan Cameron                 cxl_resv_end = cxl_fmw_base;
9636d302cf4SJonathan Cameron             }
9646d302cf4SJonathan Cameron         }
9656e4e3ae9SBen Widawsky     }
9666e4e3ae9SBen Widawsky 
96753018216SPaolo Bonzini     /* Initialize PC system firmware */
9685e640a9eSPhilippe Mathieu-Daudé     pc_system_firmware_init(pcms, rom_memory);
96953018216SPaolo Bonzini 
97053018216SPaolo Bonzini     option_rom_mr = g_malloc(sizeof(*option_rom_mr));
971413a6745SMichael Roth     if (machine_require_guest_memfd(machine)) {
972413a6745SMichael Roth         memory_region_init_ram_guest_memfd(option_rom_mr, NULL, "pc.rom",
973413a6745SMichael Roth                                            PC_ROM_SIZE, &error_fatal);
974413a6745SMichael Roth     } else {
97598a99ce0SPeter Maydell         memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE,
976f8ed85acSMarkus Armbruster                                &error_fatal);
977208fa0e4SIgor Mammedov         if (pcmc->pci_enabled) {
978208fa0e4SIgor Mammedov             memory_region_set_readonly(option_rom_mr, true);
979208fa0e4SIgor Mammedov         }
980413a6745SMichael Roth     }
98153018216SPaolo Bonzini     memory_region_add_subregion_overlap(rom_memory,
98253018216SPaolo Bonzini                                         PC_ROM_MIN_VGA,
98353018216SPaolo Bonzini                                         option_rom_mr,
98453018216SPaolo Bonzini                                         1);
98553018216SPaolo Bonzini 
986bd802bd9SPaolo Bonzini     fw_cfg = fw_cfg_arch_create(machine,
987f0bb276bSPaolo Bonzini                                 x86ms->boot_cpus, x86ms->apic_id_limit);
988c886fc4cSMarc Marí 
98953018216SPaolo Bonzini     rom_set_fw(fw_cfg);
99053018216SPaolo Bonzini 
99178732a76SDavid Hildenbrand     if (machine->device_memory) {
992de268e13SIgor Mammedov         uint64_t *val = g_malloc(sizeof(*val));
993b0c14ec4SDavid Hildenbrand         uint64_t res_mem_end = machine->device_memory->base;
9942f8b5008SIgor Mammedov 
9952f8b5008SIgor Mammedov         if (!pcmc->broken_reserved_end) {
996b0c14ec4SDavid Hildenbrand             res_mem_end += memory_region_size(&machine->device_memory->mr);
9972f8b5008SIgor Mammedov         }
9986d302cf4SJonathan Cameron 
9991ebf9001SJonathan Cameron         if (pcms->cxl_devices_state.is_enabled) {
10006d302cf4SJonathan Cameron             res_mem_end = cxl_resv_end;
10016d302cf4SJonathan Cameron         }
1002d471bf3eSPaolo Bonzini         *val = cpu_to_le64(ROUND_UP(res_mem_end, 1 * GiB));
1003de268e13SIgor Mammedov         fw_cfg_add_file(fw_cfg, "etc/reserved-memory-end", val, sizeof(*val));
1004de268e13SIgor Mammedov     }
1005de268e13SIgor Mammedov 
100653018216SPaolo Bonzini     if (linux_boot) {
1007e6115657SPhilippe Mathieu-Daudé         x86_load_linux(x86ms, fw_cfg, PC_FW_DATA, pcmc->pvh_enabled);
100853018216SPaolo Bonzini     }
100953018216SPaolo Bonzini 
101053018216SPaolo Bonzini     for (i = 0; i < nb_option_roms; i++) {
101153018216SPaolo Bonzini         rom_add_option(option_rom[i].name, option_rom[i].bootindex);
101253018216SPaolo Bonzini     }
1013f0bb276bSPaolo Bonzini     x86ms->fw_cfg = fw_cfg;
1014cb135f59SPeter Xu 
1015cb135f59SPeter Xu     /* Init default IOAPIC address space */
1016f0bb276bSPaolo Bonzini     x86ms->ioapic_as = &address_space_memory;
1017091c466eSShameer Kolothum 
1018091c466eSShameer Kolothum     /* Init ACPI memory hotplug IO base address */
1019091c466eSShameer Kolothum     pcms->memhp_io_base = ACPI_MEMORY_HOTPLUG_BASE;
102053018216SPaolo Bonzini }
102153018216SPaolo Bonzini 
10229fa99d25SMarcel Apfelbaum /*
10239fa99d25SMarcel Apfelbaum  * The 64bit pci hole starts after "above 4G RAM" and
10249fa99d25SMarcel Apfelbaum  * potentially the space reserved for memory hotplug.
10259fa99d25SMarcel Apfelbaum  */
pc_pci_hole64_start(void)10269fa99d25SMarcel Apfelbaum uint64_t pc_pci_hole64_start(void)
10279fa99d25SMarcel Apfelbaum {
10289fa99d25SMarcel Apfelbaum     PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
10299fa99d25SMarcel Apfelbaum     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
1030b0c14ec4SDavid Hildenbrand     MachineState *ms = MACHINE(pcms);
10319fa99d25SMarcel Apfelbaum     uint64_t hole64_start = 0;
10328288a828SJoao Martins     ram_addr_t size = 0;
10339fa99d25SMarcel Apfelbaum 
103455668e40SJoao Martins     if (pcms->cxl_devices_state.is_enabled) {
103555668e40SJoao Martins         hole64_start = pc_get_cxl_range_end(pcms);
10368288a828SJoao Martins     } else if (pcmc->has_reserved_memory && (ms->ram_size < ms->maxram_size)) {
10378288a828SJoao Martins         pc_get_device_memory_range(pcms, &hole64_start, &size);
10389fa99d25SMarcel Apfelbaum         if (!pcmc->broken_reserved_end) {
10398288a828SJoao Martins             hole64_start += size;
10409fa99d25SMarcel Apfelbaum         }
10419fa99d25SMarcel Apfelbaum     } else {
10425ff62e2aSJoao Martins         hole64_start = pc_above_4g_end(pcms);
10439fa99d25SMarcel Apfelbaum     }
10449fa99d25SMarcel Apfelbaum 
1045d471bf3eSPaolo Bonzini     return ROUND_UP(hole64_start, 1 * GiB);
10469fa99d25SMarcel Apfelbaum }
10479fa99d25SMarcel Apfelbaum 
pc_vga_init(ISABus * isa_bus,PCIBus * pci_bus)104853018216SPaolo Bonzini DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
104953018216SPaolo Bonzini {
105053018216SPaolo Bonzini     DeviceState *dev = NULL;
105153018216SPaolo Bonzini 
1052bab47d9aSGerd Hoffmann     rom_set_order_override(FW_CFG_ORDER_OVERRIDE_VGA);
105353018216SPaolo Bonzini     if (pci_bus) {
105453018216SPaolo Bonzini         PCIDevice *pcidev = pci_vga_init(pci_bus);
105553018216SPaolo Bonzini         dev = pcidev ? &pcidev->qdev : NULL;
105653018216SPaolo Bonzini     } else if (isa_bus) {
105753018216SPaolo Bonzini         ISADevice *isadev = isa_vga_init(isa_bus);
10584a17cc4fSAndreas Färber         dev = isadev ? DEVICE(isadev) : NULL;
105953018216SPaolo Bonzini     }
1060bab47d9aSGerd Hoffmann     rom_reset_order_override();
106153018216SPaolo Bonzini     return dev;
106253018216SPaolo Bonzini }
106353018216SPaolo Bonzini 
106453018216SPaolo Bonzini static const MemoryRegionOps ioport80_io_ops = {
106553018216SPaolo Bonzini     .write = ioport80_write,
106653018216SPaolo Bonzini     .read = ioport80_read,
106753018216SPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
106853018216SPaolo Bonzini     .impl = {
106953018216SPaolo Bonzini         .min_access_size = 1,
107053018216SPaolo Bonzini         .max_access_size = 1,
107153018216SPaolo Bonzini     },
107253018216SPaolo Bonzini };
107353018216SPaolo Bonzini 
107453018216SPaolo Bonzini static const MemoryRegionOps ioportF0_io_ops = {
107553018216SPaolo Bonzini     .write = ioportF0_write,
107653018216SPaolo Bonzini     .read = ioportF0_read,
107753018216SPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
107853018216SPaolo Bonzini     .impl = {
107953018216SPaolo Bonzini         .min_access_size = 1,
108053018216SPaolo Bonzini         .max_access_size = 1,
108153018216SPaolo Bonzini     },
108253018216SPaolo Bonzini };
108353018216SPaolo Bonzini 
pc_superio_init(ISABus * isa_bus,bool create_fdctrl,bool create_i8042,bool no_vmport,Error ** errp)10844ccd5fe2SJoelle van Dyne static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl,
1085702cbdc4SKamil Szczęk                             bool create_i8042, bool no_vmport, Error **errp)
1086ac64273cSPhilippe Mathieu-Daudé {
1087ac64273cSPhilippe Mathieu-Daudé     int i;
1088ac64273cSPhilippe Mathieu-Daudé     DriveInfo *fd[MAX_FD];
1089ac64273cSPhilippe Mathieu-Daudé     qemu_irq *a20_line;
109064436c5cSThomas Huth     ISADevice *i8042, *port92, *vmmouse;
1091ac64273cSPhilippe Mathieu-Daudé 
1092def337ffSPeter Maydell     serial_hds_isa_init(isa_bus, 0, MAX_ISA_SERIAL_PORTS);
1093ac64273cSPhilippe Mathieu-Daudé     parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS);
1094ac64273cSPhilippe Mathieu-Daudé 
1095ac64273cSPhilippe Mathieu-Daudé     for (i = 0; i < MAX_FD; i++) {
1096ac64273cSPhilippe Mathieu-Daudé         fd[i] = drive_get(IF_FLOPPY, 0, i);
1097ac64273cSPhilippe Mathieu-Daudé         create_fdctrl |= !!fd[i];
1098ac64273cSPhilippe Mathieu-Daudé     }
1099ac64273cSPhilippe Mathieu-Daudé     if (create_fdctrl) {
110064436c5cSThomas Huth #ifdef CONFIG_FDC_ISA
110164436c5cSThomas Huth         ISADevice *fdc = isa_new(TYPE_ISA_FDC);
1102fed2c173SMarkus Armbruster         if (fdc) {
1103fed2c173SMarkus Armbruster             isa_realize_and_unref(fdc, isa_bus, &error_fatal);
1104fed2c173SMarkus Armbruster             isa_fdc_init_drives(fdc, fd);
1105fed2c173SMarkus Armbruster         }
110664436c5cSThomas Huth #endif
1107ac64273cSPhilippe Mathieu-Daudé     }
1108ac64273cSPhilippe Mathieu-Daudé 
11094ccd5fe2SJoelle van Dyne     if (!create_i8042) {
1110702cbdc4SKamil Szczęk         if (!no_vmport) {
1111702cbdc4SKamil Szczęk             error_setg(errp,
1112702cbdc4SKamil Szczęk                        "vmport requires the i8042 controller to be enabled");
1113702cbdc4SKamil Szczęk         }
11144ccd5fe2SJoelle van Dyne         return;
11154ccd5fe2SJoelle van Dyne     }
11164ccd5fe2SJoelle van Dyne 
1117aa2e535cSBernhard Beschow     i8042 = isa_create_simple(isa_bus, TYPE_I8042);
1118ac64273cSPhilippe Mathieu-Daudé     if (!no_vmport) {
1119b4fa79eaSPhilippe Mathieu-Daudé         isa_create_simple(isa_bus, TYPE_VMPORT);
1120c23e0561SMarkus Armbruster         vmmouse = isa_try_new("vmmouse");
1121ac64273cSPhilippe Mathieu-Daudé     } else {
1122ac64273cSPhilippe Mathieu-Daudé         vmmouse = NULL;
1123ac64273cSPhilippe Mathieu-Daudé     }
1124ac64273cSPhilippe Mathieu-Daudé     if (vmmouse) {
1125aa2e535cSBernhard Beschow         object_property_set_link(OBJECT(vmmouse), TYPE_I8042, OBJECT(i8042),
11265325cc34SMarkus Armbruster                                  &error_abort);
1127c23e0561SMarkus Armbruster         isa_realize_and_unref(vmmouse, isa_bus, &error_fatal);
1128ac64273cSPhilippe Mathieu-Daudé     }
11299e5213c8SPhilippe Mathieu-Daudé     port92 = isa_create_simple(isa_bus, TYPE_PORT92);
1130ac64273cSPhilippe Mathieu-Daudé 
1131ac64273cSPhilippe Mathieu-Daudé     a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
113240f27a78SPhilippe Mathieu-Daudé     qdev_connect_gpio_out_named(DEVICE(i8042),
113340f27a78SPhilippe Mathieu-Daudé                                 I8042_A20_LINE, 0, a20_line[0]);
11341820b70eSPhilippe Mathieu-Daudé     qdev_connect_gpio_out_named(DEVICE(port92),
11351820b70eSPhilippe Mathieu-Daudé                                 PORT92_A20_LINE, 0, a20_line[1]);
1136ac64273cSPhilippe Mathieu-Daudé     g_free(a20_line);
1137ac64273cSPhilippe Mathieu-Daudé }
1138ac64273cSPhilippe Mathieu-Daudé 
pc_basic_device_init(struct PCMachineState * pcms,ISABus * isa_bus,qemu_irq * gsi,ISADevice * rtc_state,bool create_fdctrl,uint32_t hpet_irqs)113910e2483bSGerd Hoffmann void pc_basic_device_init(struct PCMachineState *pcms,
114010e2483bSGerd Hoffmann                           ISABus *isa_bus, qemu_irq *gsi,
114187af48a4SBernhard Beschow                           ISADevice *rtc_state,
1142fd53c87cSLaszlo Ersek                           bool create_fdctrl,
11433a87d009SPeter Maydell                           uint32_t hpet_irqs)
114453018216SPaolo Bonzini {
114553018216SPaolo Bonzini     int i;
114653018216SPaolo Bonzini     DeviceState *hpet = NULL;
114753018216SPaolo Bonzini     int pit_isa_irq = 0;
114853018216SPaolo Bonzini     qemu_irq pit_alt_irq = NULL;
1149ac64273cSPhilippe Mathieu-Daudé     ISADevice *pit = NULL;
115053018216SPaolo Bonzini     MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
115153018216SPaolo Bonzini     MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
11529dee7e51SXiaoyao Li     X86MachineState *x86ms = X86_MACHINE(pcms);
115353018216SPaolo Bonzini 
11542c9b15caSPaolo Bonzini     memory_region_init_io(ioport80_io, NULL, &ioport80_io_ops, NULL, "ioport80", 1);
115553018216SPaolo Bonzini     memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
115653018216SPaolo Bonzini 
11572c9b15caSPaolo Bonzini     memory_region_init_io(ioportF0_io, NULL, &ioportF0_io_ops, NULL, "ioportF0", 1);
115853018216SPaolo Bonzini     memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
115953018216SPaolo Bonzini 
116053018216SPaolo Bonzini     /*
116153018216SPaolo Bonzini      * Check if an HPET shall be created.
116253018216SPaolo Bonzini      */
116339dd3e1fSPaolo Bonzini     if (pcms->hpet_enabled) {
11649c910511SBernhard Beschow         qemu_irq rtc_irq;
11659c910511SBernhard Beschow 
1166df707969SMarkus Armbruster         hpet = qdev_try_new(TYPE_HPET);
11670259c78cSEduardo Habkost         if (!hpet) {
11680259c78cSEduardo Habkost             error_report("couldn't create HPET device");
11690259c78cSEduardo Habkost             exit(1);
11700259c78cSEduardo Habkost         }
117154420332SMichael S. Tsirkin         /*
1172ea985d23SPaolo Bonzini          * For pc-piix-*, hpet's intcap is always IRQ2. For pc-q35-*,
1173ea985d23SPaolo Bonzini          * use IRQ16~23, IRQ8 and IRQ2.  If the user has already set
1174ea985d23SPaolo Bonzini          * the property, use whatever mask they specified.
11757a10ef51SLiu Ping Fan          */
11765d7fb0f2SMarc-André Lureau         uint8_t compat = object_property_get_uint(OBJECT(hpet),
11777a10ef51SLiu Ping Fan                 HPET_INTCAP, NULL);
11787a10ef51SLiu Ping Fan         if (!compat) {
11797a10ef51SLiu Ping Fan             qdev_prop_set_uint32(hpet, HPET_INTCAP, hpet_irqs);
11807a10ef51SLiu Ping Fan         }
11813c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(hpet), &error_fatal);
11827a10ef51SLiu Ping Fan         sysbus_mmio_map(SYS_BUS_DEVICE(hpet), 0, HPET_BASE);
11837a10ef51SLiu Ping Fan 
1184e3e3a8adSBernhard Beschow         for (i = 0; i < IOAPIC_NUM_PINS; i++) {
118553018216SPaolo Bonzini             sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]);
118653018216SPaolo Bonzini         }
118753018216SPaolo Bonzini         pit_isa_irq = -1;
118853018216SPaolo Bonzini         pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
118953018216SPaolo Bonzini         rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
119056b1f50eSBernhard Beschow 
119156b1f50eSBernhard Beschow         /* overwrite connection created by south bridge */
119287af48a4SBernhard Beschow         qdev_connect_gpio_out(DEVICE(rtc_state), 0, rtc_irq);
119353018216SPaolo Bonzini     }
1194f0bc6bf7SBernhard Beschow 
119587af48a4SBernhard Beschow     object_property_add_alias(OBJECT(pcms), "rtc-time", OBJECT(rtc_state),
1196f0bc6bf7SBernhard Beschow                               "date");
119753018216SPaolo Bonzini 
1198ddf0fd9aSDavid Woodhouse #ifdef CONFIG_XEN_EMU
1199ddf0fd9aSDavid Woodhouse     if (xen_mode == XEN_EMULATE) {
1200eeedfe6cSDavid Woodhouse         xen_overlay_create();
1201eeedfe6cSDavid Woodhouse         xen_evtchn_create(IOAPIC_NUM_PINS, gsi);
1202eeedfe6cSDavid Woodhouse         xen_gnttab_create();
1203eeedfe6cSDavid Woodhouse         xen_xenstore_create();
1204b54a9d46SBernhard Beschow         if (pcms->pcibus) {
1205b54a9d46SBernhard Beschow             pci_create_simple(pcms->pcibus, -1, "xen-platform");
1206bdfdb748SDavid Woodhouse         }
12077d6eff13SDavid Woodhouse         xen_bus_init();
1208ddf0fd9aSDavid Woodhouse     }
1209ddf0fd9aSDavid Woodhouse #endif
1210ddf0fd9aSDavid Woodhouse 
12116605d097SBernhard Beschow     qemu_register_boot_set(pc_boot_set, pcms);
1212c5e2d744SBernhard Beschow     set_boot_dev(pcms, MC146818_RTC(rtc_state),
1213c5e2d744SBernhard Beschow                  MACHINE(pcms)->boot_config.order, &error_fatal);
121453018216SPaolo Bonzini 
12159dee7e51SXiaoyao Li     if (!xen_enabled() &&
12169dee7e51SXiaoyao Li         (x86ms->pit == ON_OFF_AUTO_AUTO || x86ms->pit == ON_OFF_AUTO_ON)) {
121715eafc2eSPaolo Bonzini         if (kvm_pit_in_kernel()) {
121853018216SPaolo Bonzini             pit = kvm_pit_init(isa_bus, 0x40);
121953018216SPaolo Bonzini         } else {
1220acf695ecSPhilippe Mathieu-Daudé             pit = i8254_pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
122153018216SPaolo Bonzini         }
122253018216SPaolo Bonzini         if (hpet) {
122353018216SPaolo Bonzini             /* connect PIT to output control line of the HPET */
12244a17cc4fSAndreas Färber             qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(DEVICE(pit), 0));
122553018216SPaolo Bonzini         }
122640f8214fSPhilippe Mathieu-Daudé         object_property_set_link(OBJECT(pcms->pcspk), "pit",
122740f8214fSPhilippe Mathieu-Daudé                                  OBJECT(pit), &error_fatal);
122840f8214fSPhilippe Mathieu-Daudé         isa_realize_and_unref(pcms->pcspk, isa_bus, &error_fatal);
122953018216SPaolo Bonzini     }
123053018216SPaolo Bonzini 
1231c911f875SKamil Szczęk     if (pcms->vmport == ON_OFF_AUTO_AUTO) {
1232702cbdc4SKamil Szczęk         pcms->vmport = (xen_enabled() || !pcms->i8042_enabled)
1233702cbdc4SKamil Szczęk             ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
1234c911f875SKamil Szczęk     }
1235c911f875SKamil Szczęk 
1236ac64273cSPhilippe Mathieu-Daudé     /* Super I/O */
12374ccd5fe2SJoelle van Dyne     pc_superio_init(isa_bus, create_fdctrl, pcms->i8042_enabled,
1238702cbdc4SKamil Szczęk                     pcms->vmport != ON_OFF_AUTO_ON, &error_fatal);
123953018216SPaolo Bonzini }
124053018216SPaolo Bonzini 
pc_nic_init(PCMachineClass * pcmc,ISABus * isa_bus,PCIBus * pci_bus)12417d6eff13SDavid Woodhouse void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus)
124253018216SPaolo Bonzini {
124301ecdaa4SThomas Huth     MachineClass *mc = MACHINE_CLASS(pcmc);
12448d39f9baSDavid Woodhouse     bool default_is_ne2k = g_str_equal(mc->default_nic, TYPE_ISA_NE2000);
12458d39f9baSDavid Woodhouse     NICInfo *nd;
124653018216SPaolo Bonzini 
1247bab47d9aSGerd Hoffmann     rom_set_order_override(FW_CFG_ORDER_OVERRIDE_NIC);
124853018216SPaolo Bonzini 
12498d39f9baSDavid Woodhouse     while ((nd = qemu_find_nic_info(TYPE_ISA_NE2000, default_is_ne2k, NULL))) {
12508d39f9baSDavid Woodhouse         pc_init_ne2k_isa(isa_bus, nd, &error_fatal);
12518d39f9baSDavid Woodhouse     }
12528d39f9baSDavid Woodhouse 
12538d39f9baSDavid Woodhouse     /* Anything remaining should be a PCI NIC */
1254*bd0e501eSPeter Maydell     if (pci_bus) {
12558d39f9baSDavid Woodhouse         pci_init_nic_devices(pci_bus, mc->default_nic);
1256*bd0e501eSPeter Maydell     }
12578d39f9baSDavid Woodhouse 
1258bab47d9aSGerd Hoffmann     rom_reset_order_override();
125953018216SPaolo Bonzini }
126053018216SPaolo Bonzini 
pc_i8259_create(ISABus * isa_bus,qemu_irq * i8259_irqs)12614501d317SPhilippe Mathieu-Daudé void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs)
12624501d317SPhilippe Mathieu-Daudé {
12634501d317SPhilippe Mathieu-Daudé     qemu_irq *i8259;
12644501d317SPhilippe Mathieu-Daudé 
12654501d317SPhilippe Mathieu-Daudé     if (kvm_pic_in_kernel()) {
12664501d317SPhilippe Mathieu-Daudé         i8259 = kvm_i8259_init(isa_bus);
12674501d317SPhilippe Mathieu-Daudé     } else if (xen_enabled()) {
12684501d317SPhilippe Mathieu-Daudé         i8259 = xen_interrupt_controller_init();
12694501d317SPhilippe Mathieu-Daudé     } else {
127089a289c7SPaolo Bonzini         i8259 = i8259_init(isa_bus, x86_allocate_cpu_irq());
12714501d317SPhilippe Mathieu-Daudé     }
12724501d317SPhilippe Mathieu-Daudé 
12734501d317SPhilippe Mathieu-Daudé     for (size_t i = 0; i < ISA_NUM_IRQS; i++) {
12744501d317SPhilippe Mathieu-Daudé         i8259_irqs[i] = i8259[i];
12754501d317SPhilippe Mathieu-Daudé     }
12764501d317SPhilippe Mathieu-Daudé 
12774501d317SPhilippe Mathieu-Daudé     g_free(i8259);
12784501d317SPhilippe Mathieu-Daudé }
12794501d317SPhilippe Mathieu-Daudé 
pc_memory_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)1280d468115bSDavid Hildenbrand static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
1281d468115bSDavid Hildenbrand                                Error **errp)
1282d468115bSDavid Hildenbrand {
128350aef131SGerd Hoffmann     const X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
1284f6a0d06bSEric Auger     const MachineState *ms = MACHINE(hotplug_dev);
1285d468115bSDavid Hildenbrand     const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
1286ae909496SThomas Huth     Error *local_err = NULL;
1287d468115bSDavid Hildenbrand 
1288d468115bSDavid Hildenbrand     /*
12894a641010SThomas Huth      * When "acpi=off" is used with the Q35 machine type, no ACPI is built,
1290d468115bSDavid Hildenbrand      * but pcms->acpi_dev is still created. Check !acpi_enabled in
1291d468115bSDavid Hildenbrand      * addition to cover this case.
1292d468115bSDavid Hildenbrand      */
129350aef131SGerd Hoffmann     if (!x86ms->acpi_dev || !x86_machine_is_acpi_enabled(x86ms)) {
1294d468115bSDavid Hildenbrand         error_setg(errp,
1295d468115bSDavid Hildenbrand                    "memory hotplug is not enabled: missing acpi device or acpi disabled");
1296d468115bSDavid Hildenbrand         return;
1297d468115bSDavid Hildenbrand     }
1298d468115bSDavid Hildenbrand 
1299f6a0d06bSEric Auger     if (is_nvdimm && !ms->nvdimms_state->is_enabled) {
1300d468115bSDavid Hildenbrand         error_setg(errp, "nvdimm is not enabled: missing 'nvdimm' in '-M'");
1301d468115bSDavid Hildenbrand         return;
1302d468115bSDavid Hildenbrand     }
13038f1ffe5bSDavid Hildenbrand 
130450aef131SGerd Hoffmann     hotplug_handler_pre_plug(x86ms->acpi_dev, dev, &local_err);
1305ae909496SThomas Huth     if (local_err) {
1306ae909496SThomas Huth         error_propagate(errp, local_err);
1307ae909496SThomas Huth         return;
1308ae909496SThomas Huth     }
1309ae909496SThomas Huth 
1310d4fdb05bSPhilippe Mathieu-Daudé     pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), errp);
1311d468115bSDavid Hildenbrand }
1312d468115bSDavid Hildenbrand 
pc_memory_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)1313bb6e2f7aSDavid Hildenbrand static void pc_memory_plug(HotplugHandler *hotplug_dev,
131495bee274SIgor Mammedov                            DeviceState *dev, Error **errp)
131595bee274SIgor Mammedov {
131695bee274SIgor Mammedov     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
131750aef131SGerd Hoffmann     X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
1318f6a0d06bSEric Auger     MachineState *ms = MACHINE(hotplug_dev);
13197f3cf2d6SStefan Hajnoczi     bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
132095bee274SIgor Mammedov 
132184fd5496SGreg Kurz     pc_dimm_plug(PC_DIMM(dev), MACHINE(pcms));
1322b8865591SIgor Mammedov 
13237f3cf2d6SStefan Hajnoczi     if (is_nvdimm) {
1324f6a0d06bSEric Auger         nvdimm_plug(ms->nvdimms_state);
1325c7f8d0f3SXiao Guangrong     }
1326c7f8d0f3SXiao Guangrong 
132750aef131SGerd Hoffmann     hotplug_handler_plug(x86ms->acpi_dev, dev, &error_abort);
132895bee274SIgor Mammedov }
132995bee274SIgor Mammedov 
pc_memory_unplug_request(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)1330bb6e2f7aSDavid Hildenbrand static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
133164fec58eSTang Chen                                      DeviceState *dev, Error **errp)
133264fec58eSTang Chen {
133350aef131SGerd Hoffmann     X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
133464fec58eSTang Chen 
13358cd91aceSHaozhong Zhang     /*
13364a641010SThomas Huth      * When "acpi=off" is used with the Q35 machine type, no ACPI is built,
13378cd91aceSHaozhong Zhang      * but pcms->acpi_dev is still created. Check !acpi_enabled in
13388cd91aceSHaozhong Zhang      * addition to cover this case.
13398cd91aceSHaozhong Zhang      */
134050aef131SGerd Hoffmann     if (!x86ms->acpi_dev || !x86_machine_is_acpi_enabled(x86ms)) {
1341dcfe4805SMarkus Armbruster         error_setg(errp,
13428cd91aceSHaozhong Zhang                    "memory hotplug is not enabled: missing acpi device or acpi disabled");
1343dcfe4805SMarkus Armbruster         return;
134464fec58eSTang Chen     }
134564fec58eSTang Chen 
1346b097cc52SXiao Guangrong     if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
1347dcfe4805SMarkus Armbruster         error_setg(errp, "nvdimm device hot unplug is not supported yet.");
1348dcfe4805SMarkus Armbruster         return;
1349b097cc52SXiao Guangrong     }
1350b097cc52SXiao Guangrong 
135150aef131SGerd Hoffmann     hotplug_handler_unplug_request(x86ms->acpi_dev, dev,
1352dcfe4805SMarkus Armbruster                                    errp);
135364fec58eSTang Chen }
135464fec58eSTang Chen 
pc_memory_unplug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)1355bb6e2f7aSDavid Hildenbrand static void pc_memory_unplug(HotplugHandler *hotplug_dev,
1356f7d3e29dSTang Chen                              DeviceState *dev, Error **errp)
1357f7d3e29dSTang Chen {
1358f7d3e29dSTang Chen     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
135950aef131SGerd Hoffmann     X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
1360f7d3e29dSTang Chen     Error *local_err = NULL;
1361f7d3e29dSTang Chen 
136250aef131SGerd Hoffmann     hotplug_handler_unplug(x86ms->acpi_dev, dev, &local_err);
1363f7d3e29dSTang Chen     if (local_err) {
1364f7d3e29dSTang Chen         goto out;
1365f7d3e29dSTang Chen     }
1366f7d3e29dSTang Chen 
1367fd3416f5SDavid Hildenbrand     pc_dimm_unplug(PC_DIMM(dev), MACHINE(pcms));
1368981c3dcdSMarkus Armbruster     qdev_unrealize(dev);
1369f7d3e29dSTang Chen  out:
1370f7d3e29dSTang Chen     error_propagate(errp, local_err);
1371f7d3e29dSTang Chen }
1372f7d3e29dSTang Chen 
pc_hv_balloon_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)13739a52aa40SMaciej S. Szmigiero static void pc_hv_balloon_pre_plug(HotplugHandler *hotplug_dev,
13749a52aa40SMaciej S. Szmigiero                                    DeviceState *dev, Error **errp)
13759a52aa40SMaciej S. Szmigiero {
13769a52aa40SMaciej S. Szmigiero     /* The vmbus handler has no hotplug handler; we should never end up here. */
13779a52aa40SMaciej S. Szmigiero     g_assert(!dev->hotplugged);
13780e0bf77dSPhilippe Mathieu-Daudé     memory_device_pre_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev), errp);
13799a52aa40SMaciej S. Szmigiero }
13809a52aa40SMaciej S. Szmigiero 
pc_hv_balloon_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)13819a52aa40SMaciej S. Szmigiero static void pc_hv_balloon_plug(HotplugHandler *hotplug_dev,
13829a52aa40SMaciej S. Szmigiero                                DeviceState *dev, Error **errp)
13839a52aa40SMaciej S. Szmigiero {
13849a52aa40SMaciej S. Szmigiero     memory_device_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev));
13859a52aa40SMaciej S. Szmigiero }
13869a52aa40SMaciej S. Szmigiero 
pc_machine_device_pre_plug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)13874ec60c76SIgor Mammedov static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
13884ec60c76SIgor Mammedov                                           DeviceState *dev, Error **errp)
13894ec60c76SIgor Mammedov {
1390d468115bSDavid Hildenbrand     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
1391d468115bSDavid Hildenbrand         pc_memory_pre_plug(hotplug_dev, dev, errp);
1392d468115bSDavid Hildenbrand     } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
13930cca1a91SGerd Hoffmann         x86_cpu_pre_plug(hotplug_dev, dev, errp);
1394dbdf841bSDavid Hildenbrand     } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
1395dbdf841bSDavid Hildenbrand         virtio_md_pci_pre_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp);
139636efa250SJean-Philippe Brucker     } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
139736efa250SJean-Philippe Brucker         /* Declare the APIC range as the reserved MSI region */
139836efa250SJean-Philippe Brucker         char *resv_prop_str = g_strdup_printf("0xfee00000:0xfeefffff:%d",
139936efa250SJean-Philippe Brucker                                               VIRTIO_IOMMU_RESV_MEM_T_MSI);
140033f0c061SKevin Wolf         QList *reserved_regions = qlist_new();
140136efa250SJean-Philippe Brucker 
140233f0c061SKevin Wolf         qlist_append_str(reserved_regions, resv_prop_str);
140333f0c061SKevin Wolf         qdev_prop_set_array(dev, "reserved-regions", reserved_regions);
140433f0c061SKevin Wolf 
140536efa250SJean-Philippe Brucker         g_free(resv_prop_str);
140636efa250SJean-Philippe Brucker     }
140736efa250SJean-Philippe Brucker 
140836efa250SJean-Philippe Brucker     if (object_dynamic_cast(OBJECT(dev), TYPE_X86_IOMMU_DEVICE) ||
140936efa250SJean-Philippe Brucker         object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
14101b3bf138SJean-Philippe Brucker         PCMachineState *pcms = PC_MACHINE(hotplug_dev);
14111b3bf138SJean-Philippe Brucker 
14121b3bf138SJean-Philippe Brucker         if (pcms->iommu) {
14131b3bf138SJean-Philippe Brucker             error_setg(errp, "QEMU does not support multiple vIOMMUs "
14141b3bf138SJean-Philippe Brucker                        "for x86 yet.");
14151b3bf138SJean-Philippe Brucker             return;
14161b3bf138SJean-Philippe Brucker         }
14171b3bf138SJean-Philippe Brucker         pcms->iommu = dev;
14189a52aa40SMaciej S. Szmigiero     } else if (object_dynamic_cast(OBJECT(dev), TYPE_HV_BALLOON)) {
14199a52aa40SMaciej S. Szmigiero         pc_hv_balloon_pre_plug(hotplug_dev, dev, errp);
14204ec60c76SIgor Mammedov     }
14214ec60c76SIgor Mammedov }
14224ec60c76SIgor Mammedov 
pc_machine_device_plug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)142395bee274SIgor Mammedov static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
142495bee274SIgor Mammedov                                       DeviceState *dev, Error **errp)
142595bee274SIgor Mammedov {
142695bee274SIgor Mammedov     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
1427bb6e2f7aSDavid Hildenbrand         pc_memory_plug(hotplug_dev, dev, errp);
14285279569eSGu Zheng     } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
14290cca1a91SGerd Hoffmann         x86_cpu_plug(hotplug_dev, dev, errp);
1430dbdf841bSDavid Hildenbrand     } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
1431dbdf841bSDavid Hildenbrand         virtio_md_pci_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp);
14329a52aa40SMaciej S. Szmigiero     } else if (object_dynamic_cast(OBJECT(dev), TYPE_HV_BALLOON)) {
14339a52aa40SMaciej S. Szmigiero         pc_hv_balloon_plug(hotplug_dev, dev, errp);
143495bee274SIgor Mammedov     }
143595bee274SIgor Mammedov }
143695bee274SIgor Mammedov 
pc_machine_device_unplug_request_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)1437d9c5c5b8STang Chen static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
1438d9c5c5b8STang Chen                                                 DeviceState *dev, Error **errp)
1439d9c5c5b8STang Chen {
144064fec58eSTang Chen     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
1441bb6e2f7aSDavid Hildenbrand         pc_memory_unplug_request(hotplug_dev, dev, errp);
14428872c25aSIgor Mammedov     } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
14430cca1a91SGerd Hoffmann         x86_cpu_unplug_request_cb(hotplug_dev, dev, errp);
1444dbdf841bSDavid Hildenbrand     } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
1445dbdf841bSDavid Hildenbrand         virtio_md_pci_unplug_request(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev),
1446dbdf841bSDavid Hildenbrand                                      errp);
144764fec58eSTang Chen     } else {
1448d9c5c5b8STang Chen         error_setg(errp, "acpi: device unplug request for not supported device"
1449d9c5c5b8STang Chen                    " type: %s", object_get_typename(OBJECT(dev)));
1450d9c5c5b8STang Chen     }
145164fec58eSTang Chen }
1452d9c5c5b8STang Chen 
pc_machine_device_unplug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)1453232391c1STang Chen static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
1454232391c1STang Chen                                         DeviceState *dev, Error **errp)
1455232391c1STang Chen {
1456f7d3e29dSTang Chen     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
1457bb6e2f7aSDavid Hildenbrand         pc_memory_unplug(hotplug_dev, dev, errp);
14588872c25aSIgor Mammedov     } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
14590cca1a91SGerd Hoffmann         x86_cpu_unplug_cb(hotplug_dev, dev, errp);
1460dbdf841bSDavid Hildenbrand     } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
1461dbdf841bSDavid Hildenbrand         virtio_md_pci_unplug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp);
1462f7d3e29dSTang Chen     } else {
1463232391c1STang Chen         error_setg(errp, "acpi: device unplug for not supported device"
1464232391c1STang Chen                    " type: %s", object_get_typename(OBJECT(dev)));
1465232391c1STang Chen     }
1466f7d3e29dSTang Chen }
1467232391c1STang Chen 
pc_get_hotplug_handler(MachineState * machine,DeviceState * dev)1468285816d7SWei Yang static HotplugHandler *pc_get_hotplug_handler(MachineState *machine,
146995bee274SIgor Mammedov                                              DeviceState *dev)
147095bee274SIgor Mammedov {
14715279569eSGu Zheng     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
1472a0a49813SDavid Hildenbrand         object_dynamic_cast(OBJECT(dev), TYPE_CPU) ||
1473dbdf841bSDavid Hildenbrand         object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI) ||
147436efa250SJean-Philippe Brucker         object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) ||
14759a52aa40SMaciej S. Szmigiero         object_dynamic_cast(OBJECT(dev), TYPE_HV_BALLOON) ||
14761b3bf138SJean-Philippe Brucker         object_dynamic_cast(OBJECT(dev), TYPE_X86_IOMMU_DEVICE)) {
147795bee274SIgor Mammedov         return HOTPLUG_HANDLER(machine);
147895bee274SIgor Mammedov     }
147995bee274SIgor Mammedov 
148038aefb57SIgor Mammedov     return NULL;
148195bee274SIgor Mammedov }
148295bee274SIgor Mammedov 
pc_machine_get_vmport(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1483d7bce999SEric Blake static void pc_machine_get_vmport(Object *obj, Visitor *v, const char *name,
1484d7bce999SEric Blake                                   void *opaque, Error **errp)
14859b23cfb7SDr. David Alan Gilbert {
14869b23cfb7SDr. David Alan Gilbert     PCMachineState *pcms = PC_MACHINE(obj);
1487d1048befSDon Slutz     OnOffAuto vmport = pcms->vmport;
14889b23cfb7SDr. David Alan Gilbert 
148951e72bc1SEric Blake     visit_type_OnOffAuto(v, name, &vmport, errp);
14909b23cfb7SDr. David Alan Gilbert }
14919b23cfb7SDr. David Alan Gilbert 
pc_machine_set_vmport(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1492d7bce999SEric Blake static void pc_machine_set_vmport(Object *obj, Visitor *v, const char *name,
1493d7bce999SEric Blake                                   void *opaque, Error **errp)
14949b23cfb7SDr. David Alan Gilbert {
14959b23cfb7SDr. David Alan Gilbert     PCMachineState *pcms = PC_MACHINE(obj);
14969b23cfb7SDr. David Alan Gilbert 
149751e72bc1SEric Blake     visit_type_OnOffAuto(v, name, &pcms->vmport, errp);
14989b23cfb7SDr. David Alan Gilbert }
14999b23cfb7SDr. David Alan Gilbert 
pc_machine_get_fd_bootchk(Object * obj,Error ** errp)150084e945aaSPaolo Bonzini static bool pc_machine_get_fd_bootchk(Object *obj, Error **errp)
150184e945aaSPaolo Bonzini {
150284e945aaSPaolo Bonzini     PCMachineState *pcms = PC_MACHINE(obj);
150384e945aaSPaolo Bonzini 
150484e945aaSPaolo Bonzini     return pcms->fd_bootchk;
150584e945aaSPaolo Bonzini }
150684e945aaSPaolo Bonzini 
pc_machine_set_fd_bootchk(Object * obj,bool value,Error ** errp)150784e945aaSPaolo Bonzini static void pc_machine_set_fd_bootchk(Object *obj, bool value, Error **errp)
150884e945aaSPaolo Bonzini {
150984e945aaSPaolo Bonzini     PCMachineState *pcms = PC_MACHINE(obj);
151084e945aaSPaolo Bonzini 
151184e945aaSPaolo Bonzini     pcms->fd_bootchk = value;
151284e945aaSPaolo Bonzini }
151384e945aaSPaolo Bonzini 
pc_machine_get_smbus(Object * obj,Error ** errp)1514be232eb0SChao Peng static bool pc_machine_get_smbus(Object *obj, Error **errp)
1515be232eb0SChao Peng {
1516be232eb0SChao Peng     PCMachineState *pcms = PC_MACHINE(obj);
1517be232eb0SChao Peng 
1518f5878b03SCorey Minyard     return pcms->smbus_enabled;
1519be232eb0SChao Peng }
1520be232eb0SChao Peng 
pc_machine_set_smbus(Object * obj,bool value,Error ** errp)1521be232eb0SChao Peng static void pc_machine_set_smbus(Object *obj, bool value, Error **errp)
1522be232eb0SChao Peng {
1523be232eb0SChao Peng     PCMachineState *pcms = PC_MACHINE(obj);
1524be232eb0SChao Peng 
1525f5878b03SCorey Minyard     pcms->smbus_enabled = value;
1526be232eb0SChao Peng }
1527be232eb0SChao Peng 
pc_machine_get_sata(Object * obj,Error ** errp)1528272f0428SChao Peng static bool pc_machine_get_sata(Object *obj, Error **errp)
1529272f0428SChao Peng {
1530272f0428SChao Peng     PCMachineState *pcms = PC_MACHINE(obj);
1531272f0428SChao Peng 
1532f5878b03SCorey Minyard     return pcms->sata_enabled;
1533272f0428SChao Peng }
1534272f0428SChao Peng 
pc_machine_set_sata(Object * obj,bool value,Error ** errp)1535272f0428SChao Peng static void pc_machine_set_sata(Object *obj, bool value, Error **errp)
1536272f0428SChao Peng {
1537272f0428SChao Peng     PCMachineState *pcms = PC_MACHINE(obj);
1538272f0428SChao Peng 
1539f5878b03SCorey Minyard     pcms->sata_enabled = value;
1540272f0428SChao Peng }
1541272f0428SChao Peng 
pc_machine_get_hpet(Object * obj,Error ** errp)15420259c78cSEduardo Habkost static bool pc_machine_get_hpet(Object *obj, Error **errp)
15430259c78cSEduardo Habkost {
15440259c78cSEduardo Habkost     PCMachineState *pcms = PC_MACHINE(obj);
15450259c78cSEduardo Habkost 
15460259c78cSEduardo Habkost     return pcms->hpet_enabled;
15470259c78cSEduardo Habkost }
15480259c78cSEduardo Habkost 
pc_machine_set_hpet(Object * obj,bool value,Error ** errp)15490259c78cSEduardo Habkost static void pc_machine_set_hpet(Object *obj, bool value, Error **errp)
15500259c78cSEduardo Habkost {
15510259c78cSEduardo Habkost     PCMachineState *pcms = PC_MACHINE(obj);
15520259c78cSEduardo Habkost 
15530259c78cSEduardo Habkost     pcms->hpet_enabled = value;
15540259c78cSEduardo Habkost }
15550259c78cSEduardo Habkost 
pc_machine_get_i8042(Object * obj,Error ** errp)15564ccd5fe2SJoelle van Dyne static bool pc_machine_get_i8042(Object *obj, Error **errp)
15574ccd5fe2SJoelle van Dyne {
15584ccd5fe2SJoelle van Dyne     PCMachineState *pcms = PC_MACHINE(obj);
15594ccd5fe2SJoelle van Dyne 
15604ccd5fe2SJoelle van Dyne     return pcms->i8042_enabled;
15614ccd5fe2SJoelle van Dyne }
15624ccd5fe2SJoelle van Dyne 
pc_machine_set_i8042(Object * obj,bool value,Error ** errp)15634ccd5fe2SJoelle van Dyne static void pc_machine_set_i8042(Object *obj, bool value, Error **errp)
15644ccd5fe2SJoelle van Dyne {
15654ccd5fe2SJoelle van Dyne     PCMachineState *pcms = PC_MACHINE(obj);
15664ccd5fe2SJoelle van Dyne 
15674ccd5fe2SJoelle van Dyne     pcms->i8042_enabled = value;
15684ccd5fe2SJoelle van Dyne }
15694ccd5fe2SJoelle van Dyne 
pc_machine_get_default_bus_bypass_iommu(Object * obj,Error ** errp)1570c9e96b04SXingang Wang static bool pc_machine_get_default_bus_bypass_iommu(Object *obj, Error **errp)
1571c9e96b04SXingang Wang {
1572c9e96b04SXingang Wang     PCMachineState *pcms = PC_MACHINE(obj);
1573c9e96b04SXingang Wang 
1574c9e96b04SXingang Wang     return pcms->default_bus_bypass_iommu;
1575c9e96b04SXingang Wang }
1576c9e96b04SXingang Wang 
pc_machine_set_default_bus_bypass_iommu(Object * obj,bool value,Error ** errp)1577c9e96b04SXingang Wang static void pc_machine_set_default_bus_bypass_iommu(Object *obj, bool value,
1578c9e96b04SXingang Wang                                                     Error **errp)
1579c9e96b04SXingang Wang {
1580c9e96b04SXingang Wang     PCMachineState *pcms = PC_MACHINE(obj);
1581c9e96b04SXingang Wang 
1582c9e96b04SXingang Wang     pcms->default_bus_bypass_iommu = value;
1583c9e96b04SXingang Wang }
1584c9e96b04SXingang Wang 
pc_machine_get_smbios_ep(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)15850e4edb3bSEduardo Habkost static void pc_machine_get_smbios_ep(Object *obj, Visitor *v, const char *name,
15860e4edb3bSEduardo Habkost                                      void *opaque, Error **errp)
15870e4edb3bSEduardo Habkost {
15880e4edb3bSEduardo Habkost     PCMachineState *pcms = PC_MACHINE(obj);
15890e4edb3bSEduardo Habkost     SmbiosEntryPointType smbios_entry_point_type = pcms->smbios_entry_point_type;
15900e4edb3bSEduardo Habkost 
15910e4edb3bSEduardo Habkost     visit_type_SmbiosEntryPointType(v, name, &smbios_entry_point_type, errp);
15920e4edb3bSEduardo Habkost }
15930e4edb3bSEduardo Habkost 
pc_machine_set_smbios_ep(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)15940e4edb3bSEduardo Habkost static void pc_machine_set_smbios_ep(Object *obj, Visitor *v, const char *name,
15950e4edb3bSEduardo Habkost                                      void *opaque, Error **errp)
15960e4edb3bSEduardo Habkost {
15970e4edb3bSEduardo Habkost     PCMachineState *pcms = PC_MACHINE(obj);
15980e4edb3bSEduardo Habkost 
15990e4edb3bSEduardo Habkost     visit_type_SmbiosEntryPointType(v, name, &pcms->smbios_entry_point_type, errp);
16000e4edb3bSEduardo Habkost }
16010e4edb3bSEduardo Habkost 
pc_machine_get_max_ram_below_4g(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)16029a45729dSGerd Hoffmann static void pc_machine_get_max_ram_below_4g(Object *obj, Visitor *v,
16039a45729dSGerd Hoffmann                                             const char *name, void *opaque,
16049a45729dSGerd Hoffmann                                             Error **errp)
16059a45729dSGerd Hoffmann {
16069a45729dSGerd Hoffmann     PCMachineState *pcms = PC_MACHINE(obj);
16079a45729dSGerd Hoffmann     uint64_t value = pcms->max_ram_below_4g;
16089a45729dSGerd Hoffmann 
16099a45729dSGerd Hoffmann     visit_type_size(v, name, &value, errp);
16109a45729dSGerd Hoffmann }
16119a45729dSGerd Hoffmann 
pc_machine_set_max_ram_below_4g(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)16129a45729dSGerd Hoffmann static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
16139a45729dSGerd Hoffmann                                             const char *name, void *opaque,
16149a45729dSGerd Hoffmann                                             Error **errp)
16159a45729dSGerd Hoffmann {
16169a45729dSGerd Hoffmann     PCMachineState *pcms = PC_MACHINE(obj);
16179a45729dSGerd Hoffmann     uint64_t value;
16189a45729dSGerd Hoffmann 
1619668f62ecSMarkus Armbruster     if (!visit_type_size(v, name, &value, errp)) {
16209a45729dSGerd Hoffmann         return;
16219a45729dSGerd Hoffmann     }
16229a45729dSGerd Hoffmann     if (value > 4 * GiB) {
1623dcfe4805SMarkus Armbruster         error_setg(errp,
16249a45729dSGerd Hoffmann                    "Machine option 'max-ram-below-4g=%"PRIu64
16259a45729dSGerd Hoffmann                    "' expects size less than or equal to 4G", value);
16269a45729dSGerd Hoffmann         return;
16279a45729dSGerd Hoffmann     }
16289a45729dSGerd Hoffmann 
16299a45729dSGerd Hoffmann     if (value < 1 * MiB) {
16309a45729dSGerd Hoffmann         warn_report("Only %" PRIu64 " bytes of RAM below the 4GiB boundary,"
16319a45729dSGerd Hoffmann                     "BIOS may not work with less than 1MiB", value);
16329a45729dSGerd Hoffmann     }
16339a45729dSGerd Hoffmann 
16349a45729dSGerd Hoffmann     pcms->max_ram_below_4g = value;
16359a45729dSGerd Hoffmann }
16369a45729dSGerd Hoffmann 
pc_machine_get_max_fw_size(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)16370657c657SErich-McMillan static void pc_machine_get_max_fw_size(Object *obj, Visitor *v,
16380657c657SErich-McMillan                                        const char *name, void *opaque,
16390657c657SErich-McMillan                                        Error **errp)
16400657c657SErich-McMillan {
16410657c657SErich-McMillan     PCMachineState *pcms = PC_MACHINE(obj);
16420657c657SErich-McMillan     uint64_t value = pcms->max_fw_size;
16430657c657SErich-McMillan 
16440657c657SErich-McMillan     visit_type_size(v, name, &value, errp);
16450657c657SErich-McMillan }
16460657c657SErich-McMillan 
pc_machine_set_max_fw_size(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)16470657c657SErich-McMillan static void pc_machine_set_max_fw_size(Object *obj, Visitor *v,
16480657c657SErich-McMillan                                        const char *name, void *opaque,
16490657c657SErich-McMillan                                        Error **errp)
16500657c657SErich-McMillan {
16510657c657SErich-McMillan     PCMachineState *pcms = PC_MACHINE(obj);
16520657c657SErich-McMillan     uint64_t value;
16530657c657SErich-McMillan 
1654d1c81c34SMarkus Armbruster     if (!visit_type_size(v, name, &value, errp)) {
16550657c657SErich-McMillan         return;
16560657c657SErich-McMillan     }
16570657c657SErich-McMillan 
16580657c657SErich-McMillan     /*
16590657c657SErich-McMillan      * We don't have a theoretically justifiable exact lower bound on the base
16600657c657SErich-McMillan      * address of any flash mapping. In practice, the IO-APIC MMIO range is
16610657c657SErich-McMillan      * [0xFEE00000..0xFEE01000] -- see IO_APIC_DEFAULT_ADDRESS --, leaving free
1662306764eeSLaszlo Ersek      * only 18MiB-4KiB below 4GiB. For now, restrict the cumulative mapping to
1663306764eeSLaszlo Ersek      * 16MiB in size.
16640657c657SErich-McMillan      */
16650657c657SErich-McMillan     if (value > 16 * MiB) {
16660657c657SErich-McMillan         error_setg(errp,
16670657c657SErich-McMillan                    "User specified max allowed firmware size %" PRIu64 " is "
1668bad5cfcdSMichael Tokarev                    "greater than 16MiB. If combined firmware size exceeds "
16690657c657SErich-McMillan                    "16MiB the system may not boot, or experience intermittent"
16700657c657SErich-McMillan                    "stability issues.",
16710657c657SErich-McMillan                    value);
16720657c657SErich-McMillan         return;
16730657c657SErich-McMillan     }
16740657c657SErich-McMillan 
16750657c657SErich-McMillan     pcms->max_fw_size = value;
16760657c657SErich-McMillan }
16770657c657SErich-McMillan 
1678602b4582SMarian Postevca 
pc_machine_initfn(Object * obj)1679bf1e8939SIgor Mammedov static void pc_machine_initfn(Object *obj)
1680bf1e8939SIgor Mammedov {
1681c87b1520SDon Slutz     PCMachineState *pcms = PC_MACHINE(obj);
1682bf376f30SSuravee Suthikulpanit     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
1683c87b1520SDon Slutz 
168497fd1ea8SJulio Montes #ifdef CONFIG_VMPORT
1685d1048befSDon Slutz     pcms->vmport = ON_OFF_AUTO_AUTO;
168697fd1ea8SJulio Montes #else
168797fd1ea8SJulio Montes     pcms->vmport = ON_OFF_AUTO_OFF;
168897fd1ea8SJulio Montes #endif /* CONFIG_VMPORT */
16899a45729dSGerd Hoffmann     pcms->max_ram_below_4g = 0; /* use default */
1690bf376f30SSuravee Suthikulpanit     pcms->smbios_entry_point_type = pcmc->default_smbios_ep_type;
1691aa0c9aecSBernhard Beschow     pcms->south_bridge = pcmc->default_south_bridge;
16920e4edb3bSEduardo Habkost 
1693021746c1SWei Liu     /* acpi build is enabled by default if machine supports it */
1694abe10037SSuravee Suthikulpanit     pcms->acpi_build_enabled = pcmc->has_acpi_build;
1695f5878b03SCorey Minyard     pcms->smbus_enabled = true;
1696f5878b03SCorey Minyard     pcms->sata_enabled = true;
16974ccd5fe2SJoelle van Dyne     pcms->i8042_enabled = true;
16980657c657SErich-McMillan     pcms->max_fw_size = 8 * MiB;
16990259c78cSEduardo Habkost #ifdef CONFIG_HPET
17000259c78cSEduardo Habkost     pcms->hpet_enabled = true;
17010259c78cSEduardo Habkost #endif
170284e945aaSPaolo Bonzini     pcms->fd_bootchk = true;
1703c9e96b04SXingang Wang     pcms->default_bus_bypass_iommu = false;
1704ebc29e1bSMarkus Armbruster 
1705f2cb9f34SBernhard Beschow     pc_system_flash_create(pcms);
17066b8d1416SGerd Hoffmann     pcms->pcspk = isa_new(TYPE_PC_SPEAKER);
17072e16ec05SGerd Hoffmann     object_property_add_alias(OBJECT(pcms), "pcspk-audiodev",
17082e16ec05SGerd Hoffmann                               OBJECT(pcms->pcspk), "audiodev");
1709aab1b3eeSPhilippe Mathieu-Daudé     if (pcmc->pci_enabled) {
17101ebf9001SJonathan Cameron         cxl_machine_init(obj, &pcms->cxl_devices_state);
1711aab1b3eeSPhilippe Mathieu-Daudé     }
17124d3457feSBernhard Beschow 
17134d3457feSBernhard Beschow     pcms->machine_done.notify = pc_machine_done;
17144d3457feSBernhard Beschow     qemu_add_machine_init_done_notifier(&pcms->machine_done);
1715bf1e8939SIgor Mammedov }
1716bf1e8939SIgor Mammedov 
pc_machine_reset(MachineState * machine,ResetType type)17171b063fe2SJuraj Marcin static void pc_machine_reset(MachineState *machine, ResetType type)
1718ae50c55aSZhu Guihua {
1719ae50c55aSZhu Guihua     CPUState *cs;
1720ae50c55aSZhu Guihua     X86CPU *cpu;
1721ae50c55aSZhu Guihua 
17221b063fe2SJuraj Marcin     qemu_devices_reset(type);
1723ae50c55aSZhu Guihua 
1724ae50c55aSZhu Guihua     /* Reset APIC after devices have been reset to cancel
1725ae50c55aSZhu Guihua      * any changes that qemu_devices_reset() might have done.
1726ae50c55aSZhu Guihua      */
1727ae50c55aSZhu Guihua     CPU_FOREACH(cs) {
1728ae50c55aSZhu Guihua         cpu = X86_CPU(cs);
1729ae50c55aSZhu Guihua 
1730ec19444aSMaciej S. Szmigiero         x86_cpu_after_reset(cpu);
1731ae50c55aSZhu Guihua     }
1732ae50c55aSZhu Guihua }
1733ae50c55aSZhu Guihua 
pc_machine_wakeup(MachineState * machine)1734c508bd12SNicholas Piggin static void pc_machine_wakeup(MachineState *machine)
1735c508bd12SNicholas Piggin {
1736c508bd12SNicholas Piggin     cpu_synchronize_all_states();
1737759cbb4eSJuraj Marcin     pc_machine_reset(machine, RESET_TYPE_WAKEUP);
1738c508bd12SNicholas Piggin     cpu_synchronize_all_post_reset();
1739c508bd12SNicholas Piggin }
1740c508bd12SNicholas Piggin 
pc_hotplug_allowed(MachineState * ms,DeviceState * dev,Error ** errp)1741c6cbc29dSPeter Xu static bool pc_hotplug_allowed(MachineState *ms, DeviceState *dev, Error **errp)
1742c6cbc29dSPeter Xu {
1743c6cbc29dSPeter Xu     X86IOMMUState *iommu = x86_iommu_get_default();
1744c6cbc29dSPeter Xu     IntelIOMMUState *intel_iommu;
1745c6cbc29dSPeter Xu 
1746c6cbc29dSPeter Xu     if (iommu &&
1747c6cbc29dSPeter Xu         object_dynamic_cast((Object *)iommu, TYPE_INTEL_IOMMU_DEVICE) &&
1748c6cbc29dSPeter Xu         object_dynamic_cast((Object *)dev, "vfio-pci")) {
1749c6cbc29dSPeter Xu         intel_iommu = INTEL_IOMMU_DEVICE(iommu);
1750c6cbc29dSPeter Xu         if (!intel_iommu->caching_mode) {
1751c6cbc29dSPeter Xu             error_setg(errp, "Device assignment is not allowed without "
1752c6cbc29dSPeter Xu                        "enabling caching-mode=on for Intel IOMMU.");
1753c6cbc29dSPeter Xu             return false;
1754c6cbc29dSPeter Xu         }
1755c6cbc29dSPeter Xu     }
1756c6cbc29dSPeter Xu 
1757c6cbc29dSPeter Xu     return true;
1758c6cbc29dSPeter Xu }
1759c6cbc29dSPeter Xu 
pc_machine_class_init(ObjectClass * oc,void * data)176095bee274SIgor Mammedov static void pc_machine_class_init(ObjectClass *oc, void *data)
176195bee274SIgor Mammedov {
176295bee274SIgor Mammedov     MachineClass *mc = MACHINE_CLASS(oc);
17636e6d59a9SBernhard Beschow     X86MachineClass *x86mc = X86_MACHINE_CLASS(oc);
176495bee274SIgor Mammedov     PCMachineClass *pcmc = PC_MACHINE_CLASS(oc);
176595bee274SIgor Mammedov     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
176695bee274SIgor Mammedov 
17677102fa70SEduardo Habkost     pcmc->pci_enabled = true;
17687102fa70SEduardo Habkost     pcmc->has_acpi_build = true;
17697102fa70SEduardo Habkost     pcmc->smbios_defaults = true;
17707102fa70SEduardo Habkost     pcmc->gigabyte_align = true;
17717102fa70SEduardo Habkost     pcmc->has_reserved_memory = true;
1772b3e6982bSJoao Martins     pcmc->enforce_amd_1tb_hole = true;
1773a44ea3faSBernhard Beschow     pcmc->isa_bios_alias = true;
1774fda672b5SStefano Garzarella     pcmc->pvh_enabled = true;
17758700a984SVitaly Kuznetsov     pcmc->kvmclock_create_always = true;
17766e6d59a9SBernhard Beschow     x86mc->apic_xrupt_override = true;
1777debbdc00SIgor Mammedov     assert(!mc->get_hotplug_handler);
1778285816d7SWei Yang     mc->get_hotplug_handler = pc_get_hotplug_handler;
1779c6cbc29dSPeter Xu     mc->hotplug_allowed = pc_hotplug_allowed;
17807b8be49dSDou Liyang     mc->auto_enable_numa_with_memhp = true;
1781195784a0SDavid Hildenbrand     mc->auto_enable_numa_with_memdev = true;
1782c5514d0eSIgor Mammedov     mc->has_hotpluggable_cpus = true;
178341742767SEduardo Habkost     mc->default_boot_order = "cad";
17842059839bSMarkus Armbruster     mc->block_default_type = IF_IDE;
17854458fb3aSEduardo Habkost     mc->max_cpus = 255;
1786ae50c55aSZhu Guihua     mc->reset = pc_machine_reset;
1787c508bd12SNicholas Piggin     mc->wakeup = pc_machine_wakeup;
17884ec60c76SIgor Mammedov     hc->pre_plug = pc_machine_device_pre_plug_cb;
178995bee274SIgor Mammedov     hc->plug = pc_machine_device_plug_cb;
1790d9c5c5b8STang Chen     hc->unplug_request = pc_machine_device_unplug_request_cb;
1791232391c1STang Chen     hc->unplug = pc_machine_device_unplug_cb;
1792311ca98dSIgor Mammedov     mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE;
1793f6a0d06bSEric Auger     mc->nvdimm_supported = true;
1794e4a97a89SYanan Wang     mc->smp_props.dies_supported = true;
179568074874SZhao Liu     mc->smp_props.modules_supported = true;
1796bd457782SIgor Mammedov     mc->default_ram_id = "pc.ram";
17972c7c45b3SIgor Mammedov     pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_AUTO;
17980efc257dSEduardo Habkost 
17999a45729dSGerd Hoffmann     object_class_property_add(oc, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
18009a45729dSGerd Hoffmann         pc_machine_get_max_ram_below_4g, pc_machine_set_max_ram_below_4g,
18019a45729dSGerd Hoffmann         NULL, NULL);
18029a45729dSGerd Hoffmann     object_class_property_set_description(oc, PC_MACHINE_MAX_RAM_BELOW_4G,
18039a45729dSGerd Hoffmann         "Maximum ram below the 4G boundary (32bit boundary)");
18049a45729dSGerd Hoffmann 
18050efc257dSEduardo Habkost     object_class_property_add(oc, PC_MACHINE_VMPORT, "OnOffAuto",
18060efc257dSEduardo Habkost         pc_machine_get_vmport, pc_machine_set_vmport,
1807d2623129SMarkus Armbruster         NULL, NULL);
18080efc257dSEduardo Habkost     object_class_property_set_description(oc, PC_MACHINE_VMPORT,
18097eecec7dSMarkus Armbruster         "Enable vmport (pc & q35)");
18100efc257dSEduardo Habkost 
1811be232eb0SChao Peng     object_class_property_add_bool(oc, PC_MACHINE_SMBUS,
1812d2623129SMarkus Armbruster         pc_machine_get_smbus, pc_machine_set_smbus);
181344bff376SThomas Huth     object_class_property_set_description(oc, PC_MACHINE_SMBUS,
181444bff376SThomas Huth         "Enable/disable system management bus");
1815272f0428SChao Peng 
1816272f0428SChao Peng     object_class_property_add_bool(oc, PC_MACHINE_SATA,
1817d2623129SMarkus Armbruster         pc_machine_get_sata, pc_machine_set_sata);
181844bff376SThomas Huth     object_class_property_set_description(oc, PC_MACHINE_SATA,
181944bff376SThomas Huth         "Enable/disable Serial ATA bus");
1820feddd2fdSChao Peng 
18210259c78cSEduardo Habkost     object_class_property_add_bool(oc, "hpet",
18220259c78cSEduardo Habkost         pc_machine_get_hpet, pc_machine_set_hpet);
182344bff376SThomas Huth     object_class_property_set_description(oc, "hpet",
182444bff376SThomas Huth         "Enable/disable high precision event timer emulation");
18250657c657SErich-McMillan 
18264ccd5fe2SJoelle van Dyne     object_class_property_add_bool(oc, PC_MACHINE_I8042,
18274ccd5fe2SJoelle van Dyne         pc_machine_get_i8042, pc_machine_set_i8042);
1828a711afbbSKamil Szczęk     object_class_property_set_description(oc, PC_MACHINE_I8042,
1829a711afbbSKamil Szczęk         "Enable/disable Intel 8042 PS/2 controller emulation");
18304ccd5fe2SJoelle van Dyne 
1831739b3863SJean-Philippe Brucker     object_class_property_add_bool(oc, "default-bus-bypass-iommu",
1832c9e96b04SXingang Wang         pc_machine_get_default_bus_bypass_iommu,
1833c9e96b04SXingang Wang         pc_machine_set_default_bus_bypass_iommu);
1834c9e96b04SXingang Wang 
18350657c657SErich-McMillan     object_class_property_add(oc, PC_MACHINE_MAX_FW_SIZE, "size",
18360657c657SErich-McMillan         pc_machine_get_max_fw_size, pc_machine_set_max_fw_size,
18370657c657SErich-McMillan         NULL, NULL);
18380657c657SErich-McMillan     object_class_property_set_description(oc, PC_MACHINE_MAX_FW_SIZE,
18390657c657SErich-McMillan         "Maximum combined firmware size");
18400e4edb3bSEduardo Habkost 
18410e4edb3bSEduardo Habkost     object_class_property_add(oc, PC_MACHINE_SMBIOS_EP, "str",
18420e4edb3bSEduardo Habkost         pc_machine_get_smbios_ep, pc_machine_set_smbios_ep,
18430e4edb3bSEduardo Habkost         NULL, NULL);
18440e4edb3bSEduardo Habkost     object_class_property_set_description(oc, PC_MACHINE_SMBIOS_EP,
18450e4edb3bSEduardo Habkost         "SMBIOS Entry Point type [32, 64]");
184684e945aaSPaolo Bonzini 
184784e945aaSPaolo Bonzini     object_class_property_add_bool(oc, "fd-bootchk",
184884e945aaSPaolo Bonzini         pc_machine_get_fd_bootchk,
184984e945aaSPaolo Bonzini         pc_machine_set_fd_bootchk);
185095bee274SIgor Mammedov }
185195bee274SIgor Mammedov 
1852d5747cacSIgor Mammedov static const TypeInfo pc_machine_info = {
1853d5747cacSIgor Mammedov     .name = TYPE_PC_MACHINE,
1854f0bb276bSPaolo Bonzini     .parent = TYPE_X86_MACHINE,
1855d5747cacSIgor Mammedov     .abstract = true,
1856d5747cacSIgor Mammedov     .instance_size = sizeof(PCMachineState),
1857bf1e8939SIgor Mammedov     .instance_init = pc_machine_initfn,
1858d5747cacSIgor Mammedov     .class_size = sizeof(PCMachineClass),
185995bee274SIgor Mammedov     .class_init = pc_machine_class_init,
186095bee274SIgor Mammedov     .interfaces = (InterfaceInfo[]) {
186195bee274SIgor Mammedov          { TYPE_HOTPLUG_HANDLER },
186295bee274SIgor Mammedov          { }
186395bee274SIgor Mammedov     },
1864d5747cacSIgor Mammedov };
1865d5747cacSIgor Mammedov 
pc_machine_register_types(void)1866d5747cacSIgor Mammedov static void pc_machine_register_types(void)
1867d5747cacSIgor Mammedov {
1868d5747cacSIgor Mammedov     type_register_static(&pc_machine_info);
1869d5747cacSIgor Mammedov }
1870d5747cacSIgor Mammedov 
1871d5747cacSIgor Mammedov type_init(pc_machine_register_types)
1872