acpi,pci,pc,virtio fixes and enhancements
This includes new unit-tests for acpi by Marcel, hotplug for pci bridges by myself (piix only so far) and cpu hotplug for q35. And a bunch of fixes all over the place as usual. I included the patch to fix memory alignment for q35 as well - even though it limits 32 bit guests to 3G (they previously could address more memory with PAE). To remove the limit, this will have to be fixed in seabios. I also added self as virtio co-maintainer so I don't need to troll the list for patches to review. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJS5O2JAAoJECgfDbjSjVRpBRsH/iueYMYqtlIOCFSBf4TSU5LN 3369DwM0EncrEIZhv6jjtX+CSKUca9IXkKcvBBHJOTwhUodGNZ1wJ/FpO9+AhjpB 5XlIcF4nOi2eYDGs/8JToecK+edggTrSjJ8Bg5n7/bEtJ/oNyjTQ0RMX+2jXq1y3 jnpVjO1ntQXkZQZWNM3O+8biVT1o8wJlFhFbYpx4TKgFplPnRrg1gZR3MtnhsZ+M OoBenpJYrh5Gw52d6HPauMDAux51MjGymzrk2Wmd/w3hPMP9BcxX7NvoapKlGTg9 DkVr7cvbIzZ2JnsRLFNeWsJIupOjl6MwqhGJo5WcB5VS7NZTbVHmtBRvqKa76EU= =y3wE -----END PGP SIGNATURE----- Merge remote-tracking branch 'mst/tags/for_anthony' into staging acpi,pci,pc,virtio fixes and enhancements This includes new unit-tests for acpi by Marcel, hotplug for pci bridges by myself (piix only so far) and cpu hotplug for q35. And a bunch of fixes all over the place as usual. I included the patch to fix memory alignment for q35 as well - even though it limits 32 bit guests to 3G (they previously could address more memory with PAE). To remove the limit, this will have to be fixed in seabios. I also added self as virtio co-maintainer so I don't need to troll the list for patches to review. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Sun 26 Jan 2014 11:12:09 GMT using RSA key ID D28D5469 # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * mst/tags/for_anthony: (35 commits) MAINTAINERS: add self as virtio co-maintainer q35: document gigabyte_align q35: gigabyte alignment for ram acpi: Fix PCI hole handling on build_srat() pc: Save size of RAM below 4GB hw/pci: fix error flow in pci multifunction init acpi-test: update expected AML since recent changes pc: ACPI: update acpi-dsdt.hex.generated q35-acpi-dsdt.hex.generated pc: ACPI: unify source of CPU hotplug IO base/len pc: ACPI: expose PRST IO range via _CRS pc: Q35 DSDT: exclude CPU hotplug IO range from PCI bus resources pc: PIIX DSDT: exclude CPU/PCI hotplug & GPE0 IO range from PCI bus resources pc: set PRST base in DSDT depending on chipset acpi: ich9: add CPU hotplug handling to Q35 machine acpi: factor out common cpu hotplug code for PIIX4/Q35 acpi-build: enable hotplug for PCI bridges piix4: add acpi pci hotplug support pcihp: generalization of piix4 acpi pci: add pci_for_each_bus_depth_first pc: make: fix dependencies: rebuild when included file is changed ... Message-id: 1390735289-15563-1-git-send-email-mst@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						0159a64397
					
				@ -610,6 +610,7 @@ F: hw/*/*vhost*
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
virtio
 | 
					virtio
 | 
				
			||||||
M: Anthony Liguori <aliguori@amazon.com>
 | 
					M: Anthony Liguori <aliguori@amazon.com>
 | 
				
			||||||
 | 
					M: Michael S. Tsirkin <mst@redhat.com>
 | 
				
			||||||
S: Supported
 | 
					S: Supported
 | 
				
			||||||
F: hw/*/virtio*
 | 
					F: hw/*/virtio*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								configure
									
									
									
									
										vendored
									
									
								
							@ -4774,6 +4774,10 @@ for bios_file in \
 | 
				
			|||||||
do
 | 
					do
 | 
				
			||||||
    FILES="$FILES pc-bios/`basename $bios_file`"
 | 
					    FILES="$FILES pc-bios/`basename $bios_file`"
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
 | 
					for test_file in `find $source_path/tests/acpi-test-data -type f`
 | 
				
			||||||
 | 
					do
 | 
				
			||||||
 | 
					    FILES="$FILES tests/acpi-test-data`echo $test_file | sed -e 's/.*acpi-test-data//'`"
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
mkdir -p $DIRS
 | 
					mkdir -p $DIRS
 | 
				
			||||||
for f in $FILES ; do
 | 
					for f in $FILES ; do
 | 
				
			||||||
    if [ -e "$source_path/$f" ] && [ "$source_path" != `pwd` ]; then
 | 
					    if [ -e "$source_path/$f" ] && [ "$source_path" != `pwd` ]; then
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,9 @@ ACPI GPE block (IO ports 0xafe0-0xafe3, byte access):
 | 
				
			|||||||
Generic ACPI GPE block. Bit 2 (GPE.2) used to notify CPU
 | 
					Generic ACPI GPE block. Bit 2 (GPE.2) used to notify CPU
 | 
				
			||||||
hot-add/remove event to ACPI BIOS, via SCI interrupt.
 | 
					hot-add/remove event to ACPI BIOS, via SCI interrupt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CPU present bitmap (IO port 0xaf00-0xaf1f, 1-byte access):
 | 
					CPU present bitmap for:
 | 
				
			||||||
 | 
					  ICH9-LPC (IO port 0x0cd8-0xcf7, 1-byte access)
 | 
				
			||||||
 | 
					  PIIX-PM  (IO port 0xaf00-0xaf1f, 1-byte access)
 | 
				
			||||||
---------------------------------------------------------------
 | 
					---------------------------------------------------------------
 | 
				
			||||||
One bit per CPU. Bit position reflects corresponding CPU APIC ID.
 | 
					One bit per CPU. Bit position reflects corresponding CPU APIC ID.
 | 
				
			||||||
Read-only.
 | 
					Read-only.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,2 +1 @@
 | 
				
			|||||||
common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o
 | 
					common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o pcihp.o cpu_hotplug.o
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										64
									
								
								hw/acpi/cpu_hotplug.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								hw/acpi/cpu_hotplug.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * QEMU ACPI hotplug utilities
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 Red Hat Inc
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Authors:
 | 
				
			||||||
 | 
					 *   Igor Mammedov <imammedo@redhat.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
				
			||||||
 | 
					 * See the COPYING file in the top-level directory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include "hw/hw.h"
 | 
				
			||||||
 | 
					#include "hw/acpi/cpu_hotplug.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AcpiCpuHotplug *cpus = opaque;
 | 
				
			||||||
 | 
					    uint64_t val = cpus->sts[addr];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
 | 
				
			||||||
 | 
					                             unsigned int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* TODO: implement VCPU removal on guest signal that CPU can be removed */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const MemoryRegionOps AcpiCpuHotplug_ops = {
 | 
				
			||||||
 | 
					    .read = cpu_status_read,
 | 
				
			||||||
 | 
					    .write = cpu_status_write,
 | 
				
			||||||
 | 
					    .endianness = DEVICE_LITTLE_ENDIAN,
 | 
				
			||||||
 | 
					    .valid = {
 | 
				
			||||||
 | 
					        .min_access_size = 1,
 | 
				
			||||||
 | 
					        .max_access_size = 1,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AcpiCpuHotplug_add(ACPIGPE *gpe, AcpiCpuHotplug *g, CPUState *cpu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    CPUClass *k = CPU_GET_CLASS(cpu);
 | 
				
			||||||
 | 
					    int64_t cpu_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *gpe->sts = *gpe->sts | ACPI_CPU_HOTPLUG_STATUS;
 | 
				
			||||||
 | 
					    cpu_id = k->get_arch_id(CPU(cpu));
 | 
				
			||||||
 | 
					    g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AcpiCpuHotplug_init(MemoryRegion *parent, Object *owner,
 | 
				
			||||||
 | 
					                         AcpiCpuHotplug *gpe_cpu, uint16_t base)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    CPUState *cpu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CPU_FOREACH(cpu) {
 | 
				
			||||||
 | 
					        CPUClass *cc = CPU_GET_CLASS(cpu);
 | 
				
			||||||
 | 
					        int64_t id = cc->get_arch_id(cpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_assert((id / 8) < ACPI_GPE_PROC_LEN);
 | 
				
			||||||
 | 
					        gpe_cpu->sts[id / 8] |= (1 << (id % 8));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    memory_region_init_io(&gpe_cpu->io, owner, &AcpiCpuHotplug_ops,
 | 
				
			||||||
 | 
					                          gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);
 | 
				
			||||||
 | 
					    memory_region_add_subregion(parent, base, &gpe_cpu->io);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -185,6 +185,15 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
 | 
				
			|||||||
    acpi_pm1_evt_power_down(&pm->acpi_regs);
 | 
					    acpi_pm1_evt_power_down(&pm->acpi_regs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ich9_cpu_added_req(Notifier *n, void *opaque)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ICH9LPCPMRegs *pm = container_of(n, ICH9LPCPMRegs, cpu_added_notifier);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(pm != NULL);
 | 
				
			||||||
 | 
					    AcpiCpuHotplug_add(&pm->acpi_regs.gpe, &pm->gpe_cpu, CPU(opaque));
 | 
				
			||||||
 | 
					    acpi_update_sci(&pm->acpi_regs, pm->irq);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
 | 
					void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
 | 
				
			||||||
                  qemu_irq sci_irq)
 | 
					                  qemu_irq sci_irq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -210,6 +219,11 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
 | 
				
			|||||||
    qemu_register_reset(pm_reset, pm);
 | 
					    qemu_register_reset(pm_reset, pm);
 | 
				
			||||||
    pm->powerdown_notifier.notify = pm_powerdown_req;
 | 
					    pm->powerdown_notifier.notify = pm_powerdown_req;
 | 
				
			||||||
    qemu_register_powerdown_notifier(&pm->powerdown_notifier);
 | 
					    qemu_register_powerdown_notifier(&pm->powerdown_notifier);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AcpiCpuHotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
 | 
				
			||||||
 | 
					                        &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
 | 
				
			||||||
 | 
					    pm->cpu_added_notifier.notify = ich9_cpu_added_req;
 | 
				
			||||||
 | 
					    qemu_register_cpu_added_notifier(&pm->cpu_added_notifier);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ich9_pm_get_gpe0_blk(Object *obj, Visitor *v,
 | 
					static void ich9_pm_get_gpe0_blk(Object *obj, Visitor *v,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										316
									
								
								hw/acpi/pcihp.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								hw/acpi/pcihp.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,316 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * QEMU<->ACPI BIOS PCI hotplug interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * QEMU supports PCI hotplug via ACPI. This module
 | 
				
			||||||
 | 
					 * implements the interface between QEMU and the ACPI BIOS.
 | 
				
			||||||
 | 
					 * Interface specification - see docs/specs/acpi_pci_hotplug.txt
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2013, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
 | 
				
			||||||
 | 
					 * Copyright (c) 2006 Fabrice Bellard
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU Lesser General Public
 | 
				
			||||||
 | 
					 * License version 2 as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
				
			||||||
 | 
					 * Lesser General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Lesser General Public
 | 
				
			||||||
 | 
					 * License along with this library; if not, see <http://www.gnu.org/licenses/>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Contributions after 2012-01-13 are licensed under the terms of the
 | 
				
			||||||
 | 
					 * GNU GPL, version 2 or (at your option) any later version.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "hw/acpi/pcihp.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "hw/hw.h"
 | 
				
			||||||
 | 
					#include "hw/i386/pc.h"
 | 
				
			||||||
 | 
					#include "hw/pci/pci.h"
 | 
				
			||||||
 | 
					#include "hw/acpi/acpi.h"
 | 
				
			||||||
 | 
					#include "sysemu/sysemu.h"
 | 
				
			||||||
 | 
					#include "qemu/range.h"
 | 
				
			||||||
 | 
					#include "exec/ioport.h"
 | 
				
			||||||
 | 
					#include "exec/address-spaces.h"
 | 
				
			||||||
 | 
					#include "hw/pci/pci_bus.h"
 | 
				
			||||||
 | 
					#include "qom/qom-qobject.h"
 | 
				
			||||||
 | 
					#include "qapi/qmp/qint.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#define DEBUG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DEBUG
 | 
				
			||||||
 | 
					# define ACPI_PCIHP_DPRINTF(format, ...)     printf(format, ## __VA_ARGS__)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					# define ACPI_PCIHP_DPRINTF(format, ...)     do { } while (0)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PCI_HOTPLUG_ADDR 0xae00
 | 
				
			||||||
 | 
					#define PCI_HOTPLUG_SIZE 0x0014
 | 
				
			||||||
 | 
					#define PCI_UP_BASE 0xae00
 | 
				
			||||||
 | 
					#define PCI_DOWN_BASE 0xae04
 | 
				
			||||||
 | 
					#define PCI_EJ_BASE 0xae08
 | 
				
			||||||
 | 
					#define PCI_RMV_BASE 0xae0c
 | 
				
			||||||
 | 
					#define PCI_SEL_BASE 0xae10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct AcpiPciHpFind {
 | 
				
			||||||
 | 
					    int bsel;
 | 
				
			||||||
 | 
					    PCIBus *bus;
 | 
				
			||||||
 | 
					} AcpiPciHpFind;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int acpi_pcihp_get_bsel(PCIBus *bus)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    QObject *o = object_property_get_qobject(OBJECT(bus),
 | 
				
			||||||
 | 
					                                             ACPI_PCIHP_PROP_BSEL, NULL);
 | 
				
			||||||
 | 
					    int64_t bsel = -1;
 | 
				
			||||||
 | 
					    if (o) {
 | 
				
			||||||
 | 
					        bsel = qint_get_int(qobject_to_qint(o));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (bsel < 0) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return bsel;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void acpi_pcihp_test_hotplug_bus(PCIBus *bus, void *opaque)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AcpiPciHpFind *find = opaque;
 | 
				
			||||||
 | 
					    if (find->bsel == acpi_pcihp_get_bsel(bus)) {
 | 
				
			||||||
 | 
					        find->bus = bus;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AcpiPciHpFind find = { .bsel = bsel, .bus = NULL };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bsel < 0) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pci_for_each_bus(s->root, acpi_pcihp_test_hotplug_bus, &find);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Make bsel 0 eject root bus if bsel property is not set,
 | 
				
			||||||
 | 
					     * for compatibility with non acpi setups.
 | 
				
			||||||
 | 
					     * TODO: really needed?
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if (!bsel && !find.bus) {
 | 
				
			||||||
 | 
					        find.bus = s->root;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return find.bus;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * ACPI doesn't allow hotplug of bridge devices.  Don't allow
 | 
				
			||||||
 | 
					     * hot-unplug of bridge devices unless they were added by hotplug
 | 
				
			||||||
 | 
					     * (and so, not described by acpi).
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    return (pc->is_bridge && !dev->qdev.hotplugged) || pc->no_hotplug;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slots)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    BusChild *kid, *next;
 | 
				
			||||||
 | 
					    int slot = ffs(slots) - 1;
 | 
				
			||||||
 | 
					    bool slot_free = true;
 | 
				
			||||||
 | 
					    PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!bus) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Mark request as complete */
 | 
				
			||||||
 | 
					    s->acpi_pcihp_pci_status[bsel].down &= ~(1U << slot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
 | 
				
			||||||
 | 
					        DeviceState *qdev = kid->child;
 | 
				
			||||||
 | 
					        PCIDevice *dev = PCI_DEVICE(qdev);
 | 
				
			||||||
 | 
					        if (PCI_SLOT(dev->devfn) == slot) {
 | 
				
			||||||
 | 
					            if (acpi_pcihp_pc_no_hotplug(s, dev)) {
 | 
				
			||||||
 | 
					                slot_free = false;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                object_unparent(OBJECT(qdev));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (slot_free) {
 | 
				
			||||||
 | 
					        s->acpi_pcihp_pci_status[bsel].device_present &= ~(1U << slot);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    BusChild *kid, *next;
 | 
				
			||||||
 | 
					    PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Execute any pending removes during reset */
 | 
				
			||||||
 | 
					    while (s->acpi_pcihp_pci_status[bsel].down) {
 | 
				
			||||||
 | 
					        acpi_pcihp_eject_slot(s, bsel, s->acpi_pcihp_pci_status[bsel].down);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s->acpi_pcihp_pci_status[bsel].hotplug_enable = ~0;
 | 
				
			||||||
 | 
					    s->acpi_pcihp_pci_status[bsel].device_present = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!bus) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
 | 
				
			||||||
 | 
					        DeviceState *qdev = kid->child;
 | 
				
			||||||
 | 
					        PCIDevice *pdev = PCI_DEVICE(qdev);
 | 
				
			||||||
 | 
					        int slot = PCI_SLOT(pdev->devfn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (acpi_pcihp_pc_no_hotplug(s, pdev)) {
 | 
				
			||||||
 | 
					            s->acpi_pcihp_pci_status[bsel].hotplug_enable &= ~(1U << slot);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void acpi_pcihp_update(AcpiPciHpState *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < ACPI_PCIHP_MAX_HOTPLUG_BUS; ++i) {
 | 
				
			||||||
 | 
					        acpi_pcihp_update_hotplug_bus(s, i);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void acpi_pcihp_reset(AcpiPciHpState *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    acpi_pcihp_update(s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void enable_device(AcpiPciHpState *s, unsigned bsel, int slot)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void disable_device(AcpiPciHpState *s, unsigned bsel, int slot)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int acpi_pcihp_device_hotplug(AcpiPciHpState *s, PCIDevice *dev,
 | 
				
			||||||
 | 
					                              PCIHotplugState state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int slot = PCI_SLOT(dev->devfn);
 | 
				
			||||||
 | 
					    int bsel = acpi_pcihp_get_bsel(dev->bus);
 | 
				
			||||||
 | 
					    if (bsel < 0) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Don't send event when device is enabled during qemu machine creation:
 | 
				
			||||||
 | 
					     * it is present on boot, no hotplug event is necessary. We do send an
 | 
				
			||||||
 | 
					     * event when the device is disabled later. */
 | 
				
			||||||
 | 
					    if (state == PCI_COLDPLUG_ENABLED) {
 | 
				
			||||||
 | 
					        s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot);
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (state == PCI_HOTPLUG_ENABLED) {
 | 
				
			||||||
 | 
					        enable_device(s, bsel, slot);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        disable_device(s, bsel, slot);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AcpiPciHpState *s = opaque;
 | 
				
			||||||
 | 
					    uint32_t val = 0;
 | 
				
			||||||
 | 
					    int bsel = s->hotplug_select;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bsel < 0 || bsel > ACPI_PCIHP_MAX_HOTPLUG_BUS) {
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (addr) {
 | 
				
			||||||
 | 
					    case PCI_UP_BASE - PCI_HOTPLUG_ADDR:
 | 
				
			||||||
 | 
					        /* Manufacture an "up" value to cause a device check on any hotplug
 | 
				
			||||||
 | 
					         * slot with a device.  Extra device checks are harmless. */
 | 
				
			||||||
 | 
					        val = s->acpi_pcihp_pci_status[bsel].device_present &
 | 
				
			||||||
 | 
					            s->acpi_pcihp_pci_status[bsel].hotplug_enable;
 | 
				
			||||||
 | 
					        ACPI_PCIHP_DPRINTF("pci_up_read %" PRIu32 "\n", val);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR:
 | 
				
			||||||
 | 
					        val = s->acpi_pcihp_pci_status[bsel].down;
 | 
				
			||||||
 | 
					        ACPI_PCIHP_DPRINTF("pci_down_read %" PRIu32 "\n", val);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
 | 
				
			||||||
 | 
					        /* No feature defined yet */
 | 
				
			||||||
 | 
					        ACPI_PCIHP_DPRINTF("pci_features_read %" PRIu32 "\n", val);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PCI_RMV_BASE - PCI_HOTPLUG_ADDR:
 | 
				
			||||||
 | 
					        val = s->acpi_pcihp_pci_status[bsel].hotplug_enable;
 | 
				
			||||||
 | 
					        ACPI_PCIHP_DPRINTF("pci_rmv_read %" PRIu32 "\n", val);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PCI_SEL_BASE - PCI_HOTPLUG_ADDR:
 | 
				
			||||||
 | 
					        val = s->hotplug_select;
 | 
				
			||||||
 | 
					        ACPI_PCIHP_DPRINTF("pci_sel_read %" PRIu32 "\n", val);
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pci_write(void *opaque, hwaddr addr, uint64_t data,
 | 
				
			||||||
 | 
					                      unsigned int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AcpiPciHpState *s = opaque;
 | 
				
			||||||
 | 
					    switch (addr) {
 | 
				
			||||||
 | 
					    case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
 | 
				
			||||||
 | 
					        if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        acpi_pcihp_eject_slot(s, s->hotplug_select, data);
 | 
				
			||||||
 | 
					        ACPI_PCIHP_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n",
 | 
				
			||||||
 | 
					                      addr, data);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PCI_SEL_BASE - PCI_HOTPLUG_ADDR:
 | 
				
			||||||
 | 
					        s->hotplug_select = data;
 | 
				
			||||||
 | 
					        ACPI_PCIHP_DPRINTF("pcisel write %" HWADDR_PRIx " <== %" PRIu64 "\n",
 | 
				
			||||||
 | 
					                      addr, data);
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const MemoryRegionOps acpi_pcihp_io_ops = {
 | 
				
			||||||
 | 
					    .read = pci_read,
 | 
				
			||||||
 | 
					    .write = pci_write,
 | 
				
			||||||
 | 
					    .endianness = DEVICE_LITTLE_ENDIAN,
 | 
				
			||||||
 | 
					    .valid = {
 | 
				
			||||||
 | 
					        .min_access_size = 4,
 | 
				
			||||||
 | 
					        .max_access_size = 4,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus,
 | 
				
			||||||
 | 
					                     MemoryRegion *address_space_io)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    s->root= root_bus;
 | 
				
			||||||
 | 
					    memory_region_init_io(&s->io, NULL, &acpi_pcihp_io_ops, s,
 | 
				
			||||||
 | 
					                          "acpi-pci-hotplug",
 | 
				
			||||||
 | 
					                          PCI_HOTPLUG_SIZE);
 | 
				
			||||||
 | 
					    memory_region_add_subregion(address_space_io, PCI_HOTPLUG_ADDR, &s->io);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const VMStateDescription vmstate_acpi_pcihp_pci_status = {
 | 
				
			||||||
 | 
					    .name = "acpi_pcihp_pci_status",
 | 
				
			||||||
 | 
					    .version_id = 1,
 | 
				
			||||||
 | 
					    .minimum_version_id = 1,
 | 
				
			||||||
 | 
					    .minimum_version_id_old = 1,
 | 
				
			||||||
 | 
					    .fields      = (VMStateField []) {
 | 
				
			||||||
 | 
					        VMSTATE_UINT32(up, AcpiPciHpPciStatus),
 | 
				
			||||||
 | 
					        VMSTATE_UINT32(down, AcpiPciHpPciStatus),
 | 
				
			||||||
 | 
					        VMSTATE_END_OF_LIST()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										155
									
								
								hw/acpi/piix4.c
									
									
									
									
									
								
							
							
						
						
									
										155
									
								
								hw/acpi/piix4.c
									
									
									
									
									
								
							@ -30,6 +30,8 @@
 | 
				
			|||||||
#include "hw/nvram/fw_cfg.h"
 | 
					#include "hw/nvram/fw_cfg.h"
 | 
				
			||||||
#include "exec/address-spaces.h"
 | 
					#include "exec/address-spaces.h"
 | 
				
			||||||
#include "hw/acpi/piix4.h"
 | 
					#include "hw/acpi/piix4.h"
 | 
				
			||||||
 | 
					#include "hw/acpi/pcihp.h"
 | 
				
			||||||
 | 
					#include "hw/acpi/cpu_hotplug.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//#define DEBUG
 | 
					//#define DEBUG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -49,21 +51,13 @@
 | 
				
			|||||||
#define PCI_EJ_BASE 0xae08
 | 
					#define PCI_EJ_BASE 0xae08
 | 
				
			||||||
#define PCI_RMV_BASE 0xae0c
 | 
					#define PCI_RMV_BASE 0xae0c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PIIX4_PROC_BASE 0xaf00
 | 
					 | 
				
			||||||
#define PIIX4_PROC_LEN 32
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define PIIX4_PCI_HOTPLUG_STATUS 2
 | 
					#define PIIX4_PCI_HOTPLUG_STATUS 2
 | 
				
			||||||
#define PIIX4_CPU_HOTPLUG_STATUS 4
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct pci_status {
 | 
					struct pci_status {
 | 
				
			||||||
    uint32_t up; /* deprecated, maintained for migration compatibility */
 | 
					    uint32_t up; /* deprecated, maintained for migration compatibility */
 | 
				
			||||||
    uint32_t down;
 | 
					    uint32_t down;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct CPUStatus {
 | 
					 | 
				
			||||||
    uint8_t sts[PIIX4_PROC_LEN];
 | 
					 | 
				
			||||||
} CPUStatus;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct PIIX4PMState {
 | 
					typedef struct PIIX4PMState {
 | 
				
			||||||
    /*< private >*/
 | 
					    /*< private >*/
 | 
				
			||||||
    PCIDevice parent_obj;
 | 
					    PCIDevice parent_obj;
 | 
				
			||||||
@ -73,8 +67,6 @@ typedef struct PIIX4PMState {
 | 
				
			|||||||
    uint32_t io_base;
 | 
					    uint32_t io_base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MemoryRegion io_gpe;
 | 
					    MemoryRegion io_gpe;
 | 
				
			||||||
    MemoryRegion io_pci;
 | 
					 | 
				
			||||||
    MemoryRegion io_cpu;
 | 
					 | 
				
			||||||
    ACPIREGS ar;
 | 
					    ACPIREGS ar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    APMState apm;
 | 
					    APMState apm;
 | 
				
			||||||
@ -88,16 +80,21 @@ typedef struct PIIX4PMState {
 | 
				
			|||||||
    Notifier machine_ready;
 | 
					    Notifier machine_ready;
 | 
				
			||||||
    Notifier powerdown_notifier;
 | 
					    Notifier powerdown_notifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* for pci hotplug */
 | 
					    /* for legacy pci hotplug (compatible with qemu 1.6 and older) */
 | 
				
			||||||
 | 
					    MemoryRegion io_pci;
 | 
				
			||||||
    struct pci_status pci0_status;
 | 
					    struct pci_status pci0_status;
 | 
				
			||||||
    uint32_t pci0_hotplug_enable;
 | 
					    uint32_t pci0_hotplug_enable;
 | 
				
			||||||
    uint32_t pci0_slot_device_present;
 | 
					    uint32_t pci0_slot_device_present;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* for new pci hotplug (with PCI2PCI bridge support) */
 | 
				
			||||||
 | 
					    AcpiPciHpState acpi_pci_hotplug;
 | 
				
			||||||
 | 
					    bool use_acpi_pci_hotplug;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t disable_s3;
 | 
					    uint8_t disable_s3;
 | 
				
			||||||
    uint8_t disable_s4;
 | 
					    uint8_t disable_s4;
 | 
				
			||||||
    uint8_t s4_val;
 | 
					    uint8_t s4_val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CPUStatus gpe_cpu;
 | 
					    AcpiCpuHotplug gpe_cpu;
 | 
				
			||||||
    Notifier cpu_added_notifier;
 | 
					    Notifier cpu_added_notifier;
 | 
				
			||||||
} PIIX4PMState;
 | 
					} PIIX4PMState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -263,6 +260,18 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool vmstate_test_use_acpi_pci_hotplug(void *opaque, int version_id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PIIX4PMState *s = opaque;
 | 
				
			||||||
 | 
					    return s->use_acpi_pci_hotplug;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool vmstate_test_no_use_acpi_pci_hotplug(void *opaque, int version_id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PIIX4PMState *s = opaque;
 | 
				
			||||||
 | 
					    return !s->use_acpi_pci_hotplug;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* qemu-kvm 1.2 uses version 3 but advertised as 2
 | 
					/* qemu-kvm 1.2 uses version 3 but advertised as 2
 | 
				
			||||||
 * To support incoming qemu-kvm 1.2 migration, change version_id
 | 
					 * To support incoming qemu-kvm 1.2 migration, change version_id
 | 
				
			||||||
 * and minimum_version_id to 2 below (which breaks migration from
 | 
					 * and minimum_version_id to 2 below (which breaks migration from
 | 
				
			||||||
@ -285,8 +294,12 @@ static const VMStateDescription vmstate_acpi = {
 | 
				
			|||||||
        VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState),
 | 
					        VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState),
 | 
				
			||||||
        VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
 | 
					        VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
 | 
				
			||||||
        VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
 | 
					        VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
 | 
				
			||||||
        VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
 | 
					        VMSTATE_STRUCT_TEST(pci0_status, PIIX4PMState,
 | 
				
			||||||
                       struct pci_status),
 | 
					                            vmstate_test_no_use_acpi_pci_hotplug,
 | 
				
			||||||
 | 
					                            2, vmstate_pci_status,
 | 
				
			||||||
 | 
					                            struct pci_status),
 | 
				
			||||||
 | 
					        VMSTATE_PCI_HOTPLUG(acpi_pci_hotplug, PIIX4PMState,
 | 
				
			||||||
 | 
					                            vmstate_test_use_acpi_pci_hotplug),
 | 
				
			||||||
        VMSTATE_END_OF_LIST()
 | 
					        VMSTATE_END_OF_LIST()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -364,7 +377,11 @@ static void piix4_reset(void *opaque)
 | 
				
			|||||||
        pci_conf[0x5B] = 0x02;
 | 
					        pci_conf[0x5B] = 0x02;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pm_io_space_update(s);
 | 
					    pm_io_space_update(s);
 | 
				
			||||||
    piix4_update_hotplug(s);
 | 
					    if (s->use_acpi_pci_hotplug) {
 | 
				
			||||||
 | 
					        acpi_pcihp_reset(&s->acpi_pci_hotplug);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        piix4_update_hotplug(s);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
 | 
					static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
 | 
				
			||||||
@ -375,6 +392,26 @@ static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
 | 
				
			|||||||
    acpi_pm1_evt_power_down(&s->ar);
 | 
					    acpi_pm1_evt_power_down(&s->ar);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int piix4_acpi_pci_hotplug(DeviceState *qdev, PCIDevice *dev,
 | 
				
			||||||
 | 
					                                  PCIHotplugState state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PIIX4PMState *s = PIIX4_PM(qdev);
 | 
				
			||||||
 | 
					    int ret = acpi_pcihp_device_hotplug(&s->acpi_pci_hotplug, dev, state);
 | 
				
			||||||
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    acpi_update_sci(&s->ar, s->irq);
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void piix4_update_bus_hotplug(PCIBus *bus, void *opaque)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PIIX4PMState *s = opaque;
 | 
				
			||||||
 | 
					    pci_bus_hotplug(bus, piix4_acpi_pci_hotplug, DEVICE(s));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void piix4_pm_machine_ready(Notifier *n, void *opaque)
 | 
					static void piix4_pm_machine_ready(Notifier *n, void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
 | 
					    PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
 | 
				
			||||||
@ -388,6 +425,10 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque)
 | 
				
			|||||||
    pci_conf[0x63] = 0x60;
 | 
					    pci_conf[0x63] = 0x60;
 | 
				
			||||||
    pci_conf[0x67] = (memory_region_present(io_as, 0x3f8) ? 0x08 : 0) |
 | 
					    pci_conf[0x67] = (memory_region_present(io_as, 0x3f8) ? 0x08 : 0) |
 | 
				
			||||||
        (memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
 | 
					        (memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (s->use_acpi_pci_hotplug) {
 | 
				
			||||||
 | 
					        pci_for_each_bus(d->bus, piix4_update_bus_hotplug, s);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void piix4_pm_add_propeties(PIIX4PMState *s)
 | 
					static void piix4_pm_add_propeties(PIIX4PMState *s)
 | 
				
			||||||
@ -509,6 +550,8 @@ static Property piix4_pm_properties[] = {
 | 
				
			|||||||
    DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
 | 
					    DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
 | 
				
			||||||
    DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
 | 
					    DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
 | 
				
			||||||
    DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
 | 
					    DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
 | 
				
			||||||
 | 
					    DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState,
 | 
				
			||||||
 | 
					                     use_acpi_pci_hotplug, true),
 | 
				
			||||||
    DEFINE_PROP_END_OF_LIST(),
 | 
					    DEFINE_PROP_END_OF_LIST(),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -632,61 +675,13 @@ static const MemoryRegionOps piix4_pci_ops = {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    PIIX4PMState *s = opaque;
 | 
					 | 
				
			||||||
    CPUStatus *cpus = &s->gpe_cpu;
 | 
					 | 
				
			||||||
    uint64_t val = cpus->sts[addr];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return val;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
 | 
					 | 
				
			||||||
                             unsigned int size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /* TODO: implement VCPU removal on guest signal that CPU can be removed */
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const MemoryRegionOps cpu_hotplug_ops = {
 | 
					 | 
				
			||||||
    .read = cpu_status_read,
 | 
					 | 
				
			||||||
    .write = cpu_status_write,
 | 
					 | 
				
			||||||
    .endianness = DEVICE_LITTLE_ENDIAN,
 | 
					 | 
				
			||||||
    .valid = {
 | 
					 | 
				
			||||||
        .min_access_size = 1,
 | 
					 | 
				
			||||||
        .max_access_size = 1,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef enum {
 | 
					 | 
				
			||||||
    PLUG,
 | 
					 | 
				
			||||||
    UNPLUG,
 | 
					 | 
				
			||||||
} HotplugEventType;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu,
 | 
					 | 
				
			||||||
                                  HotplugEventType action)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    CPUStatus *g = &s->gpe_cpu;
 | 
					 | 
				
			||||||
    ACPIGPE *gpe = &s->ar.gpe;
 | 
					 | 
				
			||||||
    CPUClass *k = CPU_GET_CLASS(cpu);
 | 
					 | 
				
			||||||
    int64_t cpu_id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    assert(s != NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
 | 
					 | 
				
			||||||
    cpu_id = k->get_arch_id(CPU(cpu));
 | 
					 | 
				
			||||||
    if (action == PLUG) {
 | 
					 | 
				
			||||||
        g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        g->sts[cpu_id / 8] &= ~(1 << (cpu_id % 8));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    acpi_update_sci(&s->ar, s->irq);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void piix4_cpu_added_req(Notifier *n, void *opaque)
 | 
					static void piix4_cpu_added_req(Notifier *n, void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier);
 | 
					    PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    piix4_cpu_hotplug_req(s, CPU(opaque), PLUG);
 | 
					    assert(s != NULL);
 | 
				
			||||||
 | 
					    AcpiCpuHotplug_add(&s->ar.gpe, &s->gpe_cpu, CPU(opaque));
 | 
				
			||||||
 | 
					    acpi_update_sci(&s->ar, s->irq);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 | 
					static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 | 
				
			||||||
@ -695,28 +690,22 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 | 
				
			|||||||
static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
 | 
					static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
 | 
				
			||||||
                                           PCIBus *bus, PIIX4PMState *s)
 | 
					                                           PCIBus *bus, PIIX4PMState *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CPUState *cpu;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    memory_region_init_io(&s->io_gpe, OBJECT(s), &piix4_gpe_ops, s,
 | 
					    memory_region_init_io(&s->io_gpe, OBJECT(s), &piix4_gpe_ops, s,
 | 
				
			||||||
                          "acpi-gpe0", GPE_LEN);
 | 
					                          "acpi-gpe0", GPE_LEN);
 | 
				
			||||||
    memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
 | 
					    memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memory_region_init_io(&s->io_pci, OBJECT(s), &piix4_pci_ops, s,
 | 
					    if (s->use_acpi_pci_hotplug) {
 | 
				
			||||||
                          "acpi-pci-hotplug", PCI_HOTPLUG_SIZE);
 | 
					        acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent);
 | 
				
			||||||
    memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
 | 
					    } else {
 | 
				
			||||||
                                &s->io_pci);
 | 
					        memory_region_init_io(&s->io_pci, OBJECT(s), &piix4_pci_ops, s,
 | 
				
			||||||
    pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s));
 | 
					                              "acpi-pci-hotplug", PCI_HOTPLUG_SIZE);
 | 
				
			||||||
 | 
					        memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
 | 
				
			||||||
    CPU_FOREACH(cpu) {
 | 
					                                    &s->io_pci);
 | 
				
			||||||
        CPUClass *cc = CPU_GET_CLASS(cpu);
 | 
					        pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s));
 | 
				
			||||||
        int64_t id = cc->get_arch_id(cpu);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        g_assert((id / 8) < PIIX4_PROC_LEN);
 | 
					 | 
				
			||||||
        s->gpe_cpu.sts[id / 8] |= (1 << (id % 8));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    memory_region_init_io(&s->io_cpu, OBJECT(s), &cpu_hotplug_ops, s,
 | 
					
 | 
				
			||||||
                          "acpi-cpu-hotplug", PIIX4_PROC_LEN);
 | 
					    AcpiCpuHotplug_init(parent, OBJECT(s), &s->gpe_cpu,
 | 
				
			||||||
    memory_region_add_subregion(parent, PIIX4_PROC_BASE, &s->io_cpu);
 | 
					                        PIIX4_CPU_HOTPLUG_IO_BASE);
 | 
				
			||||||
    s->cpu_added_notifier.notify = piix4_cpu_added_req;
 | 
					    s->cpu_added_notifier.notify = piix4_cpu_added_req;
 | 
				
			||||||
    qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
 | 
					    qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
 | 
				
			|||||||
ifdef IASL
 | 
					ifdef IASL
 | 
				
			||||||
#IASL Present. Generate hex files from .dsl
 | 
					#IASL Present. Generate hex files from .dsl
 | 
				
			||||||
hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.dsl $(SRC_PATH)/scripts/acpi_extract_preprocess.py $(SRC_PATH)/scripts/acpi_extract.py
 | 
					hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.dsl $(SRC_PATH)/scripts/acpi_extract_preprocess.py $(SRC_PATH)/scripts/acpi_extract.py
 | 
				
			||||||
	$(call quiet-command, cpp -P $< -o $*.dsl.i.orig, "  CPP $(TARGET_DIR)$*.dsl.i.orig")
 | 
						$(call quiet-command, cpp -P $(QEMU_DGFLAGS) $(QEMU_INCLUDES) $< -o $*.dsl.i.orig, "  CPP $(TARGET_DIR)$*.dsl.i.orig")
 | 
				
			||||||
	$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract_preprocess.py $*.dsl.i.orig > $*.dsl.i, "  ACPI_PREPROCESS $(TARGET_DIR)$*.dsl.i")
 | 
						$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract_preprocess.py $*.dsl.i.orig > $*.dsl.i, "  ACPI_PREPROCESS $(TARGET_DIR)$*.dsl.i")
 | 
				
			||||||
	$(call quiet-command, $(IASL) $(call iasl-option,$(IASL),-Pn,) -vs -l -tc -p $* $*.dsl.i $(if $(V), , > /dev/null) 2>&1 ,"  IASL $(TARGET_DIR)$*.dsl.i")
 | 
						$(call quiet-command, $(IASL) $(call iasl-option,$(IASL),-Pn,) -vs -l -tc -p $* $*.dsl.i $(if $(V), , > /dev/null) 2>&1 ,"  IASL $(TARGET_DIR)$*.dsl.i")
 | 
				
			||||||
	$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract.py $*.lst > $*.off, "  ACPI_EXTRACT $(TARGET_DIR)$*.off")
 | 
						$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract.py $*.lst > $*.off, "  ACPI_EXTRACT $(TARGET_DIR)$*.off")
 | 
				
			||||||
 | 
				
			|||||||
@ -36,9 +36,11 @@
 | 
				
			|||||||
#include "hw/nvram/fw_cfg.h"
 | 
					#include "hw/nvram/fw_cfg.h"
 | 
				
			||||||
#include "bios-linker-loader.h"
 | 
					#include "bios-linker-loader.h"
 | 
				
			||||||
#include "hw/loader.h"
 | 
					#include "hw/loader.h"
 | 
				
			||||||
 | 
					#include "hw/isa/isa.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Supported chipsets: */
 | 
					/* Supported chipsets: */
 | 
				
			||||||
#include "hw/acpi/piix4.h"
 | 
					#include "hw/acpi/piix4.h"
 | 
				
			||||||
 | 
					#include "hw/acpi/pcihp.h"
 | 
				
			||||||
#include "hw/i386/ich9.h"
 | 
					#include "hw/i386/ich9.h"
 | 
				
			||||||
#include "hw/pci/pci_bus.h"
 | 
					#include "hw/pci/pci_bus.h"
 | 
				
			||||||
#include "hw/pci-host/q35.h"
 | 
					#include "hw/pci-host/q35.h"
 | 
				
			||||||
@ -78,8 +80,15 @@ typedef struct AcpiMiscInfo {
 | 
				
			|||||||
    uint16_t pvpanic_port;
 | 
					    uint16_t pvpanic_port;
 | 
				
			||||||
} AcpiMiscInfo;
 | 
					} AcpiMiscInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct AcpiBuildPciBusHotplugState {
 | 
				
			||||||
 | 
					    GArray *device_table;
 | 
				
			||||||
 | 
					    GArray *notify_table;
 | 
				
			||||||
 | 
					    struct AcpiBuildPciBusHotplugState *parent;
 | 
				
			||||||
 | 
					} AcpiBuildPciBusHotplugState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void acpi_get_dsdt(AcpiMiscInfo *info)
 | 
					static void acpi_get_dsdt(AcpiMiscInfo *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t *applesmc_sta;
 | 
				
			||||||
    Object *piix = piix4_pm_find();
 | 
					    Object *piix = piix4_pm_find();
 | 
				
			||||||
    Object *lpc = ich9_lpc_find();
 | 
					    Object *lpc = ich9_lpc_find();
 | 
				
			||||||
    assert(!!piix != !!lpc);
 | 
					    assert(!!piix != !!lpc);
 | 
				
			||||||
@ -87,11 +96,17 @@ static void acpi_get_dsdt(AcpiMiscInfo *info)
 | 
				
			|||||||
    if (piix) {
 | 
					    if (piix) {
 | 
				
			||||||
        info->dsdt_code = AcpiDsdtAmlCode;
 | 
					        info->dsdt_code = AcpiDsdtAmlCode;
 | 
				
			||||||
        info->dsdt_size = sizeof AcpiDsdtAmlCode;
 | 
					        info->dsdt_size = sizeof AcpiDsdtAmlCode;
 | 
				
			||||||
 | 
					        applesmc_sta = piix_dsdt_applesmc_sta;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (lpc) {
 | 
					    if (lpc) {
 | 
				
			||||||
        info->dsdt_code = Q35AcpiDsdtAmlCode;
 | 
					        info->dsdt_code = Q35AcpiDsdtAmlCode;
 | 
				
			||||||
        info->dsdt_size = sizeof Q35AcpiDsdtAmlCode;
 | 
					        info->dsdt_size = sizeof Q35AcpiDsdtAmlCode;
 | 
				
			||||||
 | 
					        applesmc_sta = q35_dsdt_applesmc_sta;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Patch in appropriate value for AppleSMC _STA */
 | 
				
			||||||
 | 
					    *(uint8_t *)(info->dsdt_code + *applesmc_sta) =
 | 
				
			||||||
 | 
					        applesmc_find() ? 0x0b : 0x00;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
@ -171,38 +186,6 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
 | 
				
			|||||||
                                               NULL);
 | 
					                                               NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void acpi_get_hotplug_info(AcpiMiscInfo *misc)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int i;
 | 
					 | 
				
			||||||
    PCIBus *bus = find_i440fx();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!bus) {
 | 
					 | 
				
			||||||
        /* Only PIIX supports ACPI hotplug */
 | 
					 | 
				
			||||||
        memset(misc->slot_hotplug_enable, 0, sizeof misc->slot_hotplug_enable);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    memset(misc->slot_hotplug_enable, 0xff,
 | 
					 | 
				
			||||||
           DIV_ROUND_UP(PCI_SLOT_MAX, BITS_PER_BYTE));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
 | 
					 | 
				
			||||||
        PCIDeviceClass *pc;
 | 
					 | 
				
			||||||
        PCIDevice *pdev = bus->devices[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!pdev) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        pc = PCI_DEVICE_GET_CLASS(pdev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (pc->no_hotplug) {
 | 
					 | 
				
			||||||
            int slot = PCI_SLOT(i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            clear_bit(slot, misc->slot_hotplug_enable);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void acpi_get_misc_info(AcpiMiscInfo *info)
 | 
					static void acpi_get_misc_info(AcpiMiscInfo *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    info->has_hpet = hpet_find();
 | 
					    info->has_hpet = hpet_find();
 | 
				
			||||||
@ -368,6 +351,12 @@ static void build_package(GArray *package, uint8_t op, unsigned min_bytes)
 | 
				
			|||||||
    build_prepend_byte(package, op);
 | 
					    build_prepend_byte(package, op);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void build_extop_package(GArray *package, uint8_t op)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    build_package(package, op, 1);
 | 
				
			||||||
 | 
					    build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void build_append_value(GArray *table, uint32_t value, int size)
 | 
					static void build_append_value(GArray *table, uint32_t value, int size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint8_t prefix;
 | 
					    uint8_t prefix;
 | 
				
			||||||
@ -394,8 +383,44 @@ static void build_append_value(GArray *table, uint32_t value, int size)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void build_append_notify_target(GArray *method, GArray *target_name,
 | 
					static void build_append_int(GArray *table, uint32_t value)
 | 
				
			||||||
                                       uint32_t value, int size)
 | 
					{
 | 
				
			||||||
 | 
					    if (value == 0x00) {
 | 
				
			||||||
 | 
					        build_append_byte(table, 0x00); /* ZeroOp */
 | 
				
			||||||
 | 
					    } else if (value == 0x01) {
 | 
				
			||||||
 | 
					        build_append_byte(table, 0x01); /* OneOp */
 | 
				
			||||||
 | 
					    } else if (value <= 0xFF) {
 | 
				
			||||||
 | 
					        build_append_value(table, value, 1);
 | 
				
			||||||
 | 
					    } else if (value <= 0xFFFFF) {
 | 
				
			||||||
 | 
					        build_append_value(table, value, 2);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        build_append_value(table, value, 4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static GArray *build_alloc_method(const char *name, uint8_t arg_count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GArray *method = build_alloc_array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    build_append_nameseg(method, "%s", name);
 | 
				
			||||||
 | 
					    build_append_byte(method, arg_count); /* MethodFlags: ArgCount */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return method;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void build_append_and_cleanup_method(GArray *device, GArray *method)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t op = 0x14; /* MethodOp */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    build_package(method, op, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    build_append_array(device, method);
 | 
				
			||||||
 | 
					    build_free_array(method);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void build_append_notify_target_ifequal(GArray *method,
 | 
				
			||||||
 | 
					                                               GArray *target_name,
 | 
				
			||||||
 | 
					                                               uint32_t value, int size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GArray *notify = build_alloc_array();
 | 
					    GArray *notify = build_alloc_array();
 | 
				
			||||||
    uint8_t op = 0xA0; /* IfOp */
 | 
					    uint8_t op = 0xA0; /* IfOp */
 | 
				
			||||||
@ -415,6 +440,7 @@ static void build_append_notify_target(GArray *method, GArray *target_name,
 | 
				
			|||||||
    build_free_array(notify);
 | 
					    build_free_array(notify);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* End here */
 | 
				
			||||||
#define ACPI_PORT_SMI_CMD           0x00b2 /* TODO: this is APM_CNT_IOPORT */
 | 
					#define ACPI_PORT_SMI_CMD           0x00b2 /* TODO: this is APM_CNT_IOPORT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void *acpi_data_push(GArray *table_data, unsigned size)
 | 
					static inline void *acpi_data_push(GArray *table_data, unsigned size)
 | 
				
			||||||
@ -624,44 +650,236 @@ static inline char acpi_get_hex(uint32_t val)
 | 
				
			|||||||
#include "hw/i386/ssdt-pcihp.hex"
 | 
					#include "hw/i386/ssdt-pcihp.hex"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
build_append_notify(GArray *device, const char *name,
 | 
					build_append_notify_method(GArray *device, const char *name,
 | 
				
			||||||
                    const char *format, int skip, int count)
 | 
					                           const char *format, int count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    GArray *method = build_alloc_array();
 | 
					    GArray *method = build_alloc_method(name, 2);
 | 
				
			||||||
    uint8_t op = 0x14; /* MethodOp */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    build_append_nameseg(method, "%s", name);
 | 
					    for (i = 0; i < count; i++) {
 | 
				
			||||||
    build_append_byte(method, 0x02); /* MethodFlags: ArgCount */
 | 
					 | 
				
			||||||
    for (i = skip; i < count; i++) {
 | 
					 | 
				
			||||||
        GArray *target = build_alloc_array();
 | 
					        GArray *target = build_alloc_array();
 | 
				
			||||||
        build_append_nameseg(target, format, i);
 | 
					        build_append_nameseg(target, format, i);
 | 
				
			||||||
        assert(i < 256); /* Fits in 1 byte */
 | 
					        assert(i < 256); /* Fits in 1 byte */
 | 
				
			||||||
        build_append_notify_target(method, target, i, 1);
 | 
					        build_append_notify_target_ifequal(method, target, i, 1);
 | 
				
			||||||
        build_free_array(target);
 | 
					        build_free_array(target);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    build_package(method, op, 2);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    build_append_array(device, method);
 | 
					    build_append_and_cleanup_method(device, method);
 | 
				
			||||||
    build_free_array(method);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void patch_pcihp(int slot, uint8_t *ssdt_ptr, uint32_t eject)
 | 
					static void patch_pcihp(int slot, uint8_t *ssdt_ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX] = acpi_get_hex(slot >> 4);
 | 
					    unsigned devfn = PCI_DEVFN(slot, 0);
 | 
				
			||||||
    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX + 1] = acpi_get_hex(slot);
 | 
					
 | 
				
			||||||
 | 
					    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
 | 
				
			||||||
 | 
					    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX + 1] = acpi_get_hex(devfn);
 | 
				
			||||||
    ssdt_ptr[ACPI_PCIHP_OFFSET_ID] = slot;
 | 
					    ssdt_ptr[ACPI_PCIHP_OFFSET_ID] = slot;
 | 
				
			||||||
    ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot;
 | 
					    ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Runtime patching of ACPI_EJ0: to disable hotplug for a slot,
 | 
					/* Assign BSEL property to all buses.  In the future, this can be changed
 | 
				
			||||||
     * replace the method name: _EJ0 by ACPI_EJ0_.
 | 
					 * to only assign to buses that support hotplug.
 | 
				
			||||||
     */
 | 
					 */
 | 
				
			||||||
    /* Sanity check */
 | 
					static void *acpi_set_bsel(PCIBus *bus, void *opaque)
 | 
				
			||||||
    assert(!memcmp(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "_EJ0", 4));
 | 
					{
 | 
				
			||||||
 | 
					    unsigned *bsel_alloc = opaque;
 | 
				
			||||||
 | 
					    unsigned *bus_bsel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!eject) {
 | 
					    if (bus->qbus.allow_hotplug) {
 | 
				
			||||||
        memcpy(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "EJ0_", 4);
 | 
					        bus_bsel = g_malloc(sizeof *bus_bsel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *bus_bsel = (*bsel_alloc)++;
 | 
				
			||||||
 | 
					        object_property_add_uint32_ptr(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
 | 
				
			||||||
 | 
					                                       bus_bsel, NULL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return bsel_alloc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void acpi_set_pci_info(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PCIBus *bus = find_i440fx(); /* TODO: Q35 support */
 | 
				
			||||||
 | 
					    unsigned bsel_alloc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bus) {
 | 
				
			||||||
 | 
					        /* Scan all PCI buses. Set property to enable acpi based hotplug. */
 | 
				
			||||||
 | 
					        pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, &bsel_alloc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void build_pci_bus_state_init(AcpiBuildPciBusHotplugState *state,
 | 
				
			||||||
 | 
					                                     AcpiBuildPciBusHotplugState *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    state->parent = parent;
 | 
				
			||||||
 | 
					    state->device_table = build_alloc_array();
 | 
				
			||||||
 | 
					    state->notify_table = build_alloc_array();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void build_pci_bus_state_cleanup(AcpiBuildPciBusHotplugState *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    build_free_array(state->device_table);
 | 
				
			||||||
 | 
					    build_free_array(state->notify_table);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void *build_pci_bus_begin(PCIBus *bus, void *parent_state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AcpiBuildPciBusHotplugState *parent = parent_state;
 | 
				
			||||||
 | 
					    AcpiBuildPciBusHotplugState *child = g_malloc(sizeof *child);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    build_pci_bus_state_init(child, parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return child;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void build_pci_bus_end(PCIBus *bus, void *bus_state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AcpiBuildPciBusHotplugState *child = bus_state;
 | 
				
			||||||
 | 
					    AcpiBuildPciBusHotplugState *parent = child->parent;
 | 
				
			||||||
 | 
					    GArray *bus_table = build_alloc_array();
 | 
				
			||||||
 | 
					    DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
 | 
				
			||||||
 | 
					    uint8_t op;
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    QObject *bsel;
 | 
				
			||||||
 | 
					    GArray *method;
 | 
				
			||||||
 | 
					    bool bus_hotplug_support = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bus->parent_dev) {
 | 
				
			||||||
 | 
					        op = 0x82; /* DeviceOp */
 | 
				
			||||||
 | 
					        build_append_nameseg(bus_table, "S%.02X_",
 | 
				
			||||||
 | 
					                             bus->parent_dev->devfn);
 | 
				
			||||||
 | 
					        build_append_byte(bus_table, 0x08); /* NameOp */
 | 
				
			||||||
 | 
					        build_append_nameseg(bus_table, "_SUN");
 | 
				
			||||||
 | 
					        build_append_value(bus_table, PCI_SLOT(bus->parent_dev->devfn), 1);
 | 
				
			||||||
 | 
					        build_append_byte(bus_table, 0x08); /* NameOp */
 | 
				
			||||||
 | 
					        build_append_nameseg(bus_table, "_ADR");
 | 
				
			||||||
 | 
					        build_append_value(bus_table, (PCI_SLOT(bus->parent_dev->devfn) << 16) |
 | 
				
			||||||
 | 
					                           PCI_FUNC(bus->parent_dev->devfn), 4);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        op = 0x10; /* ScopeOp */;
 | 
				
			||||||
 | 
					        build_append_nameseg(bus_table, "PCI0");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
 | 
				
			||||||
 | 
					    if (bsel) {
 | 
				
			||||||
 | 
					        build_append_byte(bus_table, 0x08); /* NameOp */
 | 
				
			||||||
 | 
					        build_append_nameseg(bus_table, "BSEL");
 | 
				
			||||||
 | 
					        build_append_int(bus_table, qint_get_int(qobject_to_qint(bsel)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
 | 
				
			||||||
 | 
					            PCIDeviceClass *pc;
 | 
				
			||||||
 | 
					            PCIDevice *pdev = bus->devices[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!pdev) {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pc = PCI_DEVICE_GET_CLASS(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (pc->no_hotplug || pc->is_bridge) {
 | 
				
			||||||
 | 
					                int slot = PCI_SLOT(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                clear_bit(slot, slot_hotplug_enable);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Append Device object for each slot which supports eject */
 | 
				
			||||||
 | 
					        for (i = 0; i < PCI_SLOT_MAX; i++) {
 | 
				
			||||||
 | 
					            bool can_eject = test_bit(i, slot_hotplug_enable);
 | 
				
			||||||
 | 
					            if (can_eject) {
 | 
				
			||||||
 | 
					                void *pcihp = acpi_data_push(bus_table,
 | 
				
			||||||
 | 
					                                             ACPI_PCIHP_SIZEOF);
 | 
				
			||||||
 | 
					                memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
 | 
				
			||||||
 | 
					                patch_pcihp(i, pcihp);
 | 
				
			||||||
 | 
					                bus_hotplug_support = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        method = build_alloc_method("DVNT", 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (i = 0; i < PCI_SLOT_MAX; i++) {
 | 
				
			||||||
 | 
					            GArray *notify;
 | 
				
			||||||
 | 
					            uint8_t op;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!test_bit(i, slot_hotplug_enable)) {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            notify = build_alloc_array();
 | 
				
			||||||
 | 
					            op = 0xA0; /* IfOp */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            build_append_byte(notify, 0x7B); /* AndOp */
 | 
				
			||||||
 | 
					            build_append_byte(notify, 0x68); /* Arg0Op */
 | 
				
			||||||
 | 
					            build_append_int(notify, 0x1 << i);
 | 
				
			||||||
 | 
					            build_append_byte(notify, 0x00); /* NullName */
 | 
				
			||||||
 | 
					            build_append_byte(notify, 0x86); /* NotifyOp */
 | 
				
			||||||
 | 
					            build_append_nameseg(notify, "S%.02X_", PCI_DEVFN(i, 0));
 | 
				
			||||||
 | 
					            build_append_byte(notify, 0x69); /* Arg1Op */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Pack it up */
 | 
				
			||||||
 | 
					            build_package(notify, op, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            build_append_array(method, notify);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            build_free_array(notify);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        build_append_and_cleanup_method(bus_table, method);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Append PCNT method to notify about events on local and child buses.
 | 
				
			||||||
 | 
					     * Add unconditionally for root since DSDT expects it.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if (bus_hotplug_support || child->notify_table->len || !bus->parent_dev) {
 | 
				
			||||||
 | 
					        method = build_alloc_method("PCNT", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* If bus supports hotplug select it and notify about local events */
 | 
				
			||||||
 | 
					        if (bsel) {
 | 
				
			||||||
 | 
					            build_append_byte(method, 0x70); /* StoreOp */
 | 
				
			||||||
 | 
					            build_append_int(method, qint_get_int(qobject_to_qint(bsel)));
 | 
				
			||||||
 | 
					            build_append_nameseg(method, "BNUM");
 | 
				
			||||||
 | 
					            build_append_nameseg(method, "DVNT");
 | 
				
			||||||
 | 
					            build_append_nameseg(method, "PCIU");
 | 
				
			||||||
 | 
					            build_append_int(method, 1); /* Device Check */
 | 
				
			||||||
 | 
					            build_append_nameseg(method, "DVNT");
 | 
				
			||||||
 | 
					            build_append_nameseg(method, "PCID");
 | 
				
			||||||
 | 
					            build_append_int(method, 3); /* Eject Request */
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Notify about child bus events in any case */
 | 
				
			||||||
 | 
					        build_append_array(method, child->notify_table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        build_append_and_cleanup_method(bus_table, method);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Append description of child buses */
 | 
				
			||||||
 | 
					        build_append_array(bus_table, child->device_table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Pack it up */
 | 
				
			||||||
 | 
					        if (bus->parent_dev) {
 | 
				
			||||||
 | 
					            build_extop_package(bus_table, op);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            build_package(bus_table, op, 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Append our bus description to parent table */
 | 
				
			||||||
 | 
					        build_append_array(parent->device_table, bus_table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Also tell parent how to notify us, invoking PCNT method.
 | 
				
			||||||
 | 
					         * At the moment this is not needed for root as we have a single root.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        if (bus->parent_dev) {
 | 
				
			||||||
 | 
					            build_append_byte(parent->notify_table, '^'); /* ParentPrefixChar */
 | 
				
			||||||
 | 
					            build_append_byte(parent->notify_table, 0x2E); /* DualNamePrefix */
 | 
				
			||||||
 | 
					            build_append_nameseg(parent->notify_table, "S%.02X_",
 | 
				
			||||||
 | 
					                                 bus->parent_dev->devfn);
 | 
				
			||||||
 | 
					            build_append_nameseg(parent->notify_table, "PCNT");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    build_free_array(bus_table);
 | 
				
			||||||
 | 
					    build_pci_bus_state_cleanup(child);
 | 
				
			||||||
 | 
					    g_free(child);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size)
 | 
					static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size)
 | 
				
			||||||
@ -733,7 +951,7 @@ build_ssdt(GArray *table_data, GArray *linker,
 | 
				
			|||||||
         *   Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
 | 
					         *   Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        /* Arg0 = Processor ID = APIC ID */
 | 
					        /* Arg0 = Processor ID = APIC ID */
 | 
				
			||||||
        build_append_notify(sb_scope, "NTFY", "CP%0.02X", 0, acpi_cpus);
 | 
					        build_append_notify_method(sb_scope, "NTFY", "CP%0.02X", acpi_cpus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" */
 | 
					        /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" */
 | 
				
			||||||
        build_append_byte(sb_scope, 0x08); /* NameOp */
 | 
					        build_append_byte(sb_scope, 0x08); /* NameOp */
 | 
				
			||||||
@ -755,24 +973,19 @@ build_ssdt(GArray *table_data, GArray *linker,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            GArray *pci0 = build_alloc_array();
 | 
					            AcpiBuildPciBusHotplugState hotplug_state;
 | 
				
			||||||
            uint8_t op = 0x10; /* ScopeOp */;
 | 
					            PCIBus *bus = find_i440fx(); /* TODO: Q35 support */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            build_append_nameseg(pci0, "PCI0");
 | 
					            build_pci_bus_state_init(&hotplug_state, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* build Device object for each slot */
 | 
					            if (bus) {
 | 
				
			||||||
            for (i = 1; i < PCI_SLOT_MAX; i++) {
 | 
					                /* Scan all PCI buses. Generate tables to support hotplug. */
 | 
				
			||||||
                bool eject = test_bit(i, misc->slot_hotplug_enable);
 | 
					                pci_for_each_bus_depth_first(bus, build_pci_bus_begin,
 | 
				
			||||||
                void *pcihp = acpi_data_push(pci0, ACPI_PCIHP_SIZEOF);
 | 
					                                             build_pci_bus_end, &hotplug_state);
 | 
				
			||||||
 | 
					 | 
				
			||||||
                memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
 | 
					 | 
				
			||||||
                patch_pcihp(i, pcihp, eject);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            build_append_notify(pci0, "PCNT", "S%0.02X_", 1, PCI_SLOT_MAX);
 | 
					            build_append_array(sb_scope, hotplug_state.device_table);
 | 
				
			||||||
            build_package(pci0, op, 3);
 | 
					            build_pci_bus_state_cleanup(&hotplug_state);
 | 
				
			||||||
            build_append_array(sb_scope, pci0);
 | 
					 | 
				
			||||||
            build_free_array(pci0);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        build_package(sb_scope, op, 3);
 | 
					        build_package(sb_scope, op, 3);
 | 
				
			||||||
@ -867,16 +1080,16 @@ build_srat(GArray *table_data, GArray *linker,
 | 
				
			|||||||
        next_base = mem_base + mem_len;
 | 
					        next_base = mem_base + mem_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Cut out the ACPI_PCI hole */
 | 
					        /* Cut out the ACPI_PCI hole */
 | 
				
			||||||
        if (mem_base <= guest_info->ram_size &&
 | 
					        if (mem_base <= guest_info->ram_size_below_4g &&
 | 
				
			||||||
            next_base > guest_info->ram_size) {
 | 
					            next_base > guest_info->ram_size_below_4g) {
 | 
				
			||||||
            mem_len -= next_base - guest_info->ram_size;
 | 
					            mem_len -= next_base - guest_info->ram_size_below_4g;
 | 
				
			||||||
            if (mem_len > 0) {
 | 
					            if (mem_len > 0) {
 | 
				
			||||||
                numamem = acpi_data_push(table_data, sizeof *numamem);
 | 
					                numamem = acpi_data_push(table_data, sizeof *numamem);
 | 
				
			||||||
                acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
 | 
					                acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            mem_base = 1ULL << 32;
 | 
					            mem_base = 1ULL << 32;
 | 
				
			||||||
            mem_len = next_base - guest_info->ram_size;
 | 
					            mem_len = next_base - guest_info->ram_size_below_4g;
 | 
				
			||||||
            next_base += (1ULL << 32) - guest_info->ram_size;
 | 
					            next_base += (1ULL << 32) - guest_info->ram_size_below_4g;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        numamem = acpi_data_push(table_data, sizeof *numamem);
 | 
					        numamem = acpi_data_push(table_data, sizeof *numamem);
 | 
				
			||||||
        acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1, 1);
 | 
					        acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1, 1);
 | 
				
			||||||
@ -1055,7 +1268,6 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
 | 
				
			|||||||
    acpi_get_cpu_info(&cpu);
 | 
					    acpi_get_cpu_info(&cpu);
 | 
				
			||||||
    acpi_get_pm_info(&pm);
 | 
					    acpi_get_pm_info(&pm);
 | 
				
			||||||
    acpi_get_dsdt(&misc);
 | 
					    acpi_get_dsdt(&misc);
 | 
				
			||||||
    acpi_get_hotplug_info(&misc);
 | 
					 | 
				
			||||||
    acpi_get_misc_info(&misc);
 | 
					    acpi_get_misc_info(&misc);
 | 
				
			||||||
    acpi_get_pci_info(&pci);
 | 
					    acpi_get_pci_info(&pci);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1200,6 +1412,8 @@ void acpi_setup(PcGuestInfo *guest_info)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    build_state->guest_info = guest_info;
 | 
					    build_state->guest_info = guest_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    acpi_set_pci_info();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acpi_build_tables_init(&tables);
 | 
					    acpi_build_tables_init(&tables);
 | 
				
			||||||
    acpi_build(build_state->guest_info, &tables);
 | 
					    acpi_build(build_state->guest_info, &tables);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@
 | 
				
			|||||||
/****************************************************************
 | 
					/****************************************************************
 | 
				
			||||||
 * CPU hotplug
 | 
					 * CPU hotplug
 | 
				
			||||||
 ****************************************************************/
 | 
					 ****************************************************************/
 | 
				
			||||||
 | 
					#define CPU_HOTPLUG_RESOURCE_DEVICE PRES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Scope(\_SB) {
 | 
					Scope(\_SB) {
 | 
				
			||||||
    /* Objects filled in by run-time generated SSDT */
 | 
					    /* Objects filled in by run-time generated SSDT */
 | 
				
			||||||
@ -52,7 +53,8 @@ Scope(\_SB) {
 | 
				
			|||||||
        Sleep(200)
 | 
					        Sleep(200)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    OperationRegion(PRST, SystemIO, 0xaf00, 32)
 | 
					#define CPU_STATUS_LEN ACPI_GPE_PROC_LEN
 | 
				
			||||||
 | 
					    OperationRegion(PRST, SystemIO, CPU_STATUS_BASE, CPU_STATUS_LEN)
 | 
				
			||||||
    Field(PRST, ByteAcc, NoLock, Preserve) {
 | 
					    Field(PRST, ByteAcc, NoLock, Preserve) {
 | 
				
			||||||
        PRS, 256
 | 
					        PRS, 256
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -89,4 +91,14 @@ Scope(\_SB) {
 | 
				
			|||||||
            Increment(Local0)
 | 
					            Increment(Local0)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Device(CPU_HOTPLUG_RESOURCE_DEVICE) {
 | 
				
			||||||
 | 
					        Name(_HID, "ACPI0004")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Name(_CRS, ResourceTemplate() {
 | 
				
			||||||
 | 
					            IO(Decode16, CPU_STATUS_BASE, CPU_STATUS_BASE, 0, CPU_STATUS_LEN)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Name(_STA, 0xB) /* present, functioning, decoding, not shown in UI */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,17 @@
 | 
				
			|||||||
/* Common legacy ISA style devices. */
 | 
					/* Common legacy ISA style devices. */
 | 
				
			||||||
Scope(\_SB.PCI0.ISA) {
 | 
					Scope(\_SB.PCI0.ISA) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Device (SMC) {
 | 
				
			||||||
 | 
					        Name(_HID, EisaId("APP0001"))
 | 
				
			||||||
 | 
					        /* _STA will be patched to 0x0B if AppleSMC is present */
 | 
				
			||||||
 | 
					        ACPI_EXTRACT_NAME_BYTE_CONST DSDT_APPLESMC_STA
 | 
				
			||||||
 | 
					        Name(_STA, 0xF0)
 | 
				
			||||||
 | 
					        Name(_CRS, ResourceTemplate () {
 | 
				
			||||||
 | 
					            IO (Decode16, 0x0300, 0x0300, 0x01, 0x20)
 | 
				
			||||||
 | 
					            IRQNoFlags() { 6 }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Device(RTC) {
 | 
					    Device(RTC) {
 | 
				
			||||||
        Name(_HID, EisaId("PNP0B00"))
 | 
					        Name(_HID, EisaId("PNP0B00"))
 | 
				
			||||||
        Name(_CRS, ResourceTemplate() {
 | 
					        Name(_CRS, ResourceTemplate() {
 | 
				
			||||||
 | 
				
			|||||||
@ -30,20 +30,7 @@ Scope(\_SB.PCI0) {
 | 
				
			|||||||
            0x01,               // Address Alignment
 | 
					            0x01,               // Address Alignment
 | 
				
			||||||
            0x08,               // Address Length
 | 
					            0x08,               // Address Length
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
 | 
					        BOARD_SPECIFIC_PCI_RESOURSES
 | 
				
			||||||
            0x0000,             // Address Space Granularity
 | 
					 | 
				
			||||||
            0x0000,             // Address Range Minimum
 | 
					 | 
				
			||||||
            0x0CF7,             // Address Range Maximum
 | 
					 | 
				
			||||||
            0x0000,             // Address Translation Offset
 | 
					 | 
				
			||||||
            0x0CF8,             // Address Length
 | 
					 | 
				
			||||||
            ,, , TypeStatic)
 | 
					 | 
				
			||||||
        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
 | 
					 | 
				
			||||||
            0x0000,             // Address Space Granularity
 | 
					 | 
				
			||||||
            0x0D00,             // Address Range Minimum
 | 
					 | 
				
			||||||
            0xFFFF,             // Address Range Maximum
 | 
					 | 
				
			||||||
            0x0000,             // Address Translation Offset
 | 
					 | 
				
			||||||
            0xF300,             // Address Length
 | 
					 | 
				
			||||||
            ,, , TypeStatic)
 | 
					 | 
				
			||||||
        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
 | 
					        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
 | 
				
			||||||
            0x00000000,         // Address Space Granularity
 | 
					            0x00000000,         // Address Space Granularity
 | 
				
			||||||
            0x000A0000,         // Address Range Minimum
 | 
					            0x000A0000,         // Address Range Minimum
 | 
				
			||||||
 | 
				
			|||||||
@ -35,6 +35,45 @@ DefinitionBlock (
 | 
				
			|||||||
/****************************************************************
 | 
					/****************************************************************
 | 
				
			||||||
 * PCI Bus definition
 | 
					 * PCI Bus definition
 | 
				
			||||||
 ****************************************************************/
 | 
					 ****************************************************************/
 | 
				
			||||||
 | 
					#define BOARD_SPECIFIC_PCI_RESOURSES \
 | 
				
			||||||
 | 
					     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x0CF7, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x0CF8, \
 | 
				
			||||||
 | 
					         ,, , TypeStatic) \
 | 
				
			||||||
 | 
					     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x0D00, \
 | 
				
			||||||
 | 
					         0xADFF, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0xA100, \
 | 
				
			||||||
 | 
					         ,, , TypeStatic) \
 | 
				
			||||||
 | 
					     /* 0xae00-0xae0e hole for PCI hotplug, hw/acpi/piix4.c:PCI_HOTPLUG_ADDR */ \
 | 
				
			||||||
 | 
					     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0xAE0F, \
 | 
				
			||||||
 | 
					         0xAEFF, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x00F1, \
 | 
				
			||||||
 | 
					         ,, , TypeStatic) \
 | 
				
			||||||
 | 
					     /* 0xaf00-0xaf1f hole for CPU hotplug, hw/acpi/piix4.c:PIIX4_PROC_BASE */ \
 | 
				
			||||||
 | 
					     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0xAF20, \
 | 
				
			||||||
 | 
					         0xAFDF, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x00C0, \
 | 
				
			||||||
 | 
					         ,, , TypeStatic) \
 | 
				
			||||||
 | 
					     /* 0xafe0-0xafe3 hole for ACPI.GPE0, hw/acpi/piix4.c:GPE_BASE */ \
 | 
				
			||||||
 | 
					     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0xAFE4, \
 | 
				
			||||||
 | 
					         0xFFFF, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x501C, \
 | 
				
			||||||
 | 
					         ,, , TypeStatic)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Scope(\_SB) {
 | 
					    Scope(\_SB) {
 | 
				
			||||||
        Device(PCI0) {
 | 
					        Device(PCI0) {
 | 
				
			||||||
@ -114,6 +153,7 @@ DefinitionBlock (
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DSDT_APPLESMC_STA piix_dsdt_applesmc_sta
 | 
				
			||||||
#include "acpi-dsdt-isa.dsl"
 | 
					#include "acpi-dsdt-isa.dsl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -133,32 +173,28 @@ DefinitionBlock (
 | 
				
			|||||||
            B0EJ, 32,
 | 
					            B0EJ, 32,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OperationRegion(BNMR, SystemIO, 0xae10, 0x04)
 | 
				
			||||||
 | 
					        Field(BNMR, DWordAcc, NoLock, WriteAsZeros) {
 | 
				
			||||||
 | 
					            BNUM, 32,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Lock to protect access to fields above. */
 | 
				
			||||||
 | 
					        Mutex(BLCK, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Methods called by bulk generated PCI devices below */
 | 
					        /* Methods called by bulk generated PCI devices below */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Methods called by hotplug devices */
 | 
					        /* Methods called by hotplug devices */
 | 
				
			||||||
        Method(PCEJ, 1, NotSerialized) {
 | 
					        Method(PCEJ, 2, NotSerialized) {
 | 
				
			||||||
            // _EJ0 method - eject callback
 | 
					            // _EJ0 method - eject callback
 | 
				
			||||||
            Store(ShiftLeft(1, Arg0), B0EJ)
 | 
					            Acquire(BLCK, 0xFFFF)
 | 
				
			||||||
 | 
					            Store(Arg0, BNUM)
 | 
				
			||||||
 | 
					            Store(ShiftLeft(1, Arg1), B0EJ)
 | 
				
			||||||
 | 
					            Release(BLCK)
 | 
				
			||||||
            Return (0x0)
 | 
					            Return (0x0)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Hotplug notification method supplied by SSDT */
 | 
					        /* Hotplug notification method supplied by SSDT */
 | 
				
			||||||
        External(\_SB.PCI0.PCNT, MethodObj)
 | 
					        External(\_SB.PCI0.PCNT, MethodObj)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* PCI hotplug notify method */
 | 
					 | 
				
			||||||
        Method(PCNF, 0) {
 | 
					 | 
				
			||||||
            // Local0 = iterator
 | 
					 | 
				
			||||||
            Store(Zero, Local0)
 | 
					 | 
				
			||||||
            While (LLess(Local0, 31)) {
 | 
					 | 
				
			||||||
                Increment(Local0)
 | 
					 | 
				
			||||||
                If (And(PCIU, ShiftLeft(1, Local0))) {
 | 
					 | 
				
			||||||
                    PCNT(Local0, 1)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                If (And(PCID, ShiftLeft(1, Local0))) {
 | 
					 | 
				
			||||||
                    PCNT(Local0, 3)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -293,6 +329,8 @@ DefinitionBlock (
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "hw/acpi/cpu_hotplug_defs.h"
 | 
				
			||||||
 | 
					#define CPU_STATUS_BASE PIIX4_CPU_HOTPLUG_IO_BASE
 | 
				
			||||||
#include "acpi-dsdt-cpu-hotplug.dsl"
 | 
					#include "acpi-dsdt-cpu-hotplug.dsl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -307,7 +345,9 @@ DefinitionBlock (
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        Method(_E01) {
 | 
					        Method(_E01) {
 | 
				
			||||||
            // PCI hotplug event
 | 
					            // PCI hotplug event
 | 
				
			||||||
            \_SB.PCI0.PCNF()
 | 
					            Acquire(\_SB.PCI0.BLCK, 0xFFFF)
 | 
				
			||||||
 | 
					            \_SB.PCI0.PCNT()
 | 
				
			||||||
 | 
					            Release(\_SB.PCI0.BLCK)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Method(_E02) {
 | 
					        Method(_E02) {
 | 
				
			||||||
            // CPU hotplug event
 | 
					            // CPU hotplug event
 | 
				
			||||||
 | 
				
			|||||||
@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x53,
 | 
					0x53,
 | 
				
			||||||
0x44,
 | 
					0x44,
 | 
				
			||||||
0x54,
 | 
					0x54,
 | 
				
			||||||
0x37,
 | 
					0x87,
 | 
				
			||||||
0x11,
 | 
					0x11,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x1,
 | 
					0x1,
 | 
				
			||||||
0xd8,
 | 
					0xb8,
 | 
				
			||||||
0x42,
 | 
					0x42,
 | 
				
			||||||
0x58,
 | 
					0x58,
 | 
				
			||||||
0x50,
 | 
					0x50,
 | 
				
			||||||
@ -860,8 +860,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x4e,
 | 
					0x4e,
 | 
				
			||||||
0x1,
 | 
					0x1,
 | 
				
			||||||
0x10,
 | 
					0x10,
 | 
				
			||||||
0x4c,
 | 
					0x4b,
 | 
				
			||||||
0x1b,
 | 
					0x1e,
 | 
				
			||||||
0x2f,
 | 
					0x2f,
 | 
				
			||||||
0x3,
 | 
					0x3,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
@ -879,6 +879,53 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x5b,
 | 
					0x5b,
 | 
				
			||||||
0x82,
 | 
					0x82,
 | 
				
			||||||
0x2d,
 | 
					0x2d,
 | 
				
			||||||
 | 
					0x53,
 | 
				
			||||||
 | 
					0x4d,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x8,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x48,
 | 
				
			||||||
 | 
					0x49,
 | 
				
			||||||
 | 
					0x44,
 | 
				
			||||||
 | 
					0xc,
 | 
				
			||||||
 | 
					0x6,
 | 
				
			||||||
 | 
					0x10,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0x1,
 | 
				
			||||||
 | 
					0x8,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x53,
 | 
				
			||||||
 | 
					0x54,
 | 
				
			||||||
 | 
					0x41,
 | 
				
			||||||
 | 
					0xb,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0xff,
 | 
				
			||||||
 | 
					0x8,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x52,
 | 
				
			||||||
 | 
					0x53,
 | 
				
			||||||
 | 
					0x11,
 | 
				
			||||||
 | 
					0x10,
 | 
				
			||||||
 | 
					0xa,
 | 
				
			||||||
 | 
					0xd,
 | 
				
			||||||
 | 
					0x47,
 | 
				
			||||||
 | 
					0x1,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0x3,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0x3,
 | 
				
			||||||
 | 
					0x1,
 | 
				
			||||||
 | 
					0x20,
 | 
				
			||||||
 | 
					0x22,
 | 
				
			||||||
 | 
					0x40,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0x79,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0x5b,
 | 
				
			||||||
 | 
					0x82,
 | 
				
			||||||
 | 
					0x2d,
 | 
				
			||||||
0x52,
 | 
					0x52,
 | 
				
			||||||
0x54,
 | 
					0x54,
 | 
				
			||||||
0x43,
 | 
					0x43,
 | 
				
			||||||
@ -1305,7 +1352,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x79,
 | 
					0x79,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x10,
 | 
					0x10,
 | 
				
			||||||
0x4b,
 | 
					0x48,
 | 
				
			||||||
0x8,
 | 
					0x8,
 | 
				
			||||||
0x2e,
 | 
					0x2e,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
@ -1371,79 +1418,76 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x45,
 | 
					0x45,
 | 
				
			||||||
0x4a,
 | 
					0x4a,
 | 
				
			||||||
0x20,
 | 
					0x20,
 | 
				
			||||||
 | 
					0x5b,
 | 
				
			||||||
 | 
					0x80,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x4e,
 | 
				
			||||||
 | 
					0x4d,
 | 
				
			||||||
 | 
					0x52,
 | 
				
			||||||
 | 
					0x1,
 | 
				
			||||||
 | 
					0xb,
 | 
				
			||||||
 | 
					0x10,
 | 
				
			||||||
 | 
					0xae,
 | 
				
			||||||
 | 
					0xa,
 | 
				
			||||||
 | 
					0x4,
 | 
				
			||||||
 | 
					0x5b,
 | 
				
			||||||
 | 
					0x81,
 | 
				
			||||||
 | 
					0xb,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x4e,
 | 
				
			||||||
 | 
					0x4d,
 | 
				
			||||||
 | 
					0x52,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x4e,
 | 
				
			||||||
 | 
					0x55,
 | 
				
			||||||
 | 
					0x4d,
 | 
				
			||||||
 | 
					0x20,
 | 
				
			||||||
 | 
					0x5b,
 | 
				
			||||||
 | 
					0x1,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x4c,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x4b,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
0x14,
 | 
					0x14,
 | 
				
			||||||
0x11,
 | 
					0x25,
 | 
				
			||||||
0x50,
 | 
					0x50,
 | 
				
			||||||
0x43,
 | 
					0x43,
 | 
				
			||||||
0x45,
 | 
					0x45,
 | 
				
			||||||
0x4a,
 | 
					0x4a,
 | 
				
			||||||
0x1,
 | 
					0x2,
 | 
				
			||||||
 | 
					0x5b,
 | 
				
			||||||
 | 
					0x23,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x4c,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x4b,
 | 
				
			||||||
 | 
					0xff,
 | 
				
			||||||
 | 
					0xff,
 | 
				
			||||||
 | 
					0x70,
 | 
				
			||||||
 | 
					0x68,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x4e,
 | 
				
			||||||
 | 
					0x55,
 | 
				
			||||||
 | 
					0x4d,
 | 
				
			||||||
0x70,
 | 
					0x70,
 | 
				
			||||||
0x79,
 | 
					0x79,
 | 
				
			||||||
0x1,
 | 
					0x1,
 | 
				
			||||||
0x68,
 | 
					0x69,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x42,
 | 
					0x42,
 | 
				
			||||||
0x30,
 | 
					0x30,
 | 
				
			||||||
0x45,
 | 
					0x45,
 | 
				
			||||||
0x4a,
 | 
					0x4a,
 | 
				
			||||||
 | 
					0x5b,
 | 
				
			||||||
 | 
					0x27,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x4c,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x4b,
 | 
				
			||||||
0xa4,
 | 
					0xa4,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x14,
 | 
					 | 
				
			||||||
0x36,
 | 
					 | 
				
			||||||
0x50,
 | 
					 | 
				
			||||||
0x43,
 | 
					 | 
				
			||||||
0x4e,
 | 
					 | 
				
			||||||
0x46,
 | 
					 | 
				
			||||||
0x0,
 | 
					 | 
				
			||||||
0x70,
 | 
					 | 
				
			||||||
0x0,
 | 
					 | 
				
			||||||
0x60,
 | 
					 | 
				
			||||||
0xa2,
 | 
					 | 
				
			||||||
0x2c,
 | 
					 | 
				
			||||||
0x95,
 | 
					 | 
				
			||||||
0x60,
 | 
					 | 
				
			||||||
0xa,
 | 
					 | 
				
			||||||
0x1f,
 | 
					 | 
				
			||||||
0x75,
 | 
					 | 
				
			||||||
0x60,
 | 
					 | 
				
			||||||
0xa0,
 | 
					 | 
				
			||||||
0x11,
 | 
					 | 
				
			||||||
0x7b,
 | 
					 | 
				
			||||||
0x50,
 | 
					 | 
				
			||||||
0x43,
 | 
					 | 
				
			||||||
0x49,
 | 
					 | 
				
			||||||
0x55,
 | 
					 | 
				
			||||||
0x79,
 | 
					 | 
				
			||||||
0x1,
 | 
					 | 
				
			||||||
0x60,
 | 
					 | 
				
			||||||
0x0,
 | 
					 | 
				
			||||||
0x0,
 | 
					 | 
				
			||||||
0x50,
 | 
					 | 
				
			||||||
0x43,
 | 
					 | 
				
			||||||
0x4e,
 | 
					 | 
				
			||||||
0x54,
 | 
					 | 
				
			||||||
0x60,
 | 
					 | 
				
			||||||
0x1,
 | 
					 | 
				
			||||||
0xa0,
 | 
					 | 
				
			||||||
0x12,
 | 
					 | 
				
			||||||
0x7b,
 | 
					 | 
				
			||||||
0x50,
 | 
					 | 
				
			||||||
0x43,
 | 
					 | 
				
			||||||
0x49,
 | 
					 | 
				
			||||||
0x44,
 | 
					 | 
				
			||||||
0x79,
 | 
					 | 
				
			||||||
0x1,
 | 
					 | 
				
			||||||
0x60,
 | 
					 | 
				
			||||||
0x0,
 | 
					 | 
				
			||||||
0x0,
 | 
					 | 
				
			||||||
0x50,
 | 
					 | 
				
			||||||
0x43,
 | 
					 | 
				
			||||||
0x4e,
 | 
					 | 
				
			||||||
0x54,
 | 
					 | 
				
			||||||
0x60,
 | 
					 | 
				
			||||||
0xa,
 | 
					 | 
				
			||||||
0x3,
 | 
					 | 
				
			||||||
0x10,
 | 
					0x10,
 | 
				
			||||||
0x4a,
 | 
					0x4a,
 | 
				
			||||||
0xa0,
 | 
					0xa0,
 | 
				
			||||||
@ -4248,8 +4292,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x75,
 | 
					0x75,
 | 
				
			||||||
0x60,
 | 
					0x60,
 | 
				
			||||||
0x10,
 | 
					0x10,
 | 
				
			||||||
0x4e,
 | 
					0x42,
 | 
				
			||||||
0x9,
 | 
					0xc,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
0x47,
 | 
					0x47,
 | 
				
			||||||
0x50,
 | 
					0x50,
 | 
				
			||||||
@ -4277,12 +4321,31 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x30,
 | 
					0x30,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x14,
 | 
					0x14,
 | 
				
			||||||
0x15,
 | 
					0x39,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
0x45,
 | 
					0x45,
 | 
				
			||||||
0x30,
 | 
					0x30,
 | 
				
			||||||
0x31,
 | 
					0x31,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
 | 
					0x5b,
 | 
				
			||||||
 | 
					0x23,
 | 
				
			||||||
 | 
					0x5c,
 | 
				
			||||||
 | 
					0x2f,
 | 
				
			||||||
 | 
					0x3,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x53,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x50,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x49,
 | 
				
			||||||
 | 
					0x30,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x4c,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x4b,
 | 
				
			||||||
 | 
					0xff,
 | 
				
			||||||
 | 
					0xff,
 | 
				
			||||||
0x5c,
 | 
					0x5c,
 | 
				
			||||||
0x2f,
 | 
					0x2f,
 | 
				
			||||||
0x3,
 | 
					0x3,
 | 
				
			||||||
@ -4297,7 +4360,24 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x50,
 | 
					0x50,
 | 
				
			||||||
0x43,
 | 
					0x43,
 | 
				
			||||||
0x4e,
 | 
					0x4e,
 | 
				
			||||||
0x46,
 | 
					0x54,
 | 
				
			||||||
 | 
					0x5b,
 | 
				
			||||||
 | 
					0x27,
 | 
				
			||||||
 | 
					0x5c,
 | 
				
			||||||
 | 
					0x2f,
 | 
				
			||||||
 | 
					0x3,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x53,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x50,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x49,
 | 
				
			||||||
 | 
					0x30,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x4c,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x4b,
 | 
				
			||||||
0x14,
 | 
					0x14,
 | 
				
			||||||
0x10,
 | 
					0x10,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
@ -4407,3 +4487,6 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x46,
 | 
					0x46,
 | 
				
			||||||
0x0
 | 
					0x0
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					static unsigned short piix_dsdt_applesmc_sta[] = {
 | 
				
			||||||
 | 
					0x384
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1072,6 +1072,7 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
 | 
				
			|||||||
    PcGuestInfo *guest_info = &guest_info_state->info;
 | 
					    PcGuestInfo *guest_info = &guest_info_state->info;
 | 
				
			||||||
    int i, j;
 | 
					    int i, j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    guest_info->ram_size_below_4g = below_4g_mem_size;
 | 
				
			||||||
    guest_info->ram_size = below_4g_mem_size + above_4g_mem_size;
 | 
					    guest_info->ram_size = below_4g_mem_size + above_4g_mem_size;
 | 
				
			||||||
    guest_info->apic_id_limit = pc_apic_id_limit(max_cpus);
 | 
					    guest_info->apic_id_limit = pc_apic_id_limit(max_cpus);
 | 
				
			||||||
    guest_info->apic_xrupt_override = kvm_allows_irq0_override();
 | 
					    guest_info->apic_xrupt_override = kvm_allows_irq0_override();
 | 
				
			||||||
 | 
				
			|||||||
@ -51,6 +51,11 @@
 | 
				
			|||||||
static bool has_pci_info;
 | 
					static bool has_pci_info;
 | 
				
			||||||
static bool has_acpi_build = true;
 | 
					static bool has_acpi_build = true;
 | 
				
			||||||
static bool smbios_type1_defaults = true;
 | 
					static bool smbios_type1_defaults = true;
 | 
				
			||||||
 | 
					/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
 | 
				
			||||||
 | 
					 * host addresses aligned at 1Gbyte boundaries.  This way we can use 1GByte
 | 
				
			||||||
 | 
					 * pages in the host.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static bool gigabyte_align = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* PC hardware initialisation */
 | 
					/* PC hardware initialisation */
 | 
				
			||||||
static void pc_q35_init(QEMUMachineInitArgs *args)
 | 
					static void pc_q35_init(QEMUMachineInitArgs *args)
 | 
				
			||||||
@ -92,9 +97,19 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    kvmclock_create();
 | 
					    kvmclock_create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
 | 
				
			||||||
 | 
					     * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
 | 
				
			||||||
 | 
					     * also known as MMCFG).
 | 
				
			||||||
 | 
					     * If it doesn't, we need to split it in chunks below and above 4G.
 | 
				
			||||||
 | 
					     * In any case, try to make sure that guest addresses aligned at
 | 
				
			||||||
 | 
					     * 1G boundaries get mapped to host addresses aligned at 1G boundaries.
 | 
				
			||||||
 | 
					     * For old machine types, use whatever split we used historically to avoid
 | 
				
			||||||
 | 
					     * breaking migration.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    if (args->ram_size >= 0xb0000000) {
 | 
					    if (args->ram_size >= 0xb0000000) {
 | 
				
			||||||
        above_4g_mem_size = args->ram_size - 0xb0000000;
 | 
					        ram_addr_t lowmem = gigabyte_align ? 0x80000000 : 0xb0000000;
 | 
				
			||||||
        below_4g_mem_size = 0xb0000000;
 | 
					        above_4g_mem_size = args->ram_size - lowmem;
 | 
				
			||||||
 | 
					        below_4g_mem_size = lowmem;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        above_4g_mem_size = 0;
 | 
					        above_4g_mem_size = 0;
 | 
				
			||||||
        below_4g_mem_size = args->ram_size;
 | 
					        below_4g_mem_size = args->ram_size;
 | 
				
			||||||
@ -228,6 +243,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
 | 
				
			|||||||
static void pc_compat_1_7(QEMUMachineInitArgs *args)
 | 
					static void pc_compat_1_7(QEMUMachineInitArgs *args)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    smbios_type1_defaults = false;
 | 
					    smbios_type1_defaults = false;
 | 
				
			||||||
 | 
					    gigabyte_align = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pc_compat_1_6(QEMUMachineInitArgs *args)
 | 
					static void pc_compat_1_6(QEMUMachineInitArgs *args)
 | 
				
			||||||
 | 
				
			|||||||
@ -48,6 +48,22 @@ DefinitionBlock (
 | 
				
			|||||||
/****************************************************************
 | 
					/****************************************************************
 | 
				
			||||||
 * PCI Bus definition
 | 
					 * PCI Bus definition
 | 
				
			||||||
 ****************************************************************/
 | 
					 ****************************************************************/
 | 
				
			||||||
 | 
					#define BOARD_SPECIFIC_PCI_RESOURSES \
 | 
				
			||||||
 | 
					     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x0CD7, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x0CD8, \
 | 
				
			||||||
 | 
					         ,, , TypeStatic) \
 | 
				
			||||||
 | 
					     /* 0xcd8-0xcf7 hole for CPU hotplug, hw/acpi/ich9.c:ICH9_PROC_BASE */ \
 | 
				
			||||||
 | 
					     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0x0D00, \
 | 
				
			||||||
 | 
					         0xFFFF, \
 | 
				
			||||||
 | 
					         0x0000, \
 | 
				
			||||||
 | 
					         0xF300, \
 | 
				
			||||||
 | 
					         ,, , TypeStatic)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Scope(\_SB) {
 | 
					    Scope(\_SB) {
 | 
				
			||||||
        Device(PCI0) {
 | 
					        Device(PCI0) {
 | 
				
			||||||
@ -171,6 +187,7 @@ DefinitionBlock (
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DSDT_APPLESMC_STA q35_dsdt_applesmc_sta
 | 
				
			||||||
#include "acpi-dsdt-isa.dsl"
 | 
					#include "acpi-dsdt-isa.dsl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -404,6 +421,8 @@ DefinitionBlock (
 | 
				
			|||||||
        define_gsi_link(GSIH, 0, 0x17)
 | 
					        define_gsi_link(GSIH, 0, 0x17)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "hw/acpi/cpu_hotplug_defs.h"
 | 
				
			||||||
 | 
					#define CPU_STATUS_BASE ICH9_CPU_HOTPLUG_IO_BASE
 | 
				
			||||||
#include "acpi-dsdt-cpu-hotplug.dsl"
 | 
					#include "acpi-dsdt-cpu-hotplug.dsl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x53,
 | 
					0x53,
 | 
				
			||||||
0x44,
 | 
					0x44,
 | 
				
			||||||
0x54,
 | 
					0x54,
 | 
				
			||||||
0xb0,
 | 
					0xdf,
 | 
				
			||||||
0x1c,
 | 
					0x1c,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x1,
 | 
					0x1,
 | 
				
			||||||
0xfe,
 | 
					0xff,
 | 
				
			||||||
0x42,
 | 
					0x42,
 | 
				
			||||||
0x58,
 | 
					0x58,
 | 
				
			||||||
0x50,
 | 
					0x50,
 | 
				
			||||||
@ -1033,8 +1033,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x4e,
 | 
					0x4e,
 | 
				
			||||||
0x1,
 | 
					0x1,
 | 
				
			||||||
0x10,
 | 
					0x10,
 | 
				
			||||||
0x4c,
 | 
					0x4b,
 | 
				
			||||||
0x1b,
 | 
					0x1e,
 | 
				
			||||||
0x2f,
 | 
					0x2f,
 | 
				
			||||||
0x3,
 | 
					0x3,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
@ -1052,6 +1052,53 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x5b,
 | 
					0x5b,
 | 
				
			||||||
0x82,
 | 
					0x82,
 | 
				
			||||||
0x2d,
 | 
					0x2d,
 | 
				
			||||||
 | 
					0x53,
 | 
				
			||||||
 | 
					0x4d,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x8,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x48,
 | 
				
			||||||
 | 
					0x49,
 | 
				
			||||||
 | 
					0x44,
 | 
				
			||||||
 | 
					0xc,
 | 
				
			||||||
 | 
					0x6,
 | 
				
			||||||
 | 
					0x10,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0x1,
 | 
				
			||||||
 | 
					0x8,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x53,
 | 
				
			||||||
 | 
					0x54,
 | 
				
			||||||
 | 
					0x41,
 | 
				
			||||||
 | 
					0xb,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0xff,
 | 
				
			||||||
 | 
					0x8,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x43,
 | 
				
			||||||
 | 
					0x52,
 | 
				
			||||||
 | 
					0x53,
 | 
				
			||||||
 | 
					0x11,
 | 
				
			||||||
 | 
					0x10,
 | 
				
			||||||
 | 
					0xa,
 | 
				
			||||||
 | 
					0xd,
 | 
				
			||||||
 | 
					0x47,
 | 
				
			||||||
 | 
					0x1,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0x3,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0x3,
 | 
				
			||||||
 | 
					0x1,
 | 
				
			||||||
 | 
					0x20,
 | 
				
			||||||
 | 
					0x22,
 | 
				
			||||||
 | 
					0x40,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0x79,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
 | 
					0x5b,
 | 
				
			||||||
 | 
					0x82,
 | 
				
			||||||
 | 
					0x2d,
 | 
				
			||||||
0x52,
 | 
					0x52,
 | 
				
			||||||
0x54,
 | 
					0x54,
 | 
				
			||||||
0x43,
 | 
					0x43,
 | 
				
			||||||
@ -7229,12 +7276,19 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x30,
 | 
					0x30,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x14,
 | 
					0x14,
 | 
				
			||||||
0x10,
 | 
					0x6,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
0x4c,
 | 
					0x4c,
 | 
				
			||||||
0x30,
 | 
					0x30,
 | 
				
			||||||
0x31,
 | 
					0x31,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
 | 
					0x14,
 | 
				
			||||||
 | 
					0x10,
 | 
				
			||||||
 | 
					0x5f,
 | 
				
			||||||
 | 
					0x45,
 | 
				
			||||||
 | 
					0x30,
 | 
				
			||||||
 | 
					0x32,
 | 
				
			||||||
 | 
					0x0,
 | 
				
			||||||
0x5c,
 | 
					0x5c,
 | 
				
			||||||
0x2e,
 | 
					0x2e,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
@ -7250,13 +7304,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
0x4c,
 | 
					0x4c,
 | 
				
			||||||
0x30,
 | 
					0x30,
 | 
				
			||||||
0x32,
 | 
					 | 
				
			||||||
0x0,
 | 
					 | 
				
			||||||
0x14,
 | 
					 | 
				
			||||||
0x6,
 | 
					 | 
				
			||||||
0x5f,
 | 
					 | 
				
			||||||
0x4c,
 | 
					 | 
				
			||||||
0x30,
 | 
					 | 
				
			||||||
0x33,
 | 
					0x33,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x14,
 | 
					0x14,
 | 
				
			||||||
@ -7344,3 +7391,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
				
			|||||||
0x46,
 | 
					0x46,
 | 
				
			||||||
0x0
 | 
					0x0
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					static unsigned short q35_dsdt_applesmc_sta[] = {
 | 
				
			||||||
 | 
					0x431
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -25,6 +25,7 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
 | 
				
			|||||||
    /* Objects supplied by DSDT */
 | 
					    /* Objects supplied by DSDT */
 | 
				
			||||||
    External(\_SB.PCI0, DeviceObj)
 | 
					    External(\_SB.PCI0, DeviceObj)
 | 
				
			||||||
    External(\_SB.PCI0.PCEJ, MethodObj)
 | 
					    External(\_SB.PCI0.PCEJ, MethodObj)
 | 
				
			||||||
 | 
					    External(BSEL, IntObj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Scope(\_SB.PCI0) {
 | 
					    Scope(\_SB.PCI0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -33,19 +34,17 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
 | 
				
			|||||||
        ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
 | 
					        ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
 | 
				
			||||||
        ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
 | 
					        ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Method _EJ0 can be patched by BIOS to EJ0_
 | 
					        // Extract the offsets of the device name, address dword and the slot
 | 
				
			||||||
        // at runtime, if the slot is detected to not support hotplug.
 | 
					        // name byte - we fill them in for each device.
 | 
				
			||||||
        // Extract the offset of the address dword and the
 | 
					 | 
				
			||||||
        // _EJ0 name to allow this patching.
 | 
					 | 
				
			||||||
        Device(SAA) {
 | 
					        Device(SAA) {
 | 
				
			||||||
            ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
 | 
					            ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
 | 
				
			||||||
            Name(_SUN, 0xAA)
 | 
					            Name(_SUN, 0xAA)
 | 
				
			||||||
            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
 | 
					            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
 | 
				
			||||||
            Name(_ADR, 0xAA0000)
 | 
					            Name(_ADR, 0xAA0000)
 | 
				
			||||||
            ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0
 | 
					 | 
				
			||||||
            Method(_EJ0, 1) {
 | 
					            Method(_EJ0, 1) {
 | 
				
			||||||
                Return (PCEJ(_SUN))
 | 
					                PCEJ(BSEL, _SUN)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -5,19 +5,19 @@ static unsigned char ssdt_pcihp_adr[] = {
 | 
				
			|||||||
0x44
 | 
					0x44
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
static unsigned char ssdt_pcihp_end[] = {
 | 
					static unsigned char ssdt_pcihp_end[] = {
 | 
				
			||||||
0x58
 | 
					0x5b
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
static unsigned char ssdp_pcihp_aml[] = {
 | 
					static unsigned char ssdp_pcihp_aml[] = {
 | 
				
			||||||
0x53,
 | 
					0x53,
 | 
				
			||||||
0x53,
 | 
					0x53,
 | 
				
			||||||
0x44,
 | 
					0x44,
 | 
				
			||||||
0x54,
 | 
					0x54,
 | 
				
			||||||
0x58,
 | 
					0x5b,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x1,
 | 
					0x1,
 | 
				
			||||||
0x76,
 | 
					0xe8,
 | 
				
			||||||
0x42,
 | 
					0x42,
 | 
				
			||||||
0x58,
 | 
					0x58,
 | 
				
			||||||
0x50,
 | 
					0x50,
 | 
				
			||||||
@ -45,7 +45,7 @@ static unsigned char ssdp_pcihp_aml[] = {
 | 
				
			|||||||
0x13,
 | 
					0x13,
 | 
				
			||||||
0x20,
 | 
					0x20,
 | 
				
			||||||
0x10,
 | 
					0x10,
 | 
				
			||||||
0x33,
 | 
					0x36,
 | 
				
			||||||
0x5c,
 | 
					0x5c,
 | 
				
			||||||
0x2e,
 | 
					0x2e,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
@ -58,7 +58,7 @@ static unsigned char ssdp_pcihp_aml[] = {
 | 
				
			|||||||
0x30,
 | 
					0x30,
 | 
				
			||||||
0x5b,
 | 
					0x5b,
 | 
				
			||||||
0x82,
 | 
					0x82,
 | 
				
			||||||
0x26,
 | 
					0x29,
 | 
				
			||||||
0x53,
 | 
					0x53,
 | 
				
			||||||
0x41,
 | 
					0x41,
 | 
				
			||||||
0x41,
 | 
					0x41,
 | 
				
			||||||
@ -81,17 +81,20 @@ static unsigned char ssdp_pcihp_aml[] = {
 | 
				
			|||||||
0xaa,
 | 
					0xaa,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x14,
 | 
					0x14,
 | 
				
			||||||
0xf,
 | 
					0x12,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
0x45,
 | 
					0x45,
 | 
				
			||||||
0x4a,
 | 
					0x4a,
 | 
				
			||||||
0x30,
 | 
					0x30,
 | 
				
			||||||
0x1,
 | 
					0x1,
 | 
				
			||||||
0xa4,
 | 
					 | 
				
			||||||
0x50,
 | 
					0x50,
 | 
				
			||||||
0x43,
 | 
					0x43,
 | 
				
			||||||
0x45,
 | 
					0x45,
 | 
				
			||||||
0x4a,
 | 
					0x4a,
 | 
				
			||||||
 | 
					0x42,
 | 
				
			||||||
 | 
					0x53,
 | 
				
			||||||
 | 
					0x45,
 | 
				
			||||||
 | 
					0x4c,
 | 
				
			||||||
0x5f,
 | 
					0x5f,
 | 
				
			||||||
0x53,
 | 
					0x53,
 | 
				
			||||||
0x55,
 | 
					0x55,
 | 
				
			||||||
@ -103,6 +106,3 @@ static unsigned char ssdt_pcihp_start[] = {
 | 
				
			|||||||
static unsigned char ssdt_pcihp_id[] = {
 | 
					static unsigned char ssdt_pcihp_id[] = {
 | 
				
			||||||
0x3d
 | 
					0x3d
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
static unsigned char ssdt_pcihp_ej0[] = {
 | 
					 | 
				
			||||||
0x4a
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ static unsigned char ssdp_proc_aml[] = {
 | 
				
			|||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x1,
 | 
					0x1,
 | 
				
			||||||
0xb8,
 | 
					0x78,
 | 
				
			||||||
0x42,
 | 
					0x42,
 | 
				
			||||||
0x58,
 | 
					0x58,
 | 
				
			||||||
0x50,
 | 
					0x50,
 | 
				
			||||||
@ -47,8 +47,8 @@ static unsigned char ssdp_proc_aml[] = {
 | 
				
			|||||||
0x41,
 | 
					0x41,
 | 
				
			||||||
0x41,
 | 
					0x41,
 | 
				
			||||||
0xaa,
 | 
					0xaa,
 | 
				
			||||||
0x10,
 | 
					0x0,
 | 
				
			||||||
0xb0,
 | 
					0x0,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
0x0,
 | 
					0x0,
 | 
				
			||||||
 | 
				
			|||||||
@ -66,7 +66,6 @@ struct AppleSMCData {
 | 
				
			|||||||
    QLIST_ENTRY(AppleSMCData) node;
 | 
					    QLIST_ENTRY(AppleSMCData) node;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TYPE_APPLE_SMC "isa-applesmc"
 | 
					 | 
				
			||||||
#define APPLE_SMC(obj) OBJECT_CHECK(AppleSMCState, (obj), TYPE_APPLE_SMC)
 | 
					#define APPLE_SMC(obj) OBJECT_CHECK(AppleSMCState, (obj), TYPE_APPLE_SMC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct AppleSMCState AppleSMCState;
 | 
					typedef struct AppleSMCState AppleSMCState;
 | 
				
			||||||
 | 
				
			|||||||
@ -321,7 +321,7 @@ void vhost_net_ack_features(struct vhost_net *net, unsigned features)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
 | 
					bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return -ENOSYS;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
 | 
					void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										48
									
								
								hw/pci/pci.c
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								hw/pci/pci.c
									
									
									
									
									
								
							@ -793,6 +793,15 @@ static void pci_config_free(PCIDevice *pci_dev)
 | 
				
			|||||||
    g_free(pci_dev->used);
 | 
					    g_free(pci_dev->used);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void do_pci_unregister_device(PCIDevice *pci_dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    pci_dev->bus->devices[pci_dev->devfn] = NULL;
 | 
				
			||||||
 | 
					    pci_config_free(pci_dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    address_space_destroy(&pci_dev->bus_master_as);
 | 
				
			||||||
 | 
					    memory_region_destroy(&pci_dev->bus_master_enable_region);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* -1 for devfn means auto assign */
 | 
					/* -1 for devfn means auto assign */
 | 
				
			||||||
static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
 | 
					static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
 | 
				
			||||||
                                         const char *name, int devfn)
 | 
					                                         const char *name, int devfn)
 | 
				
			||||||
@ -858,7 +867,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
 | 
				
			|||||||
        pci_init_mask_bridge(pci_dev);
 | 
					        pci_init_mask_bridge(pci_dev);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (pci_init_multifunction(bus, pci_dev)) {
 | 
					    if (pci_init_multifunction(bus, pci_dev)) {
 | 
				
			||||||
        pci_config_free(pci_dev);
 | 
					        do_pci_unregister_device(pci_dev);
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -873,15 +882,6 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
 | 
				
			|||||||
    return pci_dev;
 | 
					    return pci_dev;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void do_pci_unregister_device(PCIDevice *pci_dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    pci_dev->bus->devices[pci_dev->devfn] = NULL;
 | 
					 | 
				
			||||||
    pci_config_free(pci_dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    address_space_destroy(&pci_dev->bus_master_as);
 | 
					 | 
				
			||||||
    memory_region_destroy(&pci_dev->bus_master_enable_region);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void pci_unregister_io_regions(PCIDevice *pci_dev)
 | 
					static void pci_unregister_io_regions(PCIDevice *pci_dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PCIIORegion *r;
 | 
					    PCIIORegion *r;
 | 
				
			||||||
@ -1704,6 +1704,34 @@ static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num)
 | 
				
			|||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void pci_for_each_bus_depth_first(PCIBus *bus,
 | 
				
			||||||
 | 
					                                  void *(*begin)(PCIBus *bus, void *parent_state),
 | 
				
			||||||
 | 
					                                  void (*end)(PCIBus *bus, void *state),
 | 
				
			||||||
 | 
					                                  void *parent_state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PCIBus *sec;
 | 
				
			||||||
 | 
					    void *state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!bus) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (begin) {
 | 
				
			||||||
 | 
					        state = begin(bus, parent_state);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        state = parent_state;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QLIST_FOREACH(sec, &bus->child, sibling) {
 | 
				
			||||||
 | 
					        pci_for_each_bus_depth_first(sec, begin, end, state);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (end) {
 | 
				
			||||||
 | 
					        end(bus, state);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
 | 
					PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bus = pci_find_bus_nr(bus, bus_num);
 | 
					    bus = pci_find_bus_nr(bus, bus_num);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										27
									
								
								include/hw/acpi/cpu_hotplug.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								include/hw/acpi/cpu_hotplug.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * QEMU ACPI hotplug utilities
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 Red Hat Inc
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Authors:
 | 
				
			||||||
 | 
					 *   Igor Mammedov <imammedo@redhat.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
				
			||||||
 | 
					 * See the COPYING file in the top-level directory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef ACPI_HOTPLUG_H
 | 
				
			||||||
 | 
					#define ACPI_HOTPLUG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "hw/acpi/acpi.h"
 | 
				
			||||||
 | 
					#include "hw/acpi/cpu_hotplug_defs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct AcpiCpuHotplug {
 | 
				
			||||||
 | 
					    MemoryRegion io;
 | 
				
			||||||
 | 
					    uint8_t sts[ACPI_GPE_PROC_LEN];
 | 
				
			||||||
 | 
					} AcpiCpuHotplug;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AcpiCpuHotplug_add(ACPIGPE *gpe, AcpiCpuHotplug *g, CPUState *cpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AcpiCpuHotplug_init(MemoryRegion *parent, Object *owner,
 | 
				
			||||||
 | 
					                         AcpiCpuHotplug *gpe_cpu, uint16_t base);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										24
									
								
								include/hw/acpi/cpu_hotplug_defs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								include/hw/acpi/cpu_hotplug_defs.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * QEMU ACPI hotplug utilities shared defines
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 Red Hat Inc
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Authors:
 | 
				
			||||||
 | 
					 *   Igor Mammedov <imammedo@redhat.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
				
			||||||
 | 
					 * See the COPYING file in the top-level directory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef ACPI_HOTPLUG_DEFS_H
 | 
				
			||||||
 | 
					#define ACPI_HOTPLUG_DEFS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * ONLY DEFINEs are permited in this file since it's shared
 | 
				
			||||||
 | 
					 * between C and ASL code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define ACPI_CPU_HOTPLUG_STATUS 4
 | 
				
			||||||
 | 
					#define ACPI_GPE_PROC_LEN 32
 | 
				
			||||||
 | 
					#define ICH9_CPU_HOTPLUG_IO_BASE 0x0CD8
 | 
				
			||||||
 | 
					#define PIIX4_CPU_HOTPLUG_IO_BASE 0xaf00
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@ -22,6 +22,7 @@
 | 
				
			|||||||
#define HW_ACPI_ICH9_H
 | 
					#define HW_ACPI_ICH9_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "hw/acpi/acpi.h"
 | 
					#include "hw/acpi/acpi.h"
 | 
				
			||||||
 | 
					#include "hw/acpi/cpu_hotplug.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct ICH9LPCPMRegs {
 | 
					typedef struct ICH9LPCPMRegs {
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
@ -42,6 +43,9 @@ typedef struct ICH9LPCPMRegs {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    uint32_t pm_io_base;
 | 
					    uint32_t pm_io_base;
 | 
				
			||||||
    Notifier powerdown_notifier;
 | 
					    Notifier powerdown_notifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AcpiCpuHotplug gpe_cpu;
 | 
				
			||||||
 | 
					    Notifier cpu_added_notifier;
 | 
				
			||||||
} ICH9LPCPMRegs;
 | 
					} ICH9LPCPMRegs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
 | 
					void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										72
									
								
								include/hw/acpi/pcihp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								include/hw/acpi/pcihp.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * QEMU<->ACPI BIOS PCI hotplug interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * QEMU supports PCI hotplug via ACPI. This module
 | 
				
			||||||
 | 
					 * implements the interface between QEMU and the ACPI BIOS.
 | 
				
			||||||
 | 
					 * Interface specification - see docs/specs/acpi_pci_hotplug.txt
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2013, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
 | 
				
			||||||
 | 
					 * Copyright (c) 2006 Fabrice Bellard
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU Lesser General Public
 | 
				
			||||||
 | 
					 * License version 2 as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
				
			||||||
 | 
					 * Lesser General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Lesser General Public
 | 
				
			||||||
 | 
					 * License along with this library; if not, see <http://www.gnu.org/licenses/>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Contributions after 2012-01-13 are licensed under the terms of the
 | 
				
			||||||
 | 
					 * GNU GPL, version 2 or (at your option) any later version.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef HW_ACPI_PCIHP_H
 | 
				
			||||||
 | 
					#define HW_ACPI_PCIHP_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					#include <qemu/typedefs.h>
 | 
				
			||||||
 | 
					#include "hw/pci/pci.h" /* for PCIHotplugState */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct AcpiPciHpPciStatus {
 | 
				
			||||||
 | 
					    uint32_t up; /* deprecated, maintained for migration compatibility */
 | 
				
			||||||
 | 
					    uint32_t down;
 | 
				
			||||||
 | 
					    uint32_t hotplug_enable;
 | 
				
			||||||
 | 
					    uint32_t device_present;
 | 
				
			||||||
 | 
					} AcpiPciHpPciStatus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ACPI_PCIHP_PROP_BSEL "acpi-pcihp-bsel"
 | 
				
			||||||
 | 
					#define ACPI_PCIHP_MAX_HOTPLUG_BUS 256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct AcpiPciHpState {
 | 
				
			||||||
 | 
					    AcpiPciHpPciStatus acpi_pcihp_pci_status[ACPI_PCIHP_MAX_HOTPLUG_BUS];
 | 
				
			||||||
 | 
					    uint32_t hotplug_select;
 | 
				
			||||||
 | 
					    PCIBus *root;
 | 
				
			||||||
 | 
					    MemoryRegion io;
 | 
				
			||||||
 | 
					} AcpiPciHpState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void acpi_pcihp_init(AcpiPciHpState *, PCIBus *root,
 | 
				
			||||||
 | 
					                     MemoryRegion *address_space_io);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Invoke on device hotplug */
 | 
				
			||||||
 | 
					int acpi_pcihp_device_hotplug(AcpiPciHpState *, PCIDevice *,
 | 
				
			||||||
 | 
					                              PCIHotplugState state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Called on reset */
 | 
				
			||||||
 | 
					void acpi_pcihp_reset(AcpiPciHpState *s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const VMStateDescription vmstate_acpi_pcihp_pci_status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp) \
 | 
				
			||||||
 | 
					        VMSTATE_UINT32_TEST(pcihp.hotplug_select, state, \
 | 
				
			||||||
 | 
					                            test_pcihp), \
 | 
				
			||||||
 | 
					        VMSTATE_STRUCT_ARRAY_TEST(pcihp.acpi_pcihp_pci_status, state, \
 | 
				
			||||||
 | 
					                                  ACPI_PCIHP_MAX_HOTPLUG_BUS, \
 | 
				
			||||||
 | 
					                                  test_pcihp, 1, \
 | 
				
			||||||
 | 
					                                  vmstate_acpi_pcihp_pci_status, \
 | 
				
			||||||
 | 
					                                  AcpiPciHpPciStatus)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@ -35,7 +35,7 @@ typedef struct PcPciInfo {
 | 
				
			|||||||
struct PcGuestInfo {
 | 
					struct PcGuestInfo {
 | 
				
			||||||
    bool has_pci_info;
 | 
					    bool has_pci_info;
 | 
				
			||||||
    bool isapc_ram_fw;
 | 
					    bool isapc_ram_fw;
 | 
				
			||||||
    hwaddr ram_size;
 | 
					    hwaddr ram_size, ram_size_below_4g;
 | 
				
			||||||
    unsigned apic_id_limit;
 | 
					    unsigned apic_id_limit;
 | 
				
			||||||
    bool apic_xrupt_override;
 | 
					    bool apic_xrupt_override;
 | 
				
			||||||
    uint64_t numa_nodes;
 | 
					    uint64_t numa_nodes;
 | 
				
			||||||
@ -265,6 +265,11 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
 | 
				
			|||||||
            .driver   = TYPE_USB_DEVICE,\
 | 
					            .driver   = TYPE_USB_DEVICE,\
 | 
				
			||||||
            .property = "msos-desc",\
 | 
					            .property = "msos-desc",\
 | 
				
			||||||
            .value    = "no",\
 | 
					            .value    = "no",\
 | 
				
			||||||
 | 
					        },\
 | 
				
			||||||
 | 
					        {\
 | 
				
			||||||
 | 
					            .driver   = "PIIX4_PM",\
 | 
				
			||||||
 | 
					            .property = "acpi-pci-hotplug-with-bridge-support",\
 | 
				
			||||||
 | 
					            .value    = "off",\
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PC_COMPAT_1_6 \
 | 
					#define PC_COMPAT_1_6 \
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,13 @@
 | 
				
			|||||||
#define TYPE_ISA_BUS "ISA"
 | 
					#define TYPE_ISA_BUS "ISA"
 | 
				
			||||||
#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS)
 | 
					#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TYPE_APPLE_SMC "isa-applesmc"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool applesmc_find(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return object_resolve_path_type("", TYPE_APPLE_SMC, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct ISADeviceClass {
 | 
					typedef struct ISADeviceClass {
 | 
				
			||||||
    DeviceClass parent_class;
 | 
					    DeviceClass parent_class;
 | 
				
			||||||
} ISADeviceClass;
 | 
					} ISADeviceClass;
 | 
				
			||||||
 | 
				
			|||||||
@ -387,6 +387,20 @@ int pci_bus_num(PCIBus *s);
 | 
				
			|||||||
void pci_for_each_device(PCIBus *bus, int bus_num,
 | 
					void pci_for_each_device(PCIBus *bus, int bus_num,
 | 
				
			||||||
                         void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque),
 | 
					                         void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque),
 | 
				
			||||||
                         void *opaque);
 | 
					                         void *opaque);
 | 
				
			||||||
 | 
					void pci_for_each_bus_depth_first(PCIBus *bus,
 | 
				
			||||||
 | 
					                                  void *(*begin)(PCIBus *bus, void *parent_state),
 | 
				
			||||||
 | 
					                                  void (*end)(PCIBus *bus, void *state),
 | 
				
			||||||
 | 
					                                  void *parent_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Use this wrapper when specific scan order is not required. */
 | 
				
			||||||
 | 
					static inline
 | 
				
			||||||
 | 
					void pci_for_each_bus(PCIBus *bus,
 | 
				
			||||||
 | 
					                      void (*fn)(PCIBus *bus, void *opaque),
 | 
				
			||||||
 | 
					                      void *opaque)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    pci_for_each_bus_depth_first(bus, NULL, fn, opaque);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PCIBus *pci_find_primary_bus(void);
 | 
					PCIBus *pci_find_primary_bus(void);
 | 
				
			||||||
PCIBus *pci_device_root_bus(const PCIDevice *d);
 | 
					PCIBus *pci_device_root_bus(const PCIDevice *d);
 | 
				
			||||||
const char *pci_root_bus_path(PCIDevice *dev);
 | 
					const char *pci_root_bus_path(PCIDevice *dev);
 | 
				
			||||||
 | 
				
			|||||||
@ -26,6 +26,10 @@ case $line in
 | 
				
			|||||||
    # save for the next definitions
 | 
					    # save for the next definitions
 | 
				
			||||||
    prefix=${line#*=}
 | 
					    prefix=${line#*=}
 | 
				
			||||||
    ;;
 | 
					    ;;
 | 
				
			||||||
 | 
					 IASL=*) # iasl executable
 | 
				
			||||||
 | 
					    value=${line#*=}
 | 
				
			||||||
 | 
					    echo "#define CONFIG_IASL $value"
 | 
				
			||||||
 | 
					    ;;
 | 
				
			||||||
 CONFIG_AUDIO_DRIVERS=*)
 | 
					 CONFIG_AUDIO_DRIVERS=*)
 | 
				
			||||||
    drivers=${line#*=}
 | 
					    drivers=${line#*=}
 | 
				
			||||||
    echo "#define CONFIG_AUDIO_DRIVERS \\"
 | 
					    echo "#define CONFIG_AUDIO_DRIVERS \\"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										339
									
								
								scripts/dump-guest-memory.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								scripts/dump-guest-memory.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,339 @@
 | 
				
			|||||||
 | 
					# This python script adds a new gdb command, "dump-guest-memory". It
 | 
				
			||||||
 | 
					# should be loaded with "source dump-guest-memory.py" at the (gdb)
 | 
				
			||||||
 | 
					# prompt.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (C) 2013, Red Hat, Inc.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Authors:
 | 
				
			||||||
 | 
					#   Laszlo Ersek <lersek@redhat.com>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This work is licensed under the terms of the GNU GPL, version 2 or later. See
 | 
				
			||||||
 | 
					# the COPYING file in the top-level directory.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The leading docstring doesn't have idiomatic Python formatting. It is
 | 
				
			||||||
 | 
					# printed by gdb's "help" command (the first line is printed in the
 | 
				
			||||||
 | 
					# "help data" summary), and it should match how other help texts look in
 | 
				
			||||||
 | 
					# gdb.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import struct
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DumpGuestMemory(gdb.Command):
 | 
				
			||||||
 | 
					    """Extract guest vmcore from qemu process coredump.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The sole argument is FILE, identifying the target file to write the
 | 
				
			||||||
 | 
					guest vmcore to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This GDB command reimplements the dump-guest-memory QMP command in
 | 
				
			||||||
 | 
					python, using the representation of guest memory as captured in the qemu
 | 
				
			||||||
 | 
					coredump. The qemu process that has been dumped must have had the
 | 
				
			||||||
 | 
					command line option "-machine dump-guest-core=on".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For simplicity, the "paging", "begin" and "end" parameters of the QMP
 | 
				
			||||||
 | 
					command are not supported -- no attempt is made to get the guest's
 | 
				
			||||||
 | 
					internal paging structures (ie. paging=false is hard-wired), and guest
 | 
				
			||||||
 | 
					memory is always fully dumped.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Only x86_64 guests are supported.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The CORE/NT_PRSTATUS and QEMU notes (that is, the VCPUs' statuses) are
 | 
				
			||||||
 | 
					not written to the vmcore. Preparing these would require context that is
 | 
				
			||||||
 | 
					only present in the KVM host kernel module when the guest is alive. A
 | 
				
			||||||
 | 
					fake ELF note is written instead, only to keep the ELF parser of "crash"
 | 
				
			||||||
 | 
					happy.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dependent on how busted the qemu process was at the time of the
 | 
				
			||||||
 | 
					coredump, this command might produce unpredictable results. If qemu
 | 
				
			||||||
 | 
					deliberately called abort(), or it was dumped in response to a signal at
 | 
				
			||||||
 | 
					a halfway fortunate point, then its coredump should be in reasonable
 | 
				
			||||||
 | 
					shape and this command should mostly work."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TARGET_PAGE_SIZE = 0x1000
 | 
				
			||||||
 | 
					    TARGET_PAGE_MASK = 0xFFFFFFFFFFFFF000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Various ELF constants
 | 
				
			||||||
 | 
					    EM_X86_64   = 62        # AMD x86-64 target machine
 | 
				
			||||||
 | 
					    ELFDATA2LSB = 1         # little endian
 | 
				
			||||||
 | 
					    ELFCLASS64  = 2
 | 
				
			||||||
 | 
					    ELFMAG      = "\x7FELF"
 | 
				
			||||||
 | 
					    EV_CURRENT  = 1
 | 
				
			||||||
 | 
					    ET_CORE     = 4
 | 
				
			||||||
 | 
					    PT_LOAD     = 1
 | 
				
			||||||
 | 
					    PT_NOTE     = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Special value for e_phnum. This indicates that the real number of
 | 
				
			||||||
 | 
					    # program headers is too large to fit into e_phnum. Instead the real
 | 
				
			||||||
 | 
					    # value is in the field sh_info of section 0.
 | 
				
			||||||
 | 
					    PN_XNUM = 0xFFFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Format strings for packing and header size calculation.
 | 
				
			||||||
 | 
					    ELF64_EHDR = ("4s" # e_ident/magic
 | 
				
			||||||
 | 
					                  "B"  # e_ident/class
 | 
				
			||||||
 | 
					                  "B"  # e_ident/data
 | 
				
			||||||
 | 
					                  "B"  # e_ident/version
 | 
				
			||||||
 | 
					                  "B"  # e_ident/osabi
 | 
				
			||||||
 | 
					                  "8s" # e_ident/pad
 | 
				
			||||||
 | 
					                  "H"  # e_type
 | 
				
			||||||
 | 
					                  "H"  # e_machine
 | 
				
			||||||
 | 
					                  "I"  # e_version
 | 
				
			||||||
 | 
					                  "Q"  # e_entry
 | 
				
			||||||
 | 
					                  "Q"  # e_phoff
 | 
				
			||||||
 | 
					                  "Q"  # e_shoff
 | 
				
			||||||
 | 
					                  "I"  # e_flags
 | 
				
			||||||
 | 
					                  "H"  # e_ehsize
 | 
				
			||||||
 | 
					                  "H"  # e_phentsize
 | 
				
			||||||
 | 
					                  "H"  # e_phnum
 | 
				
			||||||
 | 
					                  "H"  # e_shentsize
 | 
				
			||||||
 | 
					                  "H"  # e_shnum
 | 
				
			||||||
 | 
					                  "H"  # e_shstrndx
 | 
				
			||||||
 | 
					                 )
 | 
				
			||||||
 | 
					    ELF64_PHDR = ("I"  # p_type
 | 
				
			||||||
 | 
					                  "I"  # p_flags
 | 
				
			||||||
 | 
					                  "Q"  # p_offset
 | 
				
			||||||
 | 
					                  "Q"  # p_vaddr
 | 
				
			||||||
 | 
					                  "Q"  # p_paddr
 | 
				
			||||||
 | 
					                  "Q"  # p_filesz
 | 
				
			||||||
 | 
					                  "Q"  # p_memsz
 | 
				
			||||||
 | 
					                  "Q"  # p_align
 | 
				
			||||||
 | 
					                 )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
					        super(DumpGuestMemory, self).__init__("dump-guest-memory",
 | 
				
			||||||
 | 
					                                              gdb.COMMAND_DATA,
 | 
				
			||||||
 | 
					                                              gdb.COMPLETE_FILENAME)
 | 
				
			||||||
 | 
					        self.uintptr_t     = gdb.lookup_type("uintptr_t")
 | 
				
			||||||
 | 
					        self.elf64_ehdr_le = struct.Struct("<%s" % self.ELF64_EHDR)
 | 
				
			||||||
 | 
					        self.elf64_phdr_le = struct.Struct("<%s" % self.ELF64_PHDR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def int128_get64(self, val):
 | 
				
			||||||
 | 
					        assert (val["hi"] == 0)
 | 
				
			||||||
 | 
					        return val["lo"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def qtailq_foreach(self, head, field_str):
 | 
				
			||||||
 | 
					        var_p = head["tqh_first"]
 | 
				
			||||||
 | 
					        while (var_p != 0):
 | 
				
			||||||
 | 
					            var = var_p.dereference()
 | 
				
			||||||
 | 
					            yield var
 | 
				
			||||||
 | 
					            var_p = var[field_str]["tqe_next"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def qemu_get_ram_block(self, ram_addr):
 | 
				
			||||||
 | 
					        ram_blocks = gdb.parse_and_eval("ram_list.blocks")
 | 
				
			||||||
 | 
					        for block in self.qtailq_foreach(ram_blocks, "next"):
 | 
				
			||||||
 | 
					            if (ram_addr - block["offset"] < block["length"]):
 | 
				
			||||||
 | 
					                return block
 | 
				
			||||||
 | 
					        raise gdb.GdbError("Bad ram offset %x" % ram_addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def qemu_get_ram_ptr(self, ram_addr):
 | 
				
			||||||
 | 
					        block = self.qemu_get_ram_block(ram_addr)
 | 
				
			||||||
 | 
					        return block["host"] + (ram_addr - block["offset"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def memory_region_get_ram_ptr(self, mr):
 | 
				
			||||||
 | 
					        if (mr["alias"] != 0):
 | 
				
			||||||
 | 
					            return (self.memory_region_get_ram_ptr(mr["alias"].dereference()) +
 | 
				
			||||||
 | 
					                    mr["alias_offset"])
 | 
				
			||||||
 | 
					        return self.qemu_get_ram_ptr(mr["ram_addr"] & self.TARGET_PAGE_MASK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def guest_phys_blocks_init(self):
 | 
				
			||||||
 | 
					        self.guest_phys_blocks = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def guest_phys_blocks_append(self):
 | 
				
			||||||
 | 
					        print "guest RAM blocks:"
 | 
				
			||||||
 | 
					        print ("target_start     target_end       host_addr        message "
 | 
				
			||||||
 | 
					               "count")
 | 
				
			||||||
 | 
					        print ("---------------- ---------------- ---------------- ------- "
 | 
				
			||||||
 | 
					               "-----")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        current_map_p = gdb.parse_and_eval("address_space_memory.current_map")
 | 
				
			||||||
 | 
					        current_map = current_map_p.dereference()
 | 
				
			||||||
 | 
					        for cur in range(current_map["nr"]):
 | 
				
			||||||
 | 
					            flat_range   = (current_map["ranges"] + cur).dereference()
 | 
				
			||||||
 | 
					            mr           = flat_range["mr"].dereference()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # we only care about RAM
 | 
				
			||||||
 | 
					            if (not mr["ram"]):
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            section_size = self.int128_get64(flat_range["addr"]["size"])
 | 
				
			||||||
 | 
					            target_start = self.int128_get64(flat_range["addr"]["start"])
 | 
				
			||||||
 | 
					            target_end   = target_start + section_size
 | 
				
			||||||
 | 
					            host_addr    = (self.memory_region_get_ram_ptr(mr) +
 | 
				
			||||||
 | 
					                            flat_range["offset_in_region"])
 | 
				
			||||||
 | 
					            predecessor = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # find continuity in guest physical address space
 | 
				
			||||||
 | 
					            if (len(self.guest_phys_blocks) > 0):
 | 
				
			||||||
 | 
					                predecessor = self.guest_phys_blocks[-1]
 | 
				
			||||||
 | 
					                predecessor_size = (predecessor["target_end"] -
 | 
				
			||||||
 | 
					                                    predecessor["target_start"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # the memory API guarantees monotonically increasing
 | 
				
			||||||
 | 
					                # traversal
 | 
				
			||||||
 | 
					                assert (predecessor["target_end"] <= target_start)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # we want continuity in both guest-physical and
 | 
				
			||||||
 | 
					                # host-virtual memory
 | 
				
			||||||
 | 
					                if (predecessor["target_end"] < target_start or
 | 
				
			||||||
 | 
					                    predecessor["host_addr"] + predecessor_size != host_addr):
 | 
				
			||||||
 | 
					                    predecessor = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (predecessor is None):
 | 
				
			||||||
 | 
					                # isolated mapping, add it to the list
 | 
				
			||||||
 | 
					                self.guest_phys_blocks.append({"target_start": target_start,
 | 
				
			||||||
 | 
					                                               "target_end"  : target_end,
 | 
				
			||||||
 | 
					                                               "host_addr"   : host_addr})
 | 
				
			||||||
 | 
					                message = "added"
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                # expand predecessor until @target_end; predecessor's
 | 
				
			||||||
 | 
					                # start doesn't change
 | 
				
			||||||
 | 
					                predecessor["target_end"] = target_end
 | 
				
			||||||
 | 
					                message = "joined"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            print ("%016x %016x %016x %-7s %5u" %
 | 
				
			||||||
 | 
					                   (target_start, target_end, host_addr.cast(self.uintptr_t),
 | 
				
			||||||
 | 
					                    message, len(self.guest_phys_blocks)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def cpu_get_dump_info(self):
 | 
				
			||||||
 | 
					        # We can't synchronize the registers with KVM post-mortem, and
 | 
				
			||||||
 | 
					        # the bits in (first_x86_cpu->env.hflags) seem to be stale; they
 | 
				
			||||||
 | 
					        # may not reflect long mode for example. Hence just assume the
 | 
				
			||||||
 | 
					        # most common values. This also means that instruction pointer
 | 
				
			||||||
 | 
					        # etc. will be bogus in the dump, but at least the RAM contents
 | 
				
			||||||
 | 
					        # should be valid.
 | 
				
			||||||
 | 
					        self.dump_info = {"d_machine": self.EM_X86_64,
 | 
				
			||||||
 | 
					                          "d_endian" : self.ELFDATA2LSB,
 | 
				
			||||||
 | 
					                          "d_class"  : self.ELFCLASS64}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def encode_elf64_ehdr_le(self):
 | 
				
			||||||
 | 
					        return self.elf64_ehdr_le.pack(
 | 
				
			||||||
 | 
					                                 self.ELFMAG,                 # e_ident/magic
 | 
				
			||||||
 | 
					                                 self.dump_info["d_class"],   # e_ident/class
 | 
				
			||||||
 | 
					                                 self.dump_info["d_endian"],  # e_ident/data
 | 
				
			||||||
 | 
					                                 self.EV_CURRENT,             # e_ident/version
 | 
				
			||||||
 | 
					                                 0,                           # e_ident/osabi
 | 
				
			||||||
 | 
					                                 "",                          # e_ident/pad
 | 
				
			||||||
 | 
					                                 self.ET_CORE,                # e_type
 | 
				
			||||||
 | 
					                                 self.dump_info["d_machine"], # e_machine
 | 
				
			||||||
 | 
					                                 self.EV_CURRENT,             # e_version
 | 
				
			||||||
 | 
					                                 0,                           # e_entry
 | 
				
			||||||
 | 
					                                 self.elf64_ehdr_le.size,     # e_phoff
 | 
				
			||||||
 | 
					                                 0,                           # e_shoff
 | 
				
			||||||
 | 
					                                 0,                           # e_flags
 | 
				
			||||||
 | 
					                                 self.elf64_ehdr_le.size,     # e_ehsize
 | 
				
			||||||
 | 
					                                 self.elf64_phdr_le.size,     # e_phentsize
 | 
				
			||||||
 | 
					                                 self.phdr_num,               # e_phnum
 | 
				
			||||||
 | 
					                                 0,                           # e_shentsize
 | 
				
			||||||
 | 
					                                 0,                           # e_shnum
 | 
				
			||||||
 | 
					                                 0                            # e_shstrndx
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def encode_elf64_note_le(self):
 | 
				
			||||||
 | 
					        return self.elf64_phdr_le.pack(self.PT_NOTE,         # p_type
 | 
				
			||||||
 | 
					                                       0,                    # p_flags
 | 
				
			||||||
 | 
					                                       (self.memory_offset -
 | 
				
			||||||
 | 
					                                        len(self.note)),     # p_offset
 | 
				
			||||||
 | 
					                                       0,                    # p_vaddr
 | 
				
			||||||
 | 
					                                       0,                    # p_paddr
 | 
				
			||||||
 | 
					                                       len(self.note),       # p_filesz
 | 
				
			||||||
 | 
					                                       len(self.note),       # p_memsz
 | 
				
			||||||
 | 
					                                       0                     # p_align
 | 
				
			||||||
 | 
					                                      )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def encode_elf64_load_le(self, offset, start_hwaddr, range_size):
 | 
				
			||||||
 | 
					        return self.elf64_phdr_le.pack(self.PT_LOAD, # p_type
 | 
				
			||||||
 | 
					                                       0,            # p_flags
 | 
				
			||||||
 | 
					                                       offset,       # p_offset
 | 
				
			||||||
 | 
					                                       0,            # p_vaddr
 | 
				
			||||||
 | 
					                                       start_hwaddr, # p_paddr
 | 
				
			||||||
 | 
					                                       range_size,   # p_filesz
 | 
				
			||||||
 | 
					                                       range_size,   # p_memsz
 | 
				
			||||||
 | 
					                                       0             # p_align
 | 
				
			||||||
 | 
					                                      )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def note_init(self, name, desc, type):
 | 
				
			||||||
 | 
					        # name must include a trailing NUL
 | 
				
			||||||
 | 
					        namesz = (len(name) + 1 + 3) / 4 * 4
 | 
				
			||||||
 | 
					        descsz = (len(desc)     + 3) / 4 * 4
 | 
				
			||||||
 | 
					        fmt = ("<"   # little endian
 | 
				
			||||||
 | 
					               "I"   # n_namesz
 | 
				
			||||||
 | 
					               "I"   # n_descsz
 | 
				
			||||||
 | 
					               "I"   # n_type
 | 
				
			||||||
 | 
					               "%us" # name
 | 
				
			||||||
 | 
					               "%us" # desc
 | 
				
			||||||
 | 
					               % (namesz, descsz))
 | 
				
			||||||
 | 
					        self.note = struct.pack(fmt,
 | 
				
			||||||
 | 
					                                len(name) + 1, len(desc), type, name, desc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def dump_init(self):
 | 
				
			||||||
 | 
					        self.guest_phys_blocks_init()
 | 
				
			||||||
 | 
					        self.guest_phys_blocks_append()
 | 
				
			||||||
 | 
					        self.cpu_get_dump_info()
 | 
				
			||||||
 | 
					        # we have no way to retrieve the VCPU status from KVM
 | 
				
			||||||
 | 
					        # post-mortem
 | 
				
			||||||
 | 
					        self.note_init("NONE", "EMPTY", 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Account for PT_NOTE.
 | 
				
			||||||
 | 
					        self.phdr_num = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # We should never reach PN_XNUM for paging=false dumps: there's
 | 
				
			||||||
 | 
					        # just a handful of discontiguous ranges after merging.
 | 
				
			||||||
 | 
					        self.phdr_num += len(self.guest_phys_blocks)
 | 
				
			||||||
 | 
					        assert (self.phdr_num < self.PN_XNUM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Calculate the ELF file offset where the memory dump commences:
 | 
				
			||||||
 | 
					        #
 | 
				
			||||||
 | 
					        #   ELF header
 | 
				
			||||||
 | 
					        #   PT_NOTE
 | 
				
			||||||
 | 
					        #   PT_LOAD: 1
 | 
				
			||||||
 | 
					        #   PT_LOAD: 2
 | 
				
			||||||
 | 
					        #   ...
 | 
				
			||||||
 | 
					        #   PT_LOAD: len(self.guest_phys_blocks)
 | 
				
			||||||
 | 
					        #   ELF note
 | 
				
			||||||
 | 
					        #   memory dump
 | 
				
			||||||
 | 
					        self.memory_offset = (self.elf64_ehdr_le.size +
 | 
				
			||||||
 | 
					                              self.elf64_phdr_le.size * self.phdr_num +
 | 
				
			||||||
 | 
					                              len(self.note))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def dump_begin(self, vmcore):
 | 
				
			||||||
 | 
					        vmcore.write(self.encode_elf64_ehdr_le())
 | 
				
			||||||
 | 
					        vmcore.write(self.encode_elf64_note_le())
 | 
				
			||||||
 | 
					        running = self.memory_offset
 | 
				
			||||||
 | 
					        for block in self.guest_phys_blocks:
 | 
				
			||||||
 | 
					            range_size = block["target_end"] - block["target_start"]
 | 
				
			||||||
 | 
					            vmcore.write(self.encode_elf64_load_le(running,
 | 
				
			||||||
 | 
					                                                   block["target_start"],
 | 
				
			||||||
 | 
					                                                   range_size))
 | 
				
			||||||
 | 
					            running += range_size
 | 
				
			||||||
 | 
					        vmcore.write(self.note)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def dump_iterate(self, vmcore):
 | 
				
			||||||
 | 
					        qemu_core = gdb.inferiors()[0]
 | 
				
			||||||
 | 
					        for block in self.guest_phys_blocks:
 | 
				
			||||||
 | 
					            cur  = block["host_addr"]
 | 
				
			||||||
 | 
					            left = block["target_end"] - block["target_start"]
 | 
				
			||||||
 | 
					            print ("dumping range at %016x for length %016x" %
 | 
				
			||||||
 | 
					                   (cur.cast(self.uintptr_t), left))
 | 
				
			||||||
 | 
					            while (left > 0):
 | 
				
			||||||
 | 
					                chunk_size = min(self.TARGET_PAGE_SIZE, left)
 | 
				
			||||||
 | 
					                chunk = qemu_core.read_memory(cur, chunk_size)
 | 
				
			||||||
 | 
					                vmcore.write(chunk)
 | 
				
			||||||
 | 
					                cur  += chunk_size
 | 
				
			||||||
 | 
					                left -= chunk_size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_vmcore(self, filename):
 | 
				
			||||||
 | 
					        vmcore = open(filename, "wb")
 | 
				
			||||||
 | 
					        self.dump_begin(vmcore)
 | 
				
			||||||
 | 
					        self.dump_iterate(vmcore)
 | 
				
			||||||
 | 
					        vmcore.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def invoke(self, args, from_tty):
 | 
				
			||||||
 | 
					        # Unwittingly pressing the Enter key after the command should
 | 
				
			||||||
 | 
					        # not dump the same multi-gig coredump to the same file.
 | 
				
			||||||
 | 
					        self.dont_repeat()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        argv = gdb.string_to_argv(args)
 | 
				
			||||||
 | 
					        if (len(argv) != 1):
 | 
				
			||||||
 | 
					            raise gdb.GdbError("usage: dump-guest-memory FILE")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.dump_init()
 | 
				
			||||||
 | 
					        self.create_vmcore(argv[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DumpGuestMemory()
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/APIC
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/APIC
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/DSDT
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/DSDT
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/FACP
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/FACP
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/FACS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/FACS
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/HPET
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/HPET
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/SSDT
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/pc/SSDT
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/APIC
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/APIC
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/DSDT
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/DSDT
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/FACP
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/FACP
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/FACS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/FACS
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/HPET
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/HPET
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/MCFG
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/MCFG
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/SSDT
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/acpi-test-data/q35/SSDT
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										36
									
								
								tests/acpi-test-data/rebuild-expected-aml.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										36
									
								
								tests/acpi-test-data/rebuild-expected-aml.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					#! /bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Rebuild expected AML files for acpi unit-test
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2013 Red Hat Inc.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Authors:
 | 
				
			||||||
 | 
					#  Marcel Apfelbaum <marcel.a@redhat.com>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This work is licensed under the terms of the GNU GPLv2.
 | 
				
			||||||
 | 
					# See the COPYING.LIB file in the top-level directory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qemu=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -e x86_64-softmmu/qemu-system-x86_64 ]; then
 | 
				
			||||||
 | 
					    qemu="x86_64-softmmu/qemu-system-x86_64"
 | 
				
			||||||
 | 
					elif [ -e i386-softmmu/qemu-system-i386 ]; then
 | 
				
			||||||
 | 
					    qemu="i386-softmmu/qemu-system-i386"
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    echo "Run 'make' to build the qemu exectutable!"
 | 
				
			||||||
 | 
					    echo "Run this script from the build directory."
 | 
				
			||||||
 | 
					    exit 1;
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ ! -e "tests/acpi-test" ]; then
 | 
				
			||||||
 | 
					    echo "Test: acpi-test is required! Run make check before this script."
 | 
				
			||||||
 | 
					    echo "Run this script from the build directory."
 | 
				
			||||||
 | 
					    exit 1;
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_ACPI_REBUILD_AML=y QTEST_QEMU_BINARY=$qemu tests/acpi-test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "The files were rebuilt and can be added to git."
 | 
				
			||||||
 | 
					echo "However, if new files were created, please copy them manually" \
 | 
				
			||||||
 | 
					     "to tests/acpi-test-data/pc/ or tests/acpi-test-data/q35/ ."
 | 
				
			||||||
@ -13,19 +13,32 @@
 | 
				
			|||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <glib.h>
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <glib/gstdio.h>
 | 
				
			||||||
#include "qemu-common.h"
 | 
					#include "qemu-common.h"
 | 
				
			||||||
#include "libqtest.h"
 | 
					#include "libqtest.h"
 | 
				
			||||||
#include "qemu/compiler.h"
 | 
					#include "qemu/compiler.h"
 | 
				
			||||||
#include "hw/i386/acpi-defs.h"
 | 
					#include "hw/i386/acpi-defs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MACHINE_PC "pc"
 | 
				
			||||||
 | 
					#define MACHINE_Q35 "q35"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
 | 
				
			||||||
 | 
					#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* DSDT and SSDTs format */
 | 
					/* DSDT and SSDTs format */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    AcpiTableHeader header;
 | 
					    AcpiTableHeader header;
 | 
				
			||||||
    uint8_t *aml;
 | 
					    gchar *aml;            /* aml bytecode from guest */
 | 
				
			||||||
    int aml_len;
 | 
					    gsize aml_len;
 | 
				
			||||||
} AcpiSdtTable;
 | 
					    gchar *aml_file;
 | 
				
			||||||
 | 
					    gchar *asl;            /* asl code generated from aml */
 | 
				
			||||||
 | 
					    gsize asl_len;
 | 
				
			||||||
 | 
					    gchar *asl_file;
 | 
				
			||||||
 | 
					    bool asl_file_retain;   /* do not delete the temp asl */
 | 
				
			||||||
 | 
					} QEMU_PACKED AcpiSdtTable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    const char *machine;
 | 
				
			||||||
    uint32_t rsdp_addr;
 | 
					    uint32_t rsdp_addr;
 | 
				
			||||||
    AcpiRsdpDescriptor rsdp_table;
 | 
					    AcpiRsdpDescriptor rsdp_table;
 | 
				
			||||||
    AcpiRsdtDescriptorRev1 rsdt_table;
 | 
					    AcpiRsdtDescriptorRev1 rsdt_table;
 | 
				
			||||||
@ -33,8 +46,7 @@ typedef struct {
 | 
				
			|||||||
    AcpiFacsDescriptorRev1 facs_table;
 | 
					    AcpiFacsDescriptorRev1 facs_table;
 | 
				
			||||||
    uint32_t *rsdt_tables_addr;
 | 
					    uint32_t *rsdt_tables_addr;
 | 
				
			||||||
    int rsdt_tables_nr;
 | 
					    int rsdt_tables_nr;
 | 
				
			||||||
    AcpiSdtTable dsdt_table;
 | 
					    GArray *tables;
 | 
				
			||||||
    GArray *ssdt_tables;
 | 
					 | 
				
			||||||
} test_data;
 | 
					} test_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LOW(x) ((x) & 0xff)
 | 
					#define LOW(x) ((x) & 0xff)
 | 
				
			||||||
@ -51,13 +63,13 @@ typedef struct {
 | 
				
			|||||||
            field = readb(addr);               \
 | 
					            field = readb(addr);               \
 | 
				
			||||||
            break;                             \
 | 
					            break;                             \
 | 
				
			||||||
        case 2:                                \
 | 
					        case 2:                                \
 | 
				
			||||||
            field = le16_to_cpu(readw(addr));  \
 | 
					            field = readw(addr);               \
 | 
				
			||||||
            break;                             \
 | 
					            break;                             \
 | 
				
			||||||
        case 4:                                \
 | 
					        case 4:                                \
 | 
				
			||||||
            field = le32_to_cpu(readl(addr));  \
 | 
					            field = readl(addr);               \
 | 
				
			||||||
            break;                             \
 | 
					            break;                             \
 | 
				
			||||||
        case 8:                                \
 | 
					        case 8:                                \
 | 
				
			||||||
            field = le64_to_cpu(readq(addr));  \
 | 
					            field = readq(addr);               \
 | 
				
			||||||
            break;                             \
 | 
					            break;                             \
 | 
				
			||||||
        default:                               \
 | 
					        default:                               \
 | 
				
			||||||
            g_assert(false);                   \
 | 
					            g_assert(false);                   \
 | 
				
			||||||
@ -91,8 +103,10 @@ typedef struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Boot sector code: write SIGNATURE into memory,
 | 
					/* Boot sector code: write SIGNATURE into memory,
 | 
				
			||||||
 * then halt.
 | 
					 * then halt.
 | 
				
			||||||
 | 
					 * Q35 machine requires a minimum 0x7e000 bytes disk.
 | 
				
			||||||
 | 
					 * (bug or feature?)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static uint8_t boot_sector[0x200] = {
 | 
					static uint8_t boot_sector[0x7e000] = {
 | 
				
			||||||
    /* 7c00: mov $0xdead,%ax */
 | 
					    /* 7c00: mov $0xdead,%ax */
 | 
				
			||||||
    [0x00] = 0xb8,
 | 
					    [0x00] = 0xb8,
 | 
				
			||||||
    [0x01] = LOW(SIGNATURE),
 | 
					    [0x01] = LOW(SIGNATURE),
 | 
				
			||||||
@ -117,17 +131,45 @@ static uint8_t boot_sector[0x200] = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *disk = "tests/acpi-test-disk.raw";
 | 
					static const char *disk = "tests/acpi-test-disk.raw";
 | 
				
			||||||
 | 
					static const char *data_dir = "tests/acpi-test-data";
 | 
				
			||||||
 | 
					#ifdef CONFIG_IASL
 | 
				
			||||||
 | 
					static const char *iasl = stringify(CONFIG_IASL);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static const char *iasl;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void free_test_data(test_data *data)
 | 
					static void free_test_data(test_data *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    AcpiSdtTable *temp;
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_free(data->rsdt_tables_addr);
 | 
					    if (data->rsdt_tables_addr) {
 | 
				
			||||||
    for (i = 0; i < data->ssdt_tables->len; ++i) {
 | 
					        g_free(data->rsdt_tables_addr);
 | 
				
			||||||
        g_free(g_array_index(data->ssdt_tables, AcpiSdtTable, i).aml);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    g_array_free(data->ssdt_tables, false);
 | 
					
 | 
				
			||||||
    g_free(data->dsdt_table.aml);
 | 
					    for (i = 0; i < data->tables->len; ++i) {
 | 
				
			||||||
 | 
					        temp = &g_array_index(data->tables, AcpiSdtTable, i);
 | 
				
			||||||
 | 
					        if (temp->aml) {
 | 
				
			||||||
 | 
					            g_free(temp->aml);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (temp->aml_file) {
 | 
				
			||||||
 | 
					            if (g_strstr_len(temp->aml_file, -1, "aml-")) {
 | 
				
			||||||
 | 
					                unlink(temp->aml_file);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            g_free(temp->aml_file);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (temp->asl) {
 | 
				
			||||||
 | 
					            g_free(temp->asl);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (temp->asl_file) {
 | 
				
			||||||
 | 
					            if (!temp->asl_file_retain) {
 | 
				
			||||||
 | 
					                unlink(temp->asl_file);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            g_free(temp->asl_file);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_array_free(data->tables, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint8_t acpi_checksum(const uint8_t *data, int len)
 | 
					static uint8_t acpi_checksum(const uint8_t *data, int len)
 | 
				
			||||||
@ -292,34 +334,219 @@ static void test_dst_table(AcpiSdtTable *sdt_table, uint32_t addr)
 | 
				
			|||||||
    ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr);
 | 
					    ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    checksum = acpi_checksum((uint8_t *)sdt_table, sizeof(AcpiTableHeader)) +
 | 
					    checksum = acpi_checksum((uint8_t *)sdt_table, sizeof(AcpiTableHeader)) +
 | 
				
			||||||
               acpi_checksum(sdt_table->aml, sdt_table->aml_len);
 | 
					               acpi_checksum((uint8_t *)sdt_table->aml, sdt_table->aml_len);
 | 
				
			||||||
    g_assert(!checksum);
 | 
					    g_assert(!checksum);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_acpi_dsdt_table(test_data *data)
 | 
					static void test_acpi_dsdt_table(test_data *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AcpiSdtTable *dsdt_table = &data->dsdt_table;
 | 
					    AcpiSdtTable dsdt_table;
 | 
				
			||||||
    uint32_t addr = data->fadt_table.dsdt;
 | 
					    uint32_t addr = data->fadt_table.dsdt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test_dst_table(dsdt_table, addr);
 | 
					    memset(&dsdt_table, 0, sizeof(dsdt_table));
 | 
				
			||||||
    g_assert_cmphex(dsdt_table->header.signature, ==, ACPI_DSDT_SIGNATURE);
 | 
					    data->tables = g_array_new(false, true, sizeof(AcpiSdtTable));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test_dst_table(&dsdt_table, addr);
 | 
				
			||||||
 | 
					    g_assert_cmphex(dsdt_table.header.signature, ==, ACPI_DSDT_SIGNATURE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Place DSDT first */
 | 
				
			||||||
 | 
					    g_array_append_val(data->tables, dsdt_table);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_acpi_ssdt_tables(test_data *data)
 | 
					static void test_acpi_tables(test_data *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GArray *ssdt_tables;
 | 
					    int tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */
 | 
				
			||||||
    int ssdt_tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */
 | 
					 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ssdt_tables = g_array_sized_new(false, true, sizeof(AcpiSdtTable),
 | 
					    for (i = 0; i < tables_nr; i++) {
 | 
				
			||||||
                                    ssdt_tables_nr);
 | 
					 | 
				
			||||||
    for (i = 0; i < ssdt_tables_nr; i++) {
 | 
					 | 
				
			||||||
        AcpiSdtTable ssdt_table;
 | 
					        AcpiSdtTable ssdt_table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        memset(&ssdt_table, 0 , sizeof(ssdt_table));
 | 
				
			||||||
        uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */
 | 
					        uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */
 | 
				
			||||||
        test_dst_table(&ssdt_table, addr);
 | 
					        test_dst_table(&ssdt_table, addr);
 | 
				
			||||||
        g_array_append_val(ssdt_tables, ssdt_table);
 | 
					        g_array_append_val(data->tables, ssdt_table);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    data->ssdt_tables = ssdt_tables;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void dump_aml_files(test_data *data, bool rebuild)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AcpiSdtTable *sdt;
 | 
				
			||||||
 | 
					    GError *error = NULL;
 | 
				
			||||||
 | 
					    gchar *aml_file = NULL;
 | 
				
			||||||
 | 
					    gint fd;
 | 
				
			||||||
 | 
					    ssize_t ret;
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < data->tables->len; ++i) {
 | 
				
			||||||
 | 
					        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
 | 
				
			||||||
 | 
					        g_assert(sdt->aml);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (rebuild) {
 | 
				
			||||||
 | 
					            aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
 | 
				
			||||||
 | 
					                                       (gchar *)&sdt->header.signature);
 | 
				
			||||||
 | 
					            fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
 | 
				
			||||||
 | 
					                        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error);
 | 
				
			||||||
 | 
					            g_assert_no_error(error);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        g_assert(fd >= 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ret = qemu_write_full(fd, sdt, sizeof(AcpiTableHeader));
 | 
				
			||||||
 | 
					        g_assert(ret == sizeof(AcpiTableHeader));
 | 
				
			||||||
 | 
					        ret = qemu_write_full(fd, sdt->aml, sdt->aml_len);
 | 
				
			||||||
 | 
					        g_assert(ret == sdt->aml_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        close(fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (aml_file) {
 | 
				
			||||||
 | 
					            g_free(aml_file);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool compare_signature(AcpiSdtTable *sdt, uint32_t signature)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					   return sdt->header.signature == signature;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void load_asl(GArray *sdts, AcpiSdtTable *sdt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AcpiSdtTable *temp;
 | 
				
			||||||
 | 
					    GError *error = NULL;
 | 
				
			||||||
 | 
					    GString *command_line = g_string_new(iasl);
 | 
				
			||||||
 | 
					    gint fd;
 | 
				
			||||||
 | 
					    gchar *out, *out_err;
 | 
				
			||||||
 | 
					    gboolean ret;
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fd = g_file_open_tmp("asl-XXXXXX.dsl", &sdt->asl_file, &error);
 | 
				
			||||||
 | 
					    g_assert_no_error(error);
 | 
				
			||||||
 | 
					    close(fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* build command line */
 | 
				
			||||||
 | 
					    g_string_append_printf(command_line, " -p %s ", sdt->asl_file);
 | 
				
			||||||
 | 
					    if (compare_signature(sdt, ACPI_DSDT_SIGNATURE) ||
 | 
				
			||||||
 | 
					        compare_signature(sdt, ACPI_SSDT_SIGNATURE)) {
 | 
				
			||||||
 | 
					        for (i = 0; i < sdts->len; ++i) {
 | 
				
			||||||
 | 
					            temp = &g_array_index(sdts, AcpiSdtTable, i);
 | 
				
			||||||
 | 
					            if (compare_signature(temp, ACPI_DSDT_SIGNATURE) ||
 | 
				
			||||||
 | 
					                compare_signature(temp, ACPI_SSDT_SIGNATURE)) {
 | 
				
			||||||
 | 
					                g_string_append_printf(command_line, "-e %s ", temp->aml_file);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    g_string_append_printf(command_line, "-d %s", sdt->aml_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* pass 'out' and 'out_err' in order to be redirected */
 | 
				
			||||||
 | 
					    g_spawn_command_line_sync(command_line->str, &out, &out_err, NULL, &error);
 | 
				
			||||||
 | 
					    g_assert_no_error(error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = g_file_get_contents(sdt->asl_file, (gchar **)&sdt->asl,
 | 
				
			||||||
 | 
					                              &sdt->asl_len, &error);
 | 
				
			||||||
 | 
					    g_assert(ret);
 | 
				
			||||||
 | 
					    g_assert_no_error(error);
 | 
				
			||||||
 | 
					    g_assert(sdt->asl_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_free(out);
 | 
				
			||||||
 | 
					    g_free(out_err);
 | 
				
			||||||
 | 
					    g_string_free(command_line, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define COMMENT_END "*/"
 | 
				
			||||||
 | 
					#define DEF_BLOCK "DefinitionBlock ("
 | 
				
			||||||
 | 
					#define BLOCK_NAME_END ".aml"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static GString *normalize_asl(gchar *asl_code)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GString *asl = g_string_new(asl_code);
 | 
				
			||||||
 | 
					    gchar *comment, *block_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* strip comments (different generation days) */
 | 
				
			||||||
 | 
					    comment = g_strstr_len(asl->str, asl->len, COMMENT_END);
 | 
				
			||||||
 | 
					    if (comment) {
 | 
				
			||||||
 | 
					        asl = g_string_erase(asl, 0, comment + sizeof(COMMENT_END) - asl->str);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* strip def block name (it has file path in it) */
 | 
				
			||||||
 | 
					    if (g_str_has_prefix(asl->str, DEF_BLOCK)) {
 | 
				
			||||||
 | 
					        block_name = g_strstr_len(asl->str, asl->len, BLOCK_NAME_END);
 | 
				
			||||||
 | 
					        g_assert(block_name);
 | 
				
			||||||
 | 
					        asl = g_string_erase(asl, 0,
 | 
				
			||||||
 | 
					                             block_name + sizeof(BLOCK_NAME_END) - asl->str);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return asl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static GArray *load_expected_aml(test_data *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    AcpiSdtTable *sdt;
 | 
				
			||||||
 | 
					    gchar *aml_file;
 | 
				
			||||||
 | 
					    GError *error = NULL;
 | 
				
			||||||
 | 
					    gboolean ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GArray *exp_tables = g_array_new(false, true, sizeof(AcpiSdtTable));
 | 
				
			||||||
 | 
					    for (i = 0; i < data->tables->len; ++i) {
 | 
				
			||||||
 | 
					        AcpiSdtTable exp_sdt;
 | 
				
			||||||
 | 
					        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        memset(&exp_sdt, 0, sizeof(exp_sdt));
 | 
				
			||||||
 | 
					        exp_sdt.header.signature = sdt->header.signature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
 | 
				
			||||||
 | 
					                                   (gchar *)&exp_sdt.header.signature);
 | 
				
			||||||
 | 
					        exp_sdt.aml_file = aml_file;
 | 
				
			||||||
 | 
					        g_assert(g_file_test(aml_file, G_FILE_TEST_EXISTS));
 | 
				
			||||||
 | 
					        ret = g_file_get_contents(aml_file, &exp_sdt.aml,
 | 
				
			||||||
 | 
					                                  &exp_sdt.aml_len, &error);
 | 
				
			||||||
 | 
					        g_assert(ret);
 | 
				
			||||||
 | 
					        g_assert_no_error(error);
 | 
				
			||||||
 | 
					        g_assert(exp_sdt.aml);
 | 
				
			||||||
 | 
					        g_assert(exp_sdt.aml_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_array_append_val(exp_tables, exp_sdt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return exp_tables;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_acpi_asl(test_data *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    AcpiSdtTable *sdt, *exp_sdt;
 | 
				
			||||||
 | 
					    test_data exp_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(&exp_data, 0, sizeof(exp_data));
 | 
				
			||||||
 | 
					    exp_data.tables = load_expected_aml(data);
 | 
				
			||||||
 | 
					    dump_aml_files(data, false);
 | 
				
			||||||
 | 
					    for (i = 0; i < data->tables->len; ++i) {
 | 
				
			||||||
 | 
					        GString *asl, *exp_asl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
 | 
				
			||||||
 | 
					        exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        load_asl(data->tables, sdt);
 | 
				
			||||||
 | 
					        asl = normalize_asl(sdt->asl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        load_asl(exp_data.tables, exp_sdt);
 | 
				
			||||||
 | 
					        exp_asl = normalize_asl(exp_sdt->asl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (g_strcmp0(asl->str, exp_asl->str)) {
 | 
				
			||||||
 | 
					            sdt->asl_file_retain = true;
 | 
				
			||||||
 | 
					            exp_sdt->asl_file_retain = true;
 | 
				
			||||||
 | 
					            fprintf(stderr,
 | 
				
			||||||
 | 
					                    "acpi-test: Warning! %.4s mismatch. "
 | 
				
			||||||
 | 
					                    "Orig asl: %s, expected asl %s.\n",
 | 
				
			||||||
 | 
					                    (gchar *)&exp_sdt->header.signature,
 | 
				
			||||||
 | 
					                    sdt->asl_file, exp_sdt->asl_file);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        g_string_free(asl, true);
 | 
				
			||||||
 | 
					        g_string_free(exp_asl, true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free_test_data(&exp_data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_acpi_one(const char *params, test_data *data)
 | 
					static void test_acpi_one(const char *params, test_data *data)
 | 
				
			||||||
@ -329,10 +556,14 @@ static void test_acpi_one(const char *params, test_data *data)
 | 
				
			|||||||
    uint8_t signature_high;
 | 
					    uint8_t signature_high;
 | 
				
			||||||
    uint16_t signature;
 | 
					    uint16_t signature;
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					    const char *device = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memset(data, 0, sizeof(*data));
 | 
					    if (!g_strcmp0(data->machine, MACHINE_Q35)) {
 | 
				
			||||||
    args = g_strdup_printf("-net none -display none %s %s",
 | 
					        device = ",id=hd -device ide-hd,drive=hd";
 | 
				
			||||||
                           params ? params : "", disk);
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    args = g_strdup_printf("-net none -display none %s -drive file=%s%s,",
 | 
				
			||||||
 | 
					                           params ? params : "", disk, device);
 | 
				
			||||||
    qtest_start(args);
 | 
					    qtest_start(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   /* Wait at most 1 minute */
 | 
					   /* Wait at most 1 minute */
 | 
				
			||||||
@ -360,7 +591,15 @@ static void test_acpi_one(const char *params, test_data *data)
 | 
				
			|||||||
    test_acpi_fadt_table(data);
 | 
					    test_acpi_fadt_table(data);
 | 
				
			||||||
    test_acpi_facs_table(data);
 | 
					    test_acpi_facs_table(data);
 | 
				
			||||||
    test_acpi_dsdt_table(data);
 | 
					    test_acpi_dsdt_table(data);
 | 
				
			||||||
    test_acpi_ssdt_tables(data);
 | 
					    test_acpi_tables(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (iasl) {
 | 
				
			||||||
 | 
					        if (getenv(ACPI_REBUILD_EXPECTED_AML)) {
 | 
				
			||||||
 | 
					            dump_aml_files(data, true);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            test_acpi_asl(data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_quit(global_qtest);
 | 
					    qtest_quit(global_qtest);
 | 
				
			||||||
    g_free(args);
 | 
					    g_free(args);
 | 
				
			||||||
@ -373,8 +612,14 @@ static void test_acpi_tcg(void)
 | 
				
			|||||||
    /* Supplying -machine accel argument overrides the default (qtest).
 | 
					    /* Supplying -machine accel argument overrides the default (qtest).
 | 
				
			||||||
     * This is to make guest actually run.
 | 
					     * This is to make guest actually run.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
					    memset(&data, 0, sizeof(data));
 | 
				
			||||||
 | 
					    data.machine = MACHINE_PC;
 | 
				
			||||||
    test_acpi_one("-machine accel=tcg", &data);
 | 
					    test_acpi_one("-machine accel=tcg", &data);
 | 
				
			||||||
 | 
					    free_test_data(&data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(&data, 0, sizeof(data));
 | 
				
			||||||
 | 
					    data.machine = MACHINE_Q35;
 | 
				
			||||||
 | 
					    test_acpi_one("-machine q35,accel=tcg", &data);
 | 
				
			||||||
    free_test_data(&data);
 | 
					    free_test_data(&data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user