On Mon, Jul 08, 2013 at 02:10:03PM -0500, Anthony Liguori wrote:
"Michael S. Tsirkin" mst@redhat.com writes:
This fills in guest info table with misc information of interest to the guest. Will be used by ACPI table generation code.
Signed-off-by: Michael S. Tsirkin mst@redhat.com
hw/acpi/ich9.c | 7 ++++++- hw/acpi/piix4.c | 44 +++++++++++++++++++++++++++++++++++++++++++- hw/i386/Makefile.objs | 2 ++ hw/i386/pc.c | 41 +++++++++++++++++++++++++++++++++++++++-- hw/i386/pc_piix.c | 15 ++++++++++++--- hw/i386/pc_q35.c | 10 +++++++--- hw/isa/lpc_ich9.c | 11 +++++++++-- hw/mips/mips_malta.c | 2 +- hw/misc/pvpanic.c | 12 +++++++----- hw/pci-host/q35.c | 1 + include/hw/acpi/ich9.h | 2 +- include/hw/i386/ich9.h | 3 ++- include/hw/i386/pc.h | 37 ++++++++++++++++++++++++++++++++++--- 13 files changed, 164 insertions(+), 23 deletions(-)
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 4a17f32..764e27f 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -203,7 +203,7 @@ static void pm_powerdown_req(Notifier *n, void *opaque) }
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
qemu_irq sci_irq)
qemu_irq sci_irq, PcGuestInfo *guest_info)
{ memory_region_init(&pm->io, "ich9-pm", ICH9_PMIO_SIZE); memory_region_set_enabled(&pm->io, false); @@ -219,6 +219,11 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, ICH9_PMIO_GPE0_LEN); memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe);
- guest_info->gpe0_blk = PC_GUEST_PORT_ACPI_PM_BASE + ICH9_PMIO_GPE0_STS;
- guest_info->gpe0_blk_len = ICH9_PMIO_GPE0_LEN;
- guest_info->fix_rtc = true;
- guest_info->platform_timer = false;
- memory_region_init_io(&pm->io_smi, &ich9_smi_ops, pm, "apci-smi", 8); memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 756df3b..c077a7a 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -94,6 +94,8 @@ typedef struct PIIX4PMState {
CPUStatus gpe_cpu; Notifier cpu_added_notifier;
- PcGuestInfo *guest_info;
} PIIX4PMState;
static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, @@ -380,6 +382,27 @@ static void piix4_pm_powerdown_req(Notifier *n, void *opaque) acpi_pm1_evt_power_down(&s->ar); }
+static void piix4_update_guest_info(PIIX4PMState *s) +{
- PCIDevice *dev = &s->dev;
- BusState *bus = qdev_get_parent_bus(&dev->qdev);
- BusChild *kid, *next;
- memset(s->guest_info->slot_hotplug_enable, 0xff,
DIV_ROUND_UP(PCI_SLOT_MAX, BITS_PER_BYTE));
- QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
DeviceState *qdev = kid->child;
PCIDevice *pdev = PCI_DEVICE(qdev);
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
int slot = PCI_SLOT(pdev->devfn);
if (pc->no_hotplug) {
clear_bit(slot, s->guest_info->slot_hotplug_enable);
}
- }
+}
static void piix4_pm_machine_ready(Notifier *n, void *opaque) { PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready); @@ -391,6 +414,9 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque) pci_conf[0x67] = (isa_is_ioport_assigned(0x3f8) ? 0x08 : 0) | (isa_is_ioport_assigned(0x2f8) ? 0x90 : 0);
- if (s->guest_info) {
piix4_update_guest_info(s);
- }
}
static int piix4_pm_initfn(PCIDevice *dev) @@ -447,7 +473,8 @@ static int piix4_pm_initfn(PCIDevice *dev)
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq,
int kvm_enabled, FWCfgState *fw_cfg)
int kvm_enabled, FWCfgState *fw_cfg,
PcGuestInfo *guest_info)
{ PCIDevice *dev; PIIX4PMState *s; @@ -470,6 +497,21 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); }
- if (guest_info) {
s->guest_info = guest_info;
guest_info->s3_disabled = s->disable_s3;
guest_info->s4_disabled = s->disable_s4;
guest_info->s4_val = s->s4_val;
guest_info->acpi_enable_cmd = ACPI_ENABLE;
guest_info->acpi_disable_cmd = ACPI_DISABLE;
guest_info->gpe0_blk = GPE_BASE;
guest_info->gpe0_blk_len = GPE_LEN;
guest_info->fix_rtc = false;
guest_info->platform_timer = true;
- }
- return s->smb.smbus;
}
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 71be2da..e783050 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -5,6 +5,8 @@ obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
obj-y += kvmvapic.o obj-y += bios-linker-loader.o +hw/i386/pc_piix.o: hw/i386/pc_piix.c hw/i386/acpi-dsdt.hex +hw/i386/pc_q35.o: hw/i386/pc_q35.c hw/i386/q35-acpi-dsdt.hex
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \ ; then echo "$(2)"; else echo "$(3)"; fi ;) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 4b29685..e5ebfa5 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1012,6 +1012,27 @@ static void pc_fw_cfg_guest_info(PcGuestInfo *guest_info) fw_cfg_add_file(guest_info->fw_cfg, "etc/pci-info", info, sizeof *info); }
+static void pc_set_cpu_guest_info(CPUState *cpu, void *arg) +{
- PcGuestInfo *guest_info = arg;
- CPUClass *klass = CPU_GET_CLASS(cpu);
- uint64_t apic_id = klass->get_arch_id(cpu);
- int j;
- assert(apic_id <= MAX_CPUMASK_BITS);
- assert(apic_id < guest_info->apic_id_limit);
- set_bit(apic_id, guest_info->found_cpus);
- for (j = 0; j < guest_info->numa_nodes; j++) {
assert(cpu->cpu_index < max_cpus);
if (test_bit(cpu->cpu_index, node_cpumask[j])) {
guest_info->node_cpu[apic_id] = cpu_to_le64(j);
break;
}
- }
+}
typedef struct PcGuestInfoState { PcGuestInfo info; Notifier machine_done; @@ -1032,6 +1053,18 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state); PcGuestInfo *guest_info = &guest_info_state->info;
- 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_xrupt_override = kvm_allows_irq0_override();
- guest_info->numa_nodes = nb_numa_nodes;
- guest_info->node_mem = g_memdup(node_mem, guest_info->numa_nodes *
sizeof *guest_info->node_mem);
- guest_info->node_cpu = g_malloc0(guest_info->apic_id_limit *
sizeof *guest_info->node_mem);
This does not satisfy the "should use QOM properties" requirement that we discussed in the RFC thread.
I don't know which part of the RFC thread still applied and which doesn't: at that point you were rejecting the whole approach.
I found a mail where you said: I'd be a lot happier if we were passing more information to this routine and not hard coding it. For instance, the PCI interrupt assignments, the APIC ids, the number of available CPUs, etc.
So this is exactly what this code does. What, exactly, would you like to see instead? Create a guest info QOM object, and encode all information used by ACPI generation as properties of this object?
- memset(&guest_info->found_cpus, 0, sizeof guest_info->found_cpus);
- qemu_for_each_cpu(pc_set_cpu_guest_info, guest_info);
- guest_info->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS; if (sizeof(hwaddr) == 4) { guest_info->pci_info.w64.begin = 0;
@@ -1204,7 +1237,8 @@ static const MemoryRegionOps ioportF0_io_ops = { void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, ISADevice **rtc_state, ISADevice **floppy,
bool no_vmport)
bool no_vmport,
PcGuestInfo *guest_info)
{ int i; DriveInfo *fd[MAX_FD]; @@ -1230,7 +1264,10 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT * when the HPET wants to take over. Thus we have to disable the latter. */
- if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
guest_info->has_hpet = !no_hpet &&
(!kvm_irqchip_in_kernel() || kvm_has_pit_state2());
if (guest_info->has_hpet) { hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
if (hpet) {
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index ecd1490..3c2541a 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -50,6 +50,8 @@ # include <xen/hvm/hvm_info_table.h> #endif
+#include "hw/i386/acpi-dsdt.hex"
#define MAX_IDE_BUS 2
static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 }; @@ -122,6 +124,10 @@ static void pc_init1(MemoryRegion *system_memory, }
guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
guest_info->dsdt_code = AcpiDsdtAmlCode;
guest_info->dsdt_size = sizeof AcpiDsdtAmlCode;
guest_info->has_pci_info = has_pci_info;
/* Set PCI window size the way seabios has always done it. */
@@ -190,7 +196,8 @@ static void pc_init1(MemoryRegion *system_memory, pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
/* init basic PC hardware */
- pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled(),
guest_info);
pc_nic_init(isa_bus, pci_bus);
@@ -229,7 +236,9 @@ static void pc_init1(MemoryRegion *system_memory, /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, gsi[9], *smi_irq,
kvm_enabled(), fw_cfg);
kvm_enabled(), fw_cfg,
guest_info);
}guest_info->sci_int = 9; smbus_eeprom_init(smbus, 8, NULL, 0);
@@ -238,7 +247,7 @@ static void pc_init1(MemoryRegion *system_memory, }
if (has_pvpanic) {
pvpanic_init(isa_bus);
}pvpanic_init(isa_bus, guest_info);
}
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 5b92160..50afe7c 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -43,6 +43,8 @@ #include "hw/usb.h" #include "hw/cpu/icc_bus.h"
+#include "hw/i386/q35-acpi-dsdt.hex"
/* ICH9 AHCI has 6 ports */ #define MAX_SATA_PORTS 6
@@ -109,6 +111,8 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); guest_info->has_pci_info = has_pci_info;
guest_info->dsdt_code = Q35AcpiDsdtAmlCode;
guest_info->dsdt_size = sizeof Q35AcpiDsdtAmlCode;
/* allocate ram and load rom/bios */ if (!xen_enabled()) {
@@ -175,10 +179,10 @@ static void pc_q35_init(QEMUMachineInitArgs *args) pc_register_ferr_irq(gsi[13]);
/* init basic PC hardware */
- pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false);
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false, guest_info);
/* connect pm stuff to lpc */
- ich9_lpc_pm_init(lpc);
ich9_lpc_pm_init(lpc, guest_info);
/* ahci and SATA device, for q35 1 ahci controller is built-in */ ahci = pci_create_simple_multifunction(host_bus,
@@ -210,7 +214,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) }
if (has_pvpanic) {
pvpanic_init(isa_bus);
}pvpanic_init(isa_bus, guest_info);
}
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 667e882..a742fcb 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -312,6 +312,13 @@ PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin) return route; }
+void ich9_lpc_set_guest_info(PcGuestInfo *guest_info) +{
- guest_info->sci_int = 9;
- guest_info->acpi_enable_cmd = ICH9_APM_ACPI_ENABLE;
- guest_info->acpi_disable_cmd = ICH9_APM_ACPI_DISABLE;
+}
static int ich9_lpc_sci_irq(ICH9LPCState *lpc) { switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] & @@ -356,13 +363,13 @@ static void ich9_set_sci(void *opaque, int irq_num, int level) } }
-void ich9_lpc_pm_init(PCIDevice *lpc_pci) +void ich9_lpc_pm_init(PCIDevice *lpc_pci, PcGuestInfo *guest_info) { ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci); qemu_irq *sci_irq;
sci_irq = qemu_allocate_irqs(ich9_set_sci, lpc, 1);
- ich9_pm_init(lpc_pci, &lpc->pm, sci_irq[0]);
ich9_pm_init(lpc_pci, &lpc->pm, sci_irq[0], guest_info);
ich9_lpc_reset(&lpc->d.qdev);
} diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 5843fad..b95597c 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -964,7 +964,7 @@ void mips_malta_init(QEMUMachineInitArgs *args) pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1); pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci"); smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
isa_get_irq(NULL, 9), NULL, 0, NULL);
/* TODO: Populate SPD eeprom data. */ smbus_eeprom_init(smbus, 8, NULL, 0); pit = pit_init(isa_bus, 0x40, 0, NULL);isa_get_irq(NULL, 9), NULL, 0, NULL, NULL);
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c index 792d8e4..7af713a 100644 --- a/hw/misc/pvpanic.c +++ b/hw/misc/pvpanic.c @@ -101,25 +101,27 @@ static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp) isa_register_ioport(d, &s->io, s->ioport); }
-static void pvpanic_fw_cfg(ISADevice *dev, FWCfgState *fw_cfg) +static void pvpanic_guest_info(ISADevice *dev, PcGuestInfo *guest_info) { PVPanicState *s = ISA_PVPANIC_DEVICE(dev); uint16_t *pvpanic_port = g_malloc(sizeof(*pvpanic_port)); *pvpanic_port = cpu_to_le16(s->ioport);
- fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
- fw_cfg_add_file(guest_info->fw_cfg, "etc/pvpanic-port", pvpanic_port, sizeof(*pvpanic_port));
- guest_info->pvpanic_port = s->ioport;
}
-void pvpanic_init(ISABus *bus) +void pvpanic_init(ISABus *bus, PcGuestInfo *guest_info) { ISADevice *dev;
- FWCfgState *fw_cfg = fw_cfg_find();
- FWCfgState *fw_cfg = guest_info->fw_cfg; if (!fw_cfg) { return; } dev = isa_create_simple (bus, TYPE_ISA_PVPANIC_DEVICE);
- pvpanic_fw_cfg(dev, fw_cfg);
- pvpanic_guest_info(dev, guest_info);
}
static Property pvpanic_isa_properties[] = { diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 13148ed..667bd20 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -260,6 +260,7 @@ static int mch_init(PCIDevice *d) */ mch->guest_info->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT + MCH_HOST_BRIDGE_PCIEXBAR_MAX;
mch->guest_info->mcfg_base = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
/* setup pci memory regions */ memory_region_init_alias(&mch->pci_hole, "pci-hole",
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h index b1fe71f..66ab31a 100644 --- a/include/hw/acpi/ich9.h +++ b/include/hw/acpi/ich9.h @@ -45,7 +45,7 @@ typedef struct ICH9LPCPMRegs { } ICH9LPCPMRegs;
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
qemu_irq sci_irq);
qemu_irq sci_irq, PcGuestInfo *guest_info);
void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base); extern const VMStateDescription vmstate_ich9_pm;
diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h index c5f637b..7428452 100644 --- a/include/hw/i386/ich9.h +++ b/include/hw/i386/ich9.h @@ -15,10 +15,11 @@ #include "hw/acpi/ich9.h" #include "hw/pci/pci_bus.h"
+void ich9_lpc_set_guest_info(PcGuestInfo *guest_info); void ich9_lpc_set_irq(void *opaque, int irq_num, int level); int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin); -void ich9_lpc_pm_init(PCIDevice *pci_lpc); +void ich9_lpc_pm_init(PCIDevice *pci_lpc, PcGuestInfo *guest_info); PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus); i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 56f2e41..b29c8f6 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -10,6 +10,9 @@ #include "hw/i386/ioapic.h"
#include "qemu/range.h" +#include "qemu/bitmap.h" +#include "sysemu/sysemu.h" +#include "hw/pci/pci.h"
/* PC-style peripherals (also used by other machines). */
@@ -18,9 +21,35 @@ typedef struct PcPciInfo { Range w64; } PcPciInfo;
+/* Matches the value hard-coded in BIOS */ +#define PC_GUEST_PORT_ACPI_PM_BASE 0xb000
struct PcGuestInfo { PcPciInfo pci_info; bool has_pci_info;
- hwaddr ram_size;
- unsigned apic_id_limit;
- bool apic_xrupt_override;
- bool has_hpet;
- uint64_t numa_nodes;
- uint64_t *node_mem;
- uint64_t *node_cpu;
- DECLARE_BITMAP(found_cpus, MAX_CPUMASK_BITS + 1);
- bool s3_disabled;
- bool s4_disabled;
- uint8_t s4_val;
- DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
- uint16_t sci_int;
- uint8_t acpi_enable_cmd;
- uint8_t acpi_disable_cmd;
- uint32_t gpe0_blk;
- uint32_t gpe0_blk_len;
- bool fix_rtc;
- bool platform_timer;
- uint64_t mcfg_base;
- const unsigned char *dsdt_code;
- unsigned dsdt_size;
- uint16_t pvpanic_port;
This is all stuff that should be obtained via QOM.
Doing it this way just makes it all that much harder to detangle the PC initialization mess we already have.
Again, what do you mean exactly? Would you like code in acpi-build to poke at devicestate structures of random devices?
Regards,
Anthony Liguori
FWCfgState *fw_cfg;
};
@@ -114,7 +143,8 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, ISADevice **rtc_state, ISADevice **floppy,
bool no_vmport);
bool no_vmport,
PcGuestInfo *guest_info);
void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd); void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, const char *boot_device, @@ -132,7 +162,8 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq,
int kvm_enabled, FWCfgState *fw_cfg);
int kvm_enabled, FWCfgState *fw_cfg,
PcGuestInfo *guest_info);
void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
/* hpet.c */ @@ -194,7 +225,7 @@ static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd) void pc_system_firmware_init(MemoryRegion *rom_memory);
/* pvpanic.c */ -void pvpanic_init(ISABus *bus); +void pvpanic_init(ISABus *bus, PcGuestInfo *guest_info);
/* e820 types */
#define E820_RAM 1
MST
SeaBIOS mailing list SeaBIOS@seabios.org http://www.seabios.org/mailman/listinfo/seabios