Message ID | 1373307914-18543-4-git-send-email-mst@redhat.com |
---|---|
State | New |
Headers | show |
"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. > + > + 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); > + isa_get_irq(NULL, 9), NULL, 0, NULL, NULL); > /* TODO: Populate SPD eeprom data. */ > smbus_eeprom_init(smbus, 8, NULL, 0); > pit = pit_init(isa_bus, 0x40, 0, 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. 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
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); > > + isa_get_irq(NULL, 9), NULL, 0, NULL, NULL); > > /* TODO: Populate SPD eeprom data. */ > > smbus_eeprom_init(smbus, 8, NULL, 0); > > pit = pit_init(isa_bus, 0x40, 0, 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
Hi, >> 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? Don't touch device code for this. >>> -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); >>> } To pick this one as example: Instead of patching pvpanic code to stuff config info into GuestInfo you should (1) search the device object tree for a pvpanic device and (b) if present read the ioport property to figure the base address. /me suggests to check out qmp_qom_get() in qmp.c. Some qom aequivalent for qdev_find_recursive would be handy, dunno whenever such a thing exists already, Andreas? I'd tend to accept GuestInfo as temporary thing for stuff which can't be figured using qom properties today. Anthony might disagree though. cheers, Gerd
Hi Gerd, Am 24.07.2013 16:42, schrieb Gerd Hoffmann: >>> 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? > > Don't touch device code for this. > >>>> -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); >>>> } > > To pick this one as example: Instead of patching pvpanic code to stuff > config info into GuestInfo you should (1) search the device object tree > for a pvpanic device and (b) if present read the ioport property to > figure the base address. Yeah, the above does not feel so nice from a QOM view (didn't review the ACPI series yet). > /me suggests to check out qmp_qom_get() in qmp.c. Some qom aequivalent > for qdev_find_recursive would be handy, dunno whenever such a thing > exists already, Andreas? Not sure what's needed here? object_resolve_path() and object_foreach_child() come to mind... Regards, Andreas > I'd tend to accept GuestInfo as temporary thing for stuff which can't be > figured using qom properties today. Anthony might disagree though. > > cheers, > Gerd >
Hi, >> /me suggests to check out qmp_qom_get() in qmp.c. Some qom aequivalent >> for qdev_find_recursive would be handy, dunno whenever such a thing >> exists already, Andreas? > > Not sure what's needed here? object_resolve_path() and > object_foreach_child() come to mind... object_resolve_path should do to (a) figure whenever we are i440fx or q35 and (b) get the pcihost device (then read enable_s3 etc properties). For pvpanic (and maybe others) it might be handy to have "find me the device of type TYPE_ISA_PVPANIC_DEVICE, anywhere in the tree" functionality, so the same code works no matter where the isa bridge happens to live. Or "find me all pci bridges in the system". Is object_foreach_child recursive? Then it might do the job ... cheers, Gerd
Hi, Am 24.07.2013 17:04, schrieb Gerd Hoffmann: >>> /me suggests to check out qmp_qom_get() in qmp.c. Some qom aequivalent >>> for qdev_find_recursive would be handy, dunno whenever such a thing >>> exists already, Andreas? >> >> Not sure what's needed here? object_resolve_path() and >> object_foreach_child() come to mind... > > object_resolve_path should do to (a) figure whenever we are i440fx or > q35 and (b) get the pcihost device (then read enable_s3 etc properties). > > For pvpanic (and maybe others) it might be handy to have "find me the > device of type TYPE_ISA_PVPANIC_DEVICE, anywhere in the tree" > functionality, so the same code works no matter where the isa bridge > happens to live. Or "find me all pci bridges in the system". I think Paolo used object_resolve_path_type("", TYPE_...) for that somewhere in audio code. > Is object_foreach_child recursive? Then it might do the job ... No, recursion would need to be implemented in the callback - my recent recursive QOM realization series had an example of a deep search for devices. Regards, Andreas
Il 24/07/2013 17:09, Andreas Färber ha scritto: > Hi, > > Am 24.07.2013 17:04, schrieb Gerd Hoffmann: >>>> /me suggests to check out qmp_qom_get() in qmp.c. Some qom aequivalent >>>> for qdev_find_recursive would be handy, dunno whenever such a thing >>>> exists already, Andreas? >>> >>> Not sure what's needed here? object_resolve_path() and >>> object_foreach_child() come to mind... >> >> object_resolve_path should do to (a) figure whenever we are i440fx or >> q35 and (b) get the pcihost device (then read enable_s3 etc properties). >> >> For pvpanic (and maybe others) it might be handy to have "find me the >> device of type TYPE_ISA_PVPANIC_DEVICE, anywhere in the tree" >> functionality, so the same code works no matter where the isa bridge >> happens to live. Or "find me all pci bridges in the system". > > I think Paolo used object_resolve_path_type("", TYPE_...) for that > somewhere in audio code. Yes. It returns NULL if there is more than one device, but in some cases it may be exactly what you want... Paolo >> Is object_foreach_child recursive? Then it might do the job ... > > No, recursion would need to be implemented in the callback - my recent > recursive QOM realization series had an example of a deep search for > devices. > > Regards, > Andreas >
On Wed, Jul 24, 2013 at 04:42:08PM +0200, Gerd Hoffmann wrote: > Hi, > > >> 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? > > Don't touch device code for this. > > >>> -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); > >>> } > > To pick this one as example: Instead of patching pvpanic code to stuff > config info into GuestInfo you should (1) search the device object tree > for a pvpanic device and (b) if present read the ioport property to > figure the base address. > > /me suggests to check out qmp_qom_get() in qmp.c. Some qom aequivalent > for qdev_find_recursive would be handy, dunno whenever such a thing > exists already, Andreas? > > I'd tend to accept GuestInfo as temporary thing for stuff which can't be > figured using qom properties today. Anthony might disagree though. > > cheers, > Gerd That's exactly what I implemented, with APIs so that we don't expose structure internals and path names to all the world. Will post soon.
On Wed, Jul 24, 2013 at 04:52:05PM +0200, Andreas Färber wrote: > Hi Gerd, > > Am 24.07.2013 16:42, schrieb Gerd Hoffmann: > >>> 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? > > > > Don't touch device code for this. > > > >>>> -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); > >>>> } > > > > To pick this one as example: Instead of patching pvpanic code to stuff > > config info into GuestInfo you should (1) search the device object tree > > for a pvpanic device and (b) if present read the ioport property to > > figure the base address. > > Yeah, the above does not feel so nice from a QOM view (didn't review the > ACPI series yet). If you do please review v3 which was just posted. It should address your comment - though long term, it would be nicer if we had multiple inheritance for interfaces, then we could expose a generic panic interface with the io port number, avoid need to poke at specific device. > > /me suggests to check out qmp_qom_get() in qmp.c. Some qom aequivalent > > for qdev_find_recursive would be handy, dunno whenever such a thing > > exists already, Andreas? > > Not sure what's needed here? object_resolve_path() and > object_foreach_child() come to mind... > > Regards, > Andreas > > > I'd tend to accept GuestInfo as temporary thing for stuff which can't be > > figured using qom properties today. Anthony might disagree though. > > > > cheers, > > Gerd > > > > > -- > SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany > GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
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); + + 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); + isa_get_irq(NULL, 9), NULL, 0, NULL, NULL); /* TODO: Populate SPD eeprom data. */ smbus_eeprom_init(smbus, 8, NULL, 0); pit = pit_init(isa_bus, 0x40, 0, 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; 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
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(-)