149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini * ACPI implementation
349ab747fSPaolo Bonzini *
449ab747fSPaolo Bonzini * Copyright (c) 2006 Fabrice Bellard
549ab747fSPaolo Bonzini *
649ab747fSPaolo Bonzini * This library is free software; you can redistribute it and/or
749ab747fSPaolo Bonzini * modify it under the terms of the GNU Lesser General Public
861f3c91aSChetan Pant * License version 2.1 as published by the Free Software Foundation.
949ab747fSPaolo Bonzini *
1049ab747fSPaolo Bonzini * This library is distributed in the hope that it will be useful,
1149ab747fSPaolo Bonzini * but WITHOUT ANY WARRANTY; without even the implied warranty of
1249ab747fSPaolo Bonzini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1349ab747fSPaolo Bonzini * Lesser General Public License for more details.
1449ab747fSPaolo Bonzini *
1549ab747fSPaolo Bonzini * You should have received a copy of the GNU Lesser General Public
1649ab747fSPaolo Bonzini * License along with this library; if not, see <http://www.gnu.org/licenses/>
1749ab747fSPaolo Bonzini *
1849ab747fSPaolo Bonzini * Contributions after 2012-01-13 are licensed under the terms of the
1949ab747fSPaolo Bonzini * GNU GPL, version 2 or (at your option) any later version.
2049ab747fSPaolo Bonzini */
2171e8a915SMarkus Armbruster
22b6a0aa05SPeter Maydell #include "qemu/osdep.h"
2364552b6bSMarkus Armbruster #include "hw/irq.h"
2449ab747fSPaolo Bonzini #include "hw/isa/apm.h"
2549ab747fSPaolo Bonzini #include "hw/i2c/pm_smbus.h"
2649ab747fSPaolo Bonzini #include "hw/pci/pci.h"
27a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
2849ab747fSPaolo Bonzini #include "hw/acpi/acpi.h"
292bfd0845SMark Cave-Ayland #include "hw/acpi/pcihp.h"
302bfd0845SMark Cave-Ayland #include "hw/acpi/piix4.h"
3154d31236SMarkus Armbruster #include "sysemu/runstate.h"
3249ab747fSPaolo Bonzini #include "sysemu/sysemu.h"
33da278d58SPhilippe Mathieu-Daudé #include "sysemu/xen.h"
34da34e65cSMarkus Armbruster #include "qapi/error.h"
3549ab747fSPaolo Bonzini #include "qemu/range.h"
3681cea5e7SIgor Mammedov #include "hw/acpi/cpu_hotplug.h"
375e1b5d93SIgor Mammedov #include "hw/acpi/cpu.h"
38c24d5e0bSIgor Mammedov #include "hw/hotplug.h"
3934774320SIgor Mammedov #include "hw/mem/pc-dimm.h"
40132a908bSPhilippe Mathieu-Daudé #include "hw/mem/nvdimm.h"
4134774320SIgor Mammedov #include "hw/acpi/memory_hotplug.h"
4243f50410SIgor Mammedov #include "hw/acpi/acpi_dev_interface.h"
43d6454270SMarkus Armbruster #include "migration/vmstate.h"
442e5b09fdSMarkus Armbruster #include "hw/core/cpu.h"
45db1015e9SEduardo Habkost #include "qom/object.h"
4649ab747fSPaolo Bonzini
4749ab747fSPaolo Bonzini #define GPE_BASE 0xafe0
4849ab747fSPaolo Bonzini #define GPE_LEN 4
4949ab747fSPaolo Bonzini
50caf108bcSJulia Suvorova #define ACPI_PCIHP_ADDR_PIIX4 0xae00
51caf108bcSJulia Suvorova
5249ab747fSPaolo Bonzini struct pci_status {
5349ab747fSPaolo Bonzini uint32_t up; /* deprecated, maintained for migration compatibility */
5449ab747fSPaolo Bonzini uint32_t down;
5549ab747fSPaolo Bonzini };
5649ab747fSPaolo Bonzini
5749ab747fSPaolo Bonzini static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
5849ab747fSPaolo Bonzini PCIBus *bus, PIIX4PMState *s);
5949ab747fSPaolo Bonzini
6049ab747fSPaolo Bonzini #define ACPI_ENABLE 0xf1
6149ab747fSPaolo Bonzini #define ACPI_DISABLE 0xf0
6249ab747fSPaolo Bonzini
pm_tmr_timer(ACPIREGS * ar)6349ab747fSPaolo Bonzini static void pm_tmr_timer(ACPIREGS *ar)
6449ab747fSPaolo Bonzini {
6549ab747fSPaolo Bonzini PIIX4PMState *s = container_of(ar, PIIX4PMState, ar);
6606313503SIgor Mammedov acpi_update_sci(&s->ar, s->irq);
6749ab747fSPaolo Bonzini }
6849ab747fSPaolo Bonzini
apm_ctrl_changed(uint32_t val,void * arg)6949ab747fSPaolo Bonzini static void apm_ctrl_changed(uint32_t val, void *arg)
7049ab747fSPaolo Bonzini {
7149ab747fSPaolo Bonzini PIIX4PMState *s = arg;
726a6b5580SAndreas Färber PCIDevice *d = PCI_DEVICE(s);
7349ab747fSPaolo Bonzini
7449ab747fSPaolo Bonzini /* ACPI specs 3.0, 4.7.2.5 */
7549ab747fSPaolo Bonzini acpi_pm1_cnt_update(&s->ar, val == ACPI_ENABLE, val == ACPI_DISABLE);
76afd6895bSPaolo Bonzini if (val == ACPI_ENABLE || val == ACPI_DISABLE) {
77afd6895bSPaolo Bonzini return;
78afd6895bSPaolo Bonzini }
7949ab747fSPaolo Bonzini
806a6b5580SAndreas Färber if (d->config[0x5b] & (1 << 1)) {
8149ab747fSPaolo Bonzini if (s->smi_irq) {
8249ab747fSPaolo Bonzini qemu_irq_raise(s->smi_irq);
8349ab747fSPaolo Bonzini }
8449ab747fSPaolo Bonzini }
8549ab747fSPaolo Bonzini }
8649ab747fSPaolo Bonzini
pm_io_space_update(PIIX4PMState * s)8749ab747fSPaolo Bonzini static void pm_io_space_update(PIIX4PMState *s)
8849ab747fSPaolo Bonzini {
896a6b5580SAndreas Färber PCIDevice *d = PCI_DEVICE(s);
9049ab747fSPaolo Bonzini
91277e9340SMichael S. Tsirkin s->io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x40));
92277e9340SMichael S. Tsirkin s->io_base &= 0xffc0;
9349ab747fSPaolo Bonzini
9449ab747fSPaolo Bonzini memory_region_transaction_begin();
956a6b5580SAndreas Färber memory_region_set_enabled(&s->io, d->config[0x80] & 1);
96277e9340SMichael S. Tsirkin memory_region_set_address(&s->io, s->io_base);
9749ab747fSPaolo Bonzini memory_region_transaction_commit();
9849ab747fSPaolo Bonzini }
9949ab747fSPaolo Bonzini
smbus_io_space_update(PIIX4PMState * s)10049ab747fSPaolo Bonzini static void smbus_io_space_update(PIIX4PMState *s)
10149ab747fSPaolo Bonzini {
1026a6b5580SAndreas Färber PCIDevice *d = PCI_DEVICE(s);
1036a6b5580SAndreas Färber
1046a6b5580SAndreas Färber s->smb_io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x90));
10549ab747fSPaolo Bonzini s->smb_io_base &= 0xffc0;
10649ab747fSPaolo Bonzini
10749ab747fSPaolo Bonzini memory_region_transaction_begin();
1086a6b5580SAndreas Färber memory_region_set_enabled(&s->smb.io, d->config[0xd2] & 1);
10949ab747fSPaolo Bonzini memory_region_set_address(&s->smb.io, s->smb_io_base);
11049ab747fSPaolo Bonzini memory_region_transaction_commit();
11149ab747fSPaolo Bonzini }
11249ab747fSPaolo Bonzini
pm_write_config(PCIDevice * d,uint32_t address,uint32_t val,int len)11349ab747fSPaolo Bonzini static void pm_write_config(PCIDevice *d,
11449ab747fSPaolo Bonzini uint32_t address, uint32_t val, int len)
11549ab747fSPaolo Bonzini {
11649ab747fSPaolo Bonzini pci_default_write_config(d, address, val, len);
11749ab747fSPaolo Bonzini if (range_covers_byte(address, len, 0x80) ||
11849ab747fSPaolo Bonzini ranges_overlap(address, len, 0x40, 4)) {
11949ab747fSPaolo Bonzini pm_io_space_update((PIIX4PMState *)d);
12049ab747fSPaolo Bonzini }
12149ab747fSPaolo Bonzini if (range_covers_byte(address, len, 0xd2) ||
12249ab747fSPaolo Bonzini ranges_overlap(address, len, 0x90, 4)) {
12349ab747fSPaolo Bonzini smbus_io_space_update((PIIX4PMState *)d);
12449ab747fSPaolo Bonzini }
12549ab747fSPaolo Bonzini }
12649ab747fSPaolo Bonzini
vmstate_acpi_post_load(void * opaque,int version_id)12749ab747fSPaolo Bonzini static int vmstate_acpi_post_load(void *opaque, int version_id)
12849ab747fSPaolo Bonzini {
12949ab747fSPaolo Bonzini PIIX4PMState *s = opaque;
13049ab747fSPaolo Bonzini
13149ab747fSPaolo Bonzini pm_io_space_update(s);
1322b4e573cSCorey Minyard smbus_io_space_update(s);
13349ab747fSPaolo Bonzini return 0;
13449ab747fSPaolo Bonzini }
13549ab747fSPaolo Bonzini
13649ab747fSPaolo Bonzini #define VMSTATE_GPE_ARRAY(_field, _state) \
13749ab747fSPaolo Bonzini { \
13849ab747fSPaolo Bonzini .name = (stringify(_field)), \
13949ab747fSPaolo Bonzini .version_id = 0, \
14049ab747fSPaolo Bonzini .info = &vmstate_info_uint16, \
14149ab747fSPaolo Bonzini .size = sizeof(uint16_t), \
14249ab747fSPaolo Bonzini .flags = VMS_SINGLE | VMS_POINTER, \
14349ab747fSPaolo Bonzini .offset = vmstate_offset_pointer(_state, _field, uint8_t), \
14449ab747fSPaolo Bonzini }
14549ab747fSPaolo Bonzini
14649ab747fSPaolo Bonzini static const VMStateDescription vmstate_gpe = {
14749ab747fSPaolo Bonzini .name = "gpe",
14849ab747fSPaolo Bonzini .version_id = 1,
14949ab747fSPaolo Bonzini .minimum_version_id = 1,
150c559ba57SRichard Henderson .fields = (const VMStateField[]) {
15149ab747fSPaolo Bonzini VMSTATE_GPE_ARRAY(sts, ACPIGPE),
15249ab747fSPaolo Bonzini VMSTATE_GPE_ARRAY(en, ACPIGPE),
15349ab747fSPaolo Bonzini VMSTATE_END_OF_LIST()
15449ab747fSPaolo Bonzini }
15549ab747fSPaolo Bonzini };
15649ab747fSPaolo Bonzini
15749ab747fSPaolo Bonzini static const VMStateDescription vmstate_pci_status = {
15849ab747fSPaolo Bonzini .name = "pci_status",
15949ab747fSPaolo Bonzini .version_id = 1,
16049ab747fSPaolo Bonzini .minimum_version_id = 1,
161c559ba57SRichard Henderson .fields = (const VMStateField[]) {
162e358edc8SIgor Mammedov VMSTATE_UINT32(up, struct AcpiPciHpPciStatus),
163e358edc8SIgor Mammedov VMSTATE_UINT32(down, struct AcpiPciHpPciStatus),
16449ab747fSPaolo Bonzini VMSTATE_END_OF_LIST()
16549ab747fSPaolo Bonzini }
16649ab747fSPaolo Bonzini };
16749ab747fSPaolo Bonzini
vmstate_test_use_acpi_hotplug_bridge(void * opaque,int version_id)1680affda04SAni Sinha static bool vmstate_test_use_acpi_hotplug_bridge(void *opaque, int version_id)
1699e047b98SMichael S. Tsirkin {
1709e047b98SMichael S. Tsirkin PIIX4PMState *s = opaque;
1716536e427SIgor Mammedov return s->acpi_pci_hotplug.use_acpi_hotplug_bridge;
1729e047b98SMichael S. Tsirkin }
1739e047b98SMichael S. Tsirkin
vmstate_test_no_use_acpi_hotplug_bridge(void * opaque,int version_id)1740affda04SAni Sinha static bool vmstate_test_no_use_acpi_hotplug_bridge(void *opaque,
1750affda04SAni Sinha int version_id)
1769e047b98SMichael S. Tsirkin {
1779e047b98SMichael S. Tsirkin PIIX4PMState *s = opaque;
1786536e427SIgor Mammedov return !s->acpi_pci_hotplug.use_acpi_hotplug_bridge;
1799e047b98SMichael S. Tsirkin }
1809e047b98SMichael S. Tsirkin
vmstate_test_use_memhp(void * opaque)181f816a62dSIgor Mammedov static bool vmstate_test_use_memhp(void *opaque)
182f816a62dSIgor Mammedov {
183f816a62dSIgor Mammedov PIIX4PMState *s = opaque;
184f816a62dSIgor Mammedov return s->acpi_memory_hotplug.is_enabled;
185f816a62dSIgor Mammedov }
186f816a62dSIgor Mammedov
187f816a62dSIgor Mammedov static const VMStateDescription vmstate_memhp_state = {
188f816a62dSIgor Mammedov .name = "piix4_pm/memhp",
189f816a62dSIgor Mammedov .version_id = 1,
190f816a62dSIgor Mammedov .minimum_version_id = 1,
1915cd8cadaSJuan Quintela .needed = vmstate_test_use_memhp,
192c559ba57SRichard Henderson .fields = (const VMStateField[]) {
193f816a62dSIgor Mammedov VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, PIIX4PMState),
194f816a62dSIgor Mammedov VMSTATE_END_OF_LIST()
195f816a62dSIgor Mammedov }
196f816a62dSIgor Mammedov };
197f816a62dSIgor Mammedov
vmstate_test_use_cpuhp(void * opaque)198679dd1a9SIgor Mammedov static bool vmstate_test_use_cpuhp(void *opaque)
199679dd1a9SIgor Mammedov {
200679dd1a9SIgor Mammedov PIIX4PMState *s = opaque;
201679dd1a9SIgor Mammedov return !s->cpu_hotplug_legacy;
202679dd1a9SIgor Mammedov }
203679dd1a9SIgor Mammedov
vmstate_cpuhp_pre_load(void * opaque)204679dd1a9SIgor Mammedov static int vmstate_cpuhp_pre_load(void *opaque)
205679dd1a9SIgor Mammedov {
206679dd1a9SIgor Mammedov Object *obj = OBJECT(opaque);
2075325cc34SMarkus Armbruster object_property_set_bool(obj, "cpu-hotplug-legacy", false, &error_abort);
208679dd1a9SIgor Mammedov return 0;
209679dd1a9SIgor Mammedov }
210679dd1a9SIgor Mammedov
211679dd1a9SIgor Mammedov static const VMStateDescription vmstate_cpuhp_state = {
212679dd1a9SIgor Mammedov .name = "piix4_pm/cpuhp",
213679dd1a9SIgor Mammedov .version_id = 1,
214679dd1a9SIgor Mammedov .minimum_version_id = 1,
215679dd1a9SIgor Mammedov .needed = vmstate_test_use_cpuhp,
216679dd1a9SIgor Mammedov .pre_load = vmstate_cpuhp_pre_load,
217c559ba57SRichard Henderson .fields = (const VMStateField[]) {
218679dd1a9SIgor Mammedov VMSTATE_CPU_HOTPLUG(cpuhp_state, PIIX4PMState),
219679dd1a9SIgor Mammedov VMSTATE_END_OF_LIST()
220679dd1a9SIgor Mammedov }
221679dd1a9SIgor Mammedov };
222679dd1a9SIgor Mammedov
piix4_vmstate_need_smbus(void * opaque,int version_id)2234ab2f2a8SCorey Minyard static bool piix4_vmstate_need_smbus(void *opaque, int version_id)
2244ab2f2a8SCorey Minyard {
2254ab2f2a8SCorey Minyard return pm_smbus_vmstate_needed();
2264ab2f2a8SCorey Minyard }
2274ab2f2a8SCorey Minyard
228a83c2844SDr. David Alan Gilbert /*
229a83c2844SDr. David Alan Gilbert * This is a fudge to turn off the acpi_index field,
230a83c2844SDr. David Alan Gilbert * whose test was always broken on piix4 with 6.2 and older machine types.
231a83c2844SDr. David Alan Gilbert */
vmstate_test_migrate_acpi_index(void * opaque,int version_id)232a83c2844SDr. David Alan Gilbert static bool vmstate_test_migrate_acpi_index(void *opaque, int version_id)
233a83c2844SDr. David Alan Gilbert {
234a83c2844SDr. David Alan Gilbert PIIX4PMState *s = PIIX4_PM(opaque);
2356536e427SIgor Mammedov return s->acpi_pci_hotplug.use_acpi_hotplug_bridge &&
2366536e427SIgor Mammedov !s->not_migrate_acpi_index;
237a83c2844SDr. David Alan Gilbert }
238a83c2844SDr. David Alan Gilbert
23949ab747fSPaolo Bonzini /* qemu-kvm 1.2 uses version 3 but advertised as 2
24049ab747fSPaolo Bonzini * To support incoming qemu-kvm 1.2 migration, change version_id
24149ab747fSPaolo Bonzini * and minimum_version_id to 2 below (which breaks migration from
24249ab747fSPaolo Bonzini * qemu 1.2).
24349ab747fSPaolo Bonzini *
24449ab747fSPaolo Bonzini */
24549ab747fSPaolo Bonzini static const VMStateDescription vmstate_acpi = {
24649ab747fSPaolo Bonzini .name = "piix4_pm",
24749ab747fSPaolo Bonzini .version_id = 3,
24849ab747fSPaolo Bonzini .minimum_version_id = 3,
24949ab747fSPaolo Bonzini .post_load = vmstate_acpi_post_load,
250c559ba57SRichard Henderson .fields = (const VMStateField[]) {
2516a6b5580SAndreas Färber VMSTATE_PCI_DEVICE(parent_obj, PIIX4PMState),
25249ab747fSPaolo Bonzini VMSTATE_UINT16(ar.pm1.evt.sts, PIIX4PMState),
25349ab747fSPaolo Bonzini VMSTATE_UINT16(ar.pm1.evt.en, PIIX4PMState),
25449ab747fSPaolo Bonzini VMSTATE_UINT16(ar.pm1.cnt.cnt, PIIX4PMState),
25549ab747fSPaolo Bonzini VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
2564ab2f2a8SCorey Minyard VMSTATE_STRUCT_TEST(smb, PIIX4PMState, piix4_vmstate_need_smbus, 3,
2574ab2f2a8SCorey Minyard pmsmb_vmstate, PMSMBus),
258e720677eSPaolo Bonzini VMSTATE_TIMER_PTR(ar.tmr.timer, PIIX4PMState),
25949ab747fSPaolo Bonzini VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
26049ab747fSPaolo Bonzini VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
261e358edc8SIgor Mammedov VMSTATE_STRUCT_TEST(
262e358edc8SIgor Mammedov acpi_pci_hotplug.acpi_pcihp_pci_status[ACPI_PCIHP_BSEL_DEFAULT],
263e358edc8SIgor Mammedov PIIX4PMState,
2640affda04SAni Sinha vmstate_test_no_use_acpi_hotplug_bridge,
2659e047b98SMichael S. Tsirkin 2, vmstate_pci_status,
266e358edc8SIgor Mammedov struct AcpiPciHpPciStatus),
2679e047b98SMichael S. Tsirkin VMSTATE_PCI_HOTPLUG(acpi_pci_hotplug, PIIX4PMState,
268b32bd763SIgor Mammedov vmstate_test_use_acpi_hotplug_bridge,
269a83c2844SDr. David Alan Gilbert vmstate_test_migrate_acpi_index),
27049ab747fSPaolo Bonzini VMSTATE_END_OF_LIST()
271f816a62dSIgor Mammedov },
272c559ba57SRichard Henderson .subsections = (const VMStateDescription * const []) {
2735cd8cadaSJuan Quintela &vmstate_memhp_state,
274679dd1a9SIgor Mammedov &vmstate_cpuhp_state,
2755cd8cadaSJuan Quintela NULL
27649ab747fSPaolo Bonzini }
27749ab747fSPaolo Bonzini };
27849ab747fSPaolo Bonzini
piix4_pm_reset(DeviceState * dev)279217e8ef9SPhilippe Mathieu-Daudé static void piix4_pm_reset(DeviceState *dev)
28049ab747fSPaolo Bonzini {
281217e8ef9SPhilippe Mathieu-Daudé PIIX4PMState *s = PIIX4_PM(dev);
2826a6b5580SAndreas Färber PCIDevice *d = PCI_DEVICE(s);
2836a6b5580SAndreas Färber uint8_t *pci_conf = d->config;
28449ab747fSPaolo Bonzini
28549ab747fSPaolo Bonzini pci_conf[0x58] = 0;
28649ab747fSPaolo Bonzini pci_conf[0x59] = 0;
28749ab747fSPaolo Bonzini pci_conf[0x5a] = 0;
28849ab747fSPaolo Bonzini pci_conf[0x5b] = 0;
28949ab747fSPaolo Bonzini
29049ab747fSPaolo Bonzini pci_conf[0x40] = 0x01; /* PM io base read only bit */
29149ab747fSPaolo Bonzini pci_conf[0x80] = 0;
29249ab747fSPaolo Bonzini
29361e66c62SPaolo Bonzini if (!s->smm_enabled) {
29449ab747fSPaolo Bonzini /* Mark SMM as already inited (until KVM supports SMM). */
29549ab747fSPaolo Bonzini pci_conf[0x5B] = 0x02;
29649ab747fSPaolo Bonzini }
2970fd74325SIsaku Yamahata
2980fd74325SIsaku Yamahata acpi_pm1_evt_reset(&s->ar);
2990fd74325SIsaku Yamahata acpi_pm1_cnt_reset(&s->ar);
3000fd74325SIsaku Yamahata acpi_pm_tmr_reset(&s->ar);
3010fd74325SIsaku Yamahata acpi_gpe_reset(&s->ar);
3020fd74325SIsaku Yamahata acpi_update_sci(&s->ar, s->irq);
3030fd74325SIsaku Yamahata
304c046e8c4SMichael S. Tsirkin pm_io_space_update(s);
3056536e427SIgor Mammedov if (s->acpi_pci_hotplug.use_acpi_hotplug_bridge ||
3066536e427SIgor Mammedov s->acpi_pci_hotplug.use_acpi_root_pci_hotplug) {
3076536e427SIgor Mammedov acpi_pcihp_reset(&s->acpi_pci_hotplug);
3089e047b98SMichael S. Tsirkin }
30945284cfbSIgor Mammedov }
31049ab747fSPaolo Bonzini
piix4_pm_powerdown_req(Notifier * n,void * opaque)31149ab747fSPaolo Bonzini static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
31249ab747fSPaolo Bonzini {
31349ab747fSPaolo Bonzini PIIX4PMState *s = container_of(n, PIIX4PMState, powerdown_notifier);
31449ab747fSPaolo Bonzini
31549ab747fSPaolo Bonzini assert(s != NULL);
31649ab747fSPaolo Bonzini acpi_pm1_evt_power_down(&s->ar);
31749ab747fSPaolo Bonzini }
31849ab747fSPaolo Bonzini
piix4_device_pre_plug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)319ec266f40SDavid Hildenbrand static void piix4_device_pre_plug_cb(HotplugHandler *hotplug_dev,
320ec266f40SDavid Hildenbrand DeviceState *dev, Error **errp)
321ec266f40SDavid Hildenbrand {
3229040e6dfSWei Yang PIIX4PMState *s = PIIX4_PM(hotplug_dev);
3239040e6dfSWei Yang
324ec266f40SDavid Hildenbrand if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
325ec266f40SDavid Hildenbrand acpi_pcihp_device_pre_plug_cb(hotplug_dev, dev, errp);
3269040e6dfSWei Yang } else if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
3279040e6dfSWei Yang if (!s->acpi_memory_hotplug.is_enabled) {
3289040e6dfSWei Yang error_setg(errp,
3299040e6dfSWei Yang "memory hotplug is not enabled: %s.memory-hotplug-support "
3309040e6dfSWei Yang "is not set", object_get_typename(OBJECT(s)));
3319040e6dfSWei Yang }
3329040e6dfSWei Yang } else if (
333ec266f40SDavid Hildenbrand !object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
334ec266f40SDavid Hildenbrand error_setg(errp, "acpi: device pre plug request for not supported"
335ec266f40SDavid Hildenbrand " device type: %s", object_get_typename(OBJECT(dev)));
336ec266f40SDavid Hildenbrand }
337ec266f40SDavid Hildenbrand }
338ec266f40SDavid Hildenbrand
piix4_device_plug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)339f1adc360SIgor Mammedov static void piix4_device_plug_cb(HotplugHandler *hotplug_dev,
340c24d5e0bSIgor Mammedov DeviceState *dev, Error **errp)
3419e047b98SMichael S. Tsirkin {
342c24d5e0bSIgor Mammedov PIIX4PMState *s = PIIX4_PM(hotplug_dev);
343f1adc360SIgor Mammedov
3449040e6dfSWei Yang if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
34575f27498SXiao Guangrong if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
34675f27498SXiao Guangrong nvdimm_acpi_plug_cb(hotplug_dev, dev);
34775f27498SXiao Guangrong } else {
34875f27498SXiao Guangrong acpi_memory_plug_cb(hotplug_dev, &s->acpi_memory_hotplug,
34975f27498SXiao Guangrong dev, errp);
35075f27498SXiao Guangrong }
35134774320SIgor Mammedov } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
3522bed1ba7SAnthony PERARD acpi_pcihp_device_plug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev, errp);
3535e1b5d93SIgor Mammedov } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
3545e1b5d93SIgor Mammedov if (s->cpu_hotplug_legacy) {
3550058c082SIgor Mammedov legacy_acpi_cpu_plug_cb(hotplug_dev, &s->gpe_cpu, dev, errp);
356f1adc360SIgor Mammedov } else {
3575e1b5d93SIgor Mammedov acpi_cpu_plug_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
3585e1b5d93SIgor Mammedov }
3595e1b5d93SIgor Mammedov } else {
360ec266f40SDavid Hildenbrand g_assert_not_reached();
361f1adc360SIgor Mammedov }
3629e047b98SMichael S. Tsirkin }
3639e047b98SMichael S. Tsirkin
piix4_device_unplug_request_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)36414d5a28fSIgor Mammedov static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
365c24d5e0bSIgor Mammedov DeviceState *dev, Error **errp)
366c24d5e0bSIgor Mammedov {
367c24d5e0bSIgor Mammedov PIIX4PMState *s = PIIX4_PM(hotplug_dev);
368f1adc360SIgor Mammedov
36964fec58eSTang Chen if (s->acpi_memory_hotplug.is_enabled &&
37064fec58eSTang Chen object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
3710058c082SIgor Mammedov acpi_memory_unplug_request_cb(hotplug_dev, &s->acpi_memory_hotplug,
37264fec58eSTang Chen dev, errp);
37364fec58eSTang Chen } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
374c97adf3cSDavid Hildenbrand acpi_pcihp_device_unplug_request_cb(hotplug_dev, &s->acpi_pci_hotplug,
375c97adf3cSDavid Hildenbrand dev, errp);
3768872c25aSIgor Mammedov } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) &&
3778872c25aSIgor Mammedov !s->cpu_hotplug_legacy) {
3788872c25aSIgor Mammedov acpi_cpu_unplug_request_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
379f1adc360SIgor Mammedov } else {
380f1adc360SIgor Mammedov error_setg(errp, "acpi: device unplug request for not supported device"
381f1adc360SIgor Mammedov " type: %s", object_get_typename(OBJECT(dev)));
382f1adc360SIgor Mammedov }
383c24d5e0bSIgor Mammedov }
384c24d5e0bSIgor Mammedov
piix4_device_unplug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)385c0e57a60STang Chen static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
386c0e57a60STang Chen DeviceState *dev, Error **errp)
387c0e57a60STang Chen {
388f7d3e29dSTang Chen PIIX4PMState *s = PIIX4_PM(hotplug_dev);
389f7d3e29dSTang Chen
390f7d3e29dSTang Chen if (s->acpi_memory_hotplug.is_enabled &&
391f7d3e29dSTang Chen object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
392f7d3e29dSTang Chen acpi_memory_unplug_cb(&s->acpi_memory_hotplug, dev, errp);
393c97adf3cSDavid Hildenbrand } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
394c97adf3cSDavid Hildenbrand acpi_pcihp_device_unplug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev,
395c97adf3cSDavid Hildenbrand errp);
3968872c25aSIgor Mammedov } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) &&
3978872c25aSIgor Mammedov !s->cpu_hotplug_legacy) {
3988872c25aSIgor Mammedov acpi_cpu_unplug_cb(&s->cpuhp_state, dev, errp);
399f7d3e29dSTang Chen } else {
400c0e57a60STang Chen error_setg(errp, "acpi: device unplug for not supported device"
401c0e57a60STang Chen " type: %s", object_get_typename(OBJECT(dev)));
402c0e57a60STang Chen }
403f7d3e29dSTang Chen }
404c0e57a60STang Chen
piix4_is_hotpluggable_bus(HotplugHandler * hotplug_dev,BusState * bus)405f18e29fcSIgor Mammedov static bool piix4_is_hotpluggable_bus(HotplugHandler *hotplug_dev,
406f18e29fcSIgor Mammedov BusState *bus)
407f18e29fcSIgor Mammedov {
408f18e29fcSIgor Mammedov PIIX4PMState *s = PIIX4_PM(hotplug_dev);
409f18e29fcSIgor Mammedov return acpi_pcihp_is_hotpluggbale_bus(&s->acpi_pci_hotplug, bus);
410f18e29fcSIgor Mammedov }
411f18e29fcSIgor Mammedov
piix4_pm_machine_ready(Notifier * n,void * opaque)41249ab747fSPaolo Bonzini static void piix4_pm_machine_ready(Notifier *n, void *opaque)
41349ab747fSPaolo Bonzini {
41449ab747fSPaolo Bonzini PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
4156a6b5580SAndreas Färber PCIDevice *d = PCI_DEVICE(s);
4166a6b5580SAndreas Färber MemoryRegion *io_as = pci_address_space_io(d);
41749ab747fSPaolo Bonzini uint8_t *pci_conf;
41849ab747fSPaolo Bonzini
4196a6b5580SAndreas Färber pci_conf = d->config;
420b6f32962SJan Kiszka pci_conf[0x5f] = 0x10 |
4213ce10901SPaolo Bonzini (memory_region_present(io_as, 0x378) ? 0x80 : 0);
42249ab747fSPaolo Bonzini pci_conf[0x63] = 0x60;
4233ce10901SPaolo Bonzini pci_conf[0x67] = (memory_region_present(io_as, 0x3f8) ? 0x08 : 0) |
4243ce10901SPaolo Bonzini (memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
42549ab747fSPaolo Bonzini }
42649ab747fSPaolo Bonzini
piix4_pm_add_properties(PIIX4PMState * s)4275ad1037cSGreg Kurz static void piix4_pm_add_properties(PIIX4PMState *s)
428277e9340SMichael S. Tsirkin {
429277e9340SMichael S. Tsirkin static const uint8_t acpi_enable_cmd = ACPI_ENABLE;
430277e9340SMichael S. Tsirkin static const uint8_t acpi_disable_cmd = ACPI_DISABLE;
431277e9340SMichael S. Tsirkin static const uint32_t gpe0_blk = GPE_BASE;
432277e9340SMichael S. Tsirkin static const uint32_t gpe0_blk_len = GPE_LEN;
433277e9340SMichael S. Tsirkin static const uint16_t sci_int = 9;
434277e9340SMichael S. Tsirkin
435277e9340SMichael S. Tsirkin object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_ENABLE_CMD,
436d2623129SMarkus Armbruster &acpi_enable_cmd, OBJ_PROP_FLAG_READ);
437277e9340SMichael S. Tsirkin object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_DISABLE_CMD,
438d2623129SMarkus Armbruster &acpi_disable_cmd, OBJ_PROP_FLAG_READ);
439277e9340SMichael S. Tsirkin object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK,
440d2623129SMarkus Armbruster &gpe0_blk, OBJ_PROP_FLAG_READ);
441277e9340SMichael S. Tsirkin object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK_LEN,
442d2623129SMarkus Armbruster &gpe0_blk_len, OBJ_PROP_FLAG_READ);
443277e9340SMichael S. Tsirkin object_property_add_uint16_ptr(OBJECT(s), ACPI_PM_PROP_SCI_INT,
444d2623129SMarkus Armbruster &sci_int, OBJ_PROP_FLAG_READ);
445277e9340SMichael S. Tsirkin object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_PM_IO_BASE,
446d2623129SMarkus Armbruster &s->io_base, OBJ_PROP_FLAG_READ);
447277e9340SMichael S. Tsirkin }
448277e9340SMichael S. Tsirkin
piix4_pm_realize(PCIDevice * dev,Error ** errp)4499af21dbeSMarkus Armbruster static void piix4_pm_realize(PCIDevice *dev, Error **errp)
45049ab747fSPaolo Bonzini {
45174e445f6SPeter Crosthwaite PIIX4PMState *s = PIIX4_PM(dev);
45249ab747fSPaolo Bonzini uint8_t *pci_conf;
45349ab747fSPaolo Bonzini
4546a6b5580SAndreas Färber pci_conf = dev->config;
45549ab747fSPaolo Bonzini pci_conf[0x06] = 0x80;
45649ab747fSPaolo Bonzini pci_conf[0x07] = 0x02;
45749ab747fSPaolo Bonzini pci_conf[0x09] = 0x00;
45849ab747fSPaolo Bonzini pci_conf[0x3d] = 0x01; // interrupt pin 1
45949ab747fSPaolo Bonzini
46049ab747fSPaolo Bonzini /* APM */
46149ab747fSPaolo Bonzini apm_init(dev, &s->apm, apm_ctrl_changed, s);
46249ab747fSPaolo Bonzini
46361e66c62SPaolo Bonzini if (!s->smm_enabled) {
46449ab747fSPaolo Bonzini /* Mark SMM as already inited to prevent SMM from running. KVM does not
46549ab747fSPaolo Bonzini * support SMM mode. */
46649ab747fSPaolo Bonzini pci_conf[0x5B] = 0x02;
46749ab747fSPaolo Bonzini }
46849ab747fSPaolo Bonzini
46949ab747fSPaolo Bonzini /* XXX: which specification is used ? The i82731AB has different
47049ab747fSPaolo Bonzini mappings */
47149ab747fSPaolo Bonzini pci_conf[0x90] = s->smb_io_base | 1;
47249ab747fSPaolo Bonzini pci_conf[0x91] = s->smb_io_base >> 8;
47349ab747fSPaolo Bonzini pci_conf[0xd2] = 0x09;
47445726b6eSCorey Minyard pm_smbus_init(DEVICE(dev), &s->smb, true);
47549ab747fSPaolo Bonzini memory_region_set_enabled(&s->smb.io, pci_conf[0xd2] & 1);
47649ab747fSPaolo Bonzini memory_region_add_subregion(pci_address_space_io(dev),
47749ab747fSPaolo Bonzini s->smb_io_base, &s->smb.io);
47849ab747fSPaolo Bonzini
47964bde0f3SPaolo Bonzini memory_region_init(&s->io, OBJECT(s), "piix4-pm", 64);
48049ab747fSPaolo Bonzini memory_region_set_enabled(&s->io, false);
48149ab747fSPaolo Bonzini memory_region_add_subregion(pci_address_space_io(dev),
48249ab747fSPaolo Bonzini 0, &s->io);
48349ab747fSPaolo Bonzini
48449ab747fSPaolo Bonzini acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
48549ab747fSPaolo Bonzini acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
4866be8cf56SIsaku Yamahata acpi_pm1_cnt_init(&s->ar, &s->io, s->disable_s3, s->disable_s4, s->s4_val,
4876be8cf56SIsaku Yamahata !s->smm_compat && !s->smm_enabled);
48849ab747fSPaolo Bonzini acpi_gpe_init(&s->ar, GPE_LEN);
48949ab747fSPaolo Bonzini
49049ab747fSPaolo Bonzini s->powerdown_notifier.notify = piix4_pm_powerdown_req;
49149ab747fSPaolo Bonzini qemu_register_powerdown_notifier(&s->powerdown_notifier);
49249ab747fSPaolo Bonzini
49349ab747fSPaolo Bonzini s->machine_ready.notify = piix4_pm_machine_ready;
49449ab747fSPaolo Bonzini qemu_add_machine_init_done_notifier(&s->machine_ready);
49549ab747fSPaolo Bonzini
4963f0efcacSMark Cave-Ayland if (xen_enabled()) {
4976536e427SIgor Mammedov s->acpi_pci_hotplug.use_acpi_hotplug_bridge = false;
4983f0efcacSMark Cave-Ayland }
4993f0efcacSMark Cave-Ayland
500fd56e061SDavid Gibson piix4_acpi_system_hot_add_init(pci_address_space_io(dev),
501fd56e061SDavid Gibson pci_get_bus(dev), s);
50249ab747fSPaolo Bonzini
5035ad1037cSGreg Kurz piix4_pm_add_properties(s);
50449ab747fSPaolo Bonzini }
50549ab747fSPaolo Bonzini
piix4_pm_init(Object * obj)50629786d42SMark Cave-Ayland static void piix4_pm_init(Object *obj)
50729786d42SMark Cave-Ayland {
50829786d42SMark Cave-Ayland PIIX4PMState *s = PIIX4_PM(obj);
50929786d42SMark Cave-Ayland
51029786d42SMark Cave-Ayland qdev_init_gpio_out(DEVICE(obj), &s->irq, 1);
511b49e9442SMark Cave-Ayland qdev_init_gpio_out_named(DEVICE(obj), &s->smi_irq, "smi-irq", 1);
51229786d42SMark Cave-Ayland }
51329786d42SMark Cave-Ayland
gpe_readb(void * opaque,hwaddr addr,unsigned width)51449ab747fSPaolo Bonzini static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width)
51549ab747fSPaolo Bonzini {
51649ab747fSPaolo Bonzini PIIX4PMState *s = opaque;
51749ab747fSPaolo Bonzini uint32_t val = acpi_gpe_ioport_readb(&s->ar, addr);
51849ab747fSPaolo Bonzini
51949ab747fSPaolo Bonzini return val;
52049ab747fSPaolo Bonzini }
52149ab747fSPaolo Bonzini
gpe_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned width)52249ab747fSPaolo Bonzini static void gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
52349ab747fSPaolo Bonzini unsigned width)
52449ab747fSPaolo Bonzini {
52549ab747fSPaolo Bonzini PIIX4PMState *s = opaque;
52649ab747fSPaolo Bonzini
52749ab747fSPaolo Bonzini acpi_gpe_ioport_writeb(&s->ar, addr, val);
52806313503SIgor Mammedov acpi_update_sci(&s->ar, s->irq);
52949ab747fSPaolo Bonzini }
53049ab747fSPaolo Bonzini
53149ab747fSPaolo Bonzini static const MemoryRegionOps piix4_gpe_ops = {
53249ab747fSPaolo Bonzini .read = gpe_readb,
53349ab747fSPaolo Bonzini .write = gpe_writeb,
53449ab747fSPaolo Bonzini .valid.min_access_size = 1,
53549ab747fSPaolo Bonzini .valid.max_access_size = 4,
53649ab747fSPaolo Bonzini .impl.min_access_size = 1,
53749ab747fSPaolo Bonzini .impl.max_access_size = 1,
53849ab747fSPaolo Bonzini .endianness = DEVICE_LITTLE_ENDIAN,
53949ab747fSPaolo Bonzini };
54049ab747fSPaolo Bonzini
54116bcab97SIgor Mammedov
piix4_get_cpu_hotplug_legacy(Object * obj,Error ** errp)54216bcab97SIgor Mammedov static bool piix4_get_cpu_hotplug_legacy(Object *obj, Error **errp)
54316bcab97SIgor Mammedov {
54416bcab97SIgor Mammedov PIIX4PMState *s = PIIX4_PM(obj);
54516bcab97SIgor Mammedov
54616bcab97SIgor Mammedov return s->cpu_hotplug_legacy;
54716bcab97SIgor Mammedov }
54816bcab97SIgor Mammedov
piix4_set_cpu_hotplug_legacy(Object * obj,bool value,Error ** errp)54916bcab97SIgor Mammedov static void piix4_set_cpu_hotplug_legacy(Object *obj, bool value, Error **errp)
55016bcab97SIgor Mammedov {
55116bcab97SIgor Mammedov PIIX4PMState *s = PIIX4_PM(obj);
55216bcab97SIgor Mammedov
553679dd1a9SIgor Mammedov assert(!value);
554679dd1a9SIgor Mammedov if (s->cpu_hotplug_legacy && value == false) {
555679dd1a9SIgor Mammedov acpi_switch_to_modern_cphp(&s->gpe_cpu, &s->cpuhp_state,
556679dd1a9SIgor Mammedov PIIX4_CPU_HOTPLUG_IO_BASE);
557679dd1a9SIgor Mammedov }
55816bcab97SIgor Mammedov s->cpu_hotplug_legacy = value;
55916bcab97SIgor Mammedov }
56016bcab97SIgor Mammedov
piix4_acpi_system_hot_add_init(MemoryRegion * parent,PCIBus * bus,PIIX4PMState * s)56149ab747fSPaolo Bonzini static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
56249ab747fSPaolo Bonzini PCIBus *bus, PIIX4PMState *s)
56349ab747fSPaolo Bonzini {
56464bde0f3SPaolo Bonzini memory_region_init_io(&s->io_gpe, OBJECT(s), &piix4_gpe_ops, s,
56564bde0f3SPaolo Bonzini "acpi-gpe0", GPE_LEN);
56649ab747fSPaolo Bonzini memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
56749ab747fSPaolo Bonzini
5686536e427SIgor Mammedov if (s->acpi_pci_hotplug.use_acpi_hotplug_bridge ||
5696536e427SIgor Mammedov s->acpi_pci_hotplug.use_acpi_root_pci_hotplug) {
57078c2d872SIgor Mammedov acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, bus, parent,
5716536e427SIgor Mammedov ACPI_PCIHP_ADDR_PIIX4);
572f40e6a4cSIgor Mammedov qbus_set_hotplug_handler(BUS(pci_get_bus(PCI_DEVICE(s))), OBJECT(s));
573df4008c9SAni Sinha }
574b8622725SIgor Mammedov
57516bcab97SIgor Mammedov s->cpu_hotplug_legacy = true;
57616bcab97SIgor Mammedov object_property_add_bool(OBJECT(s), "cpu-hotplug-legacy",
57716bcab97SIgor Mammedov piix4_get_cpu_hotplug_legacy,
578d2623129SMarkus Armbruster piix4_set_cpu_hotplug_legacy);
57996e3e12bSIgor Mammedov legacy_acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu,
580e4cf8ed0SIgor Mammedov PIIX4_CPU_HOTPLUG_IO_BASE);
58134774320SIgor Mammedov
58234774320SIgor Mammedov if (s->acpi_memory_hotplug.is_enabled) {
58380db0e78SIgor Mammedov acpi_memory_hotplug_init(parent, OBJECT(s), &s->acpi_memory_hotplug,
58480db0e78SIgor Mammedov ACPI_MEMORY_HOTPLUG_BASE);
58534774320SIgor Mammedov }
58649ab747fSPaolo Bonzini }
5875fdae20cSIgor Mammedov
piix4_ospm_status(AcpiDeviceIf * adev,ACPIOSTInfoList *** list)58843f50410SIgor Mammedov static void piix4_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
58943f50410SIgor Mammedov {
59043f50410SIgor Mammedov PIIX4PMState *s = PIIX4_PM(adev);
59143f50410SIgor Mammedov
59243f50410SIgor Mammedov acpi_memory_ospm_status(&s->acpi_memory_hotplug, list);
59376623d00SIgor Mammedov if (!s->cpu_hotplug_legacy) {
59476623d00SIgor Mammedov acpi_cpu_ospm_status(&s->cpuhp_state, list);
59576623d00SIgor Mammedov }
59643f50410SIgor Mammedov }
59743f50410SIgor Mammedov
piix4_send_gpe(AcpiDeviceIf * adev,AcpiEventStatusBits ev)598eaf23bf7SIgor Mammedov static void piix4_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
599eaf23bf7SIgor Mammedov {
600eaf23bf7SIgor Mammedov PIIX4PMState *s = PIIX4_PM(adev);
601eaf23bf7SIgor Mammedov
602eaf23bf7SIgor Mammedov acpi_send_gpe_event(&s->ar, s->irq, ev);
603eaf23bf7SIgor Mammedov }
604eaf23bf7SIgor Mammedov
6055fdae20cSIgor Mammedov static Property piix4_pm_properties[] = {
6065fdae20cSIgor Mammedov DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
6075fdae20cSIgor Mammedov DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
6085fdae20cSIgor Mammedov DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
6095fdae20cSIgor Mammedov DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
610aa29466bSAni Sinha DEFINE_PROP_BOOL(ACPI_PM_PROP_ACPI_PCIHP_BRIDGE, PIIX4PMState,
6116536e427SIgor Mammedov acpi_pci_hotplug.use_acpi_hotplug_bridge, true),
612aa29466bSAni Sinha DEFINE_PROP_BOOL(ACPI_PM_PROP_ACPI_PCI_ROOTHP, PIIX4PMState,
6136536e427SIgor Mammedov acpi_pci_hotplug.use_acpi_root_pci_hotplug, true),
61434774320SIgor Mammedov DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState,
61534774320SIgor Mammedov acpi_memory_hotplug.is_enabled, true),
61624cd04fcSIsaku Yamahata DEFINE_PROP_BOOL("smm-compat", PIIX4PMState, smm_compat, false),
6177ace6b4fSMark Cave-Ayland DEFINE_PROP_BOOL("smm-enabled", PIIX4PMState, smm_enabled, false),
618a83c2844SDr. David Alan Gilbert DEFINE_PROP_BOOL("x-not-migrate-acpi-index", PIIX4PMState,
619a83c2844SDr. David Alan Gilbert not_migrate_acpi_index, false),
6205fdae20cSIgor Mammedov DEFINE_PROP_END_OF_LIST(),
6215fdae20cSIgor Mammedov };
6225fdae20cSIgor Mammedov
piix4_pm_class_init(ObjectClass * klass,void * data)6235fdae20cSIgor Mammedov static void piix4_pm_class_init(ObjectClass *klass, void *data)
6245fdae20cSIgor Mammedov {
6255fdae20cSIgor Mammedov DeviceClass *dc = DEVICE_CLASS(klass);
6265fdae20cSIgor Mammedov PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
627c24d5e0bSIgor Mammedov HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
62843f50410SIgor Mammedov AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(klass);
6295fdae20cSIgor Mammedov
6309af21dbeSMarkus Armbruster k->realize = piix4_pm_realize;
6315fdae20cSIgor Mammedov k->config_write = pm_write_config;
6325fdae20cSIgor Mammedov k->vendor_id = PCI_VENDOR_ID_INTEL;
6335fdae20cSIgor Mammedov k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3;
6345fdae20cSIgor Mammedov k->revision = 0x03;
6355fdae20cSIgor Mammedov k->class_id = PCI_CLASS_BRIDGE_OTHER;
636*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, piix4_pm_reset);
6375fdae20cSIgor Mammedov dc->desc = "PM";
6385fdae20cSIgor Mammedov dc->vmsd = &vmstate_acpi;
6394f67d30bSMarc-André Lureau device_class_set_props(dc, piix4_pm_properties);
6405fdae20cSIgor Mammedov /*
6415fdae20cSIgor Mammedov * Reason: part of PIIX4 southbridge, needs to be wired up,
6425fdae20cSIgor Mammedov * e.g. by mips_malta_init()
6435fdae20cSIgor Mammedov */
644e90f2a8cSEduardo Habkost dc->user_creatable = false;
6452897ae02SIgor Mammedov dc->hotpluggable = false;
646ec266f40SDavid Hildenbrand hc->pre_plug = piix4_device_pre_plug_cb;
647f1adc360SIgor Mammedov hc->plug = piix4_device_plug_cb;
64814d5a28fSIgor Mammedov hc->unplug_request = piix4_device_unplug_request_cb;
649c0e57a60STang Chen hc->unplug = piix4_device_unplug_cb;
650f18e29fcSIgor Mammedov hc->is_hotpluggable_bus = piix4_is_hotpluggable_bus;
65143f50410SIgor Mammedov adevc->ospm_status = piix4_ospm_status;
652eaf23bf7SIgor Mammedov adevc->send_event = piix4_send_gpe;
6535fdae20cSIgor Mammedov }
6545fdae20cSIgor Mammedov
6555fdae20cSIgor Mammedov static const TypeInfo piix4_pm_info = {
6565fdae20cSIgor Mammedov .name = TYPE_PIIX4_PM,
6575fdae20cSIgor Mammedov .parent = TYPE_PCI_DEVICE,
65829786d42SMark Cave-Ayland .instance_init = piix4_pm_init,
6595fdae20cSIgor Mammedov .instance_size = sizeof(PIIX4PMState),
6605fdae20cSIgor Mammedov .class_init = piix4_pm_class_init,
661c24d5e0bSIgor Mammedov .interfaces = (InterfaceInfo[]) {
662c24d5e0bSIgor Mammedov { TYPE_HOTPLUG_HANDLER },
66343f50410SIgor Mammedov { TYPE_ACPI_DEVICE_IF },
664fd3b02c8SEduardo Habkost { INTERFACE_CONVENTIONAL_PCI_DEVICE },
665c24d5e0bSIgor Mammedov { }
666c24d5e0bSIgor Mammedov }
6675fdae20cSIgor Mammedov };
6685fdae20cSIgor Mammedov
piix4_pm_register_types(void)6695fdae20cSIgor Mammedov static void piix4_pm_register_types(void)
6705fdae20cSIgor Mammedov {
6715fdae20cSIgor Mammedov type_register_static(&piix4_pm_info);
6725fdae20cSIgor Mammedov }
6735fdae20cSIgor Mammedov
6745fdae20cSIgor Mammedov type_init(piix4_pm_register_types)
675