diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-11-03 22:51:07 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-11-03 22:51:08 +0000 |
commit | 949ca9e479c381a63ddb257adca1a6f0c44d898e (patch) | |
tree | c0ef67123c24a2474fe31ea17a924cbac424f53f /hw | |
parent | 47e8acb45feddcbc340583781b53935459330db2 (diff) | |
parent | d43f0d641e366251bd9c63005241775f672bf3ec (diff) | |
download | qemu-949ca9e479c381a63ddb257adca1a6f0c44d898e.tar.gz qemu-949ca9e479c381a63ddb257adca1a6f0c44d898e.tar.bz2 qemu-949ca9e479c381a63ddb257adca1a6f0c44d898e.zip |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc, virtio, misc bugfixes
A bunch of minor bugfixes all over the place.
changes from v2:
added cpu hotplug rework
added default vga type switch
more fixes
changes from v1:
fix for test re-generation script
add missing acks to two patches
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Mon 03 Nov 2014 16:33:13 GMT using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
* remotes/mst/tags/for_upstream: (28 commits)
vga: flip qemu 2.2 pc machine types from cirrus to stdvga
vga: add default display to machine class
vhost-user: fix mmap offset calculation
hw/i386/acpi-build.c: Fix memory leak in acpi_build_tables_cleanup()
smbios: Encode UUID according to SMBIOS specification
pc: Add pc_compat_2_1() function
hw/virtio/vring/event_idx: fix the vring_avail_event error
hw/pci: fixed hotplug crash when using rombar=0 with devices having romfile
hw/pci: fixed error flow in pci_qdev_init
-machine vmport=off: Allow disabling of VMWare ioport emulation
acpi/cpu-hotplug: introduce helper function to keep bit setting in one place
cpu-hotplug: rename function for better readability
qom/cpu: remove the unused CPU hot-plug notifier
pc: Update rtc_cmos in pc_cpu_plug
pc: add cpu hotplug handler to PC_MACHINE
acpi:piix4: convert cpu hotplug to hotplug_handler API
acpi:ich9: convert cpu hotplug to hotplug_handler API
acpi/cpu: add cpu hotplug callback function to match hotplug_handler API
acpi: create separate file for TCPA log
tests: fix rebuild-expected-aml.sh for acpi-test rename
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/acpi/cpu_hotplug.c | 34 | ||||
-rw-r--r-- | hw/acpi/ich9.c | 17 | ||||
-rw-r--r-- | hw/acpi/piix4.c | 18 | ||||
-rw-r--r-- | hw/i386/acpi-build.c | 28 | ||||
-rw-r--r-- | hw/i386/pc.c | 67 | ||||
-rw-r--r-- | hw/i386/pc_piix.c | 31 | ||||
-rw-r--r-- | hw/i386/pc_q35.c | 29 | ||||
-rw-r--r-- | hw/i386/smbios.c | 29 | ||||
-rw-r--r-- | hw/pci/pci.c | 16 | ||||
-rw-r--r-- | hw/pci/pcie.c | 2 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 7 | ||||
-rw-r--r-- | hw/virtio/dataplane/vring.c | 8 | ||||
-rw-r--r-- | hw/virtio/vhost-user.c | 2 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.c | 29 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.h | 5 | ||||
-rw-r--r-- | hw/virtio/virtio.c | 2 |
16 files changed, 210 insertions, 114 deletions
diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c index 2ad83a0ede..b8ebfadc30 100644 --- a/hw/acpi/cpu_hotplug.c +++ b/hw/acpi/cpu_hotplug.c @@ -36,28 +36,40 @@ static const MemoryRegionOps AcpiCpuHotplug_ops = { }, }; -void AcpiCpuHotplug_add(ACPIGPE *gpe, AcpiCpuHotplug *g, CPUState *cpu) +static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu, + Error **errp) { 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_assert((cpu_id / 8) < ACPI_GPE_PROC_LEN); + cpu_id = k->get_arch_id(cpu); + if ((cpu_id / 8) >= ACPI_GPE_PROC_LEN) { + error_setg(errp, "acpi: invalid cpu id: %" PRIi64, cpu_id); + return; + } + g->sts[cpu_id / 8] |= (1 << (cpu_id % 8)); } -void AcpiCpuHotplug_init(MemoryRegion *parent, Object *owner, - AcpiCpuHotplug *gpe_cpu, uint16_t base) +void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq, + AcpiCpuHotplug *g, DeviceState *dev, Error **errp) +{ + acpi_set_cpu_present_bit(g, CPU(dev), errp); + if (*errp != NULL) { + return; + } + + ar->gpe.sts[0] |= ACPI_CPU_HOTPLUG_STATUS; + acpi_update_sci(ar, irq); +} + +void acpi_cpu_hotplug_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)); + acpi_set_cpu_present_bit(gpe_cpu, cpu, &error_abort); } memory_region_init_io(&gpe_cpu->io, owner, &AcpiCpuHotplug_ops, gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN); diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 7b14bbbee1..ea991a3c65 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -209,15 +209,6 @@ static void pm_powerdown_req(Notifier *n, void *opaque) 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, qemu_irq sci_irq) { @@ -244,10 +235,8 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, pm->powerdown_notifier.notify = pm_powerdown_req; 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); + acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci), + &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE); if (pm->acpi_memory_hotplug.is_enabled) { acpi_memory_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci), @@ -304,6 +293,8 @@ void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp) object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { acpi_memory_plug_cb(&pm->acpi_regs, pm->irq, &pm->acpi_memory_hotplug, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + acpi_cpu_plug_cb(&pm->acpi_regs, pm->irq, &pm->gpe_cpu, dev, errp); } else { error_setg(errp, "acpi: device plug request for not supported device" " type: %s", object_get_typename(OBJECT(dev))); diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 0bfa814f71..78c0a6d323 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -83,7 +83,6 @@ typedef struct PIIX4PMState { uint8_t s4_val; AcpiCpuHotplug gpe_cpu; - Notifier cpu_added_notifier; MemHotplugState acpi_memory_hotplug; } PIIX4PMState; @@ -348,6 +347,8 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev, } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + acpi_cpu_plug_cb(&s->ar, s->irq, &s->gpe_cpu, dev, errp); } else { error_setg(errp, "acpi: device plug request for not supported device" " type: %s", object_get_typename(OBJECT(dev))); @@ -544,15 +545,6 @@ static const MemoryRegionOps piix4_gpe_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static void piix4_cpu_added_req(Notifier *n, void *opaque) -{ - PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier); - - assert(s != NULL); - AcpiCpuHotplug_add(&s->ar.gpe, &s->gpe_cpu, CPU(opaque)); - acpi_update_sci(&s->ar, s->irq); -} - static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, PCIBus *bus, PIIX4PMState *s) { @@ -563,10 +555,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent, s->use_acpi_pci_hotplug); - AcpiCpuHotplug_init(parent, OBJECT(s), &s->gpe_cpu, - PIIX4_CPU_HOTPLUG_IO_BASE); - s->cpu_added_notifier.notify = piix4_cpu_added_req; - qemu_register_cpu_added_notifier(&s->cpu_added_notifier); + acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu, + PIIX4_CPU_HOTPLUG_IO_BASE); if (s->acpi_memory_hotplug.is_enabled) { acpi_memory_hotplug_init(parent, OBJECT(s), &s->acpi_memory_hotplug); diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 00be4bb12a..4003b6bf9b 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -249,6 +249,7 @@ static void acpi_get_pci_info(PcPciInfo *info) #define ACPI_BUILD_TABLE_FILE "etc/acpi/tables" #define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp" +#define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log" static void build_header(GArray *linker, GArray *table_data, @@ -1214,27 +1215,28 @@ build_hpet(GArray *table_data, GArray *linker) } static void -build_tpm_tcpa(GArray *table_data, GArray *linker) +build_tpm_tcpa(GArray *table_data, GArray *linker, GArray *tcpalog) { Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa); - /* the log area will come right after the TCPA table */ - uint64_t log_area_start_address = acpi_data_len(table_data); + uint64_t log_area_start_address = acpi_data_len(tcpalog); tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT); tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE); tcpa->log_area_start_address = cpu_to_le64(log_area_start_address); + bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, 1, + false /* high memory */); + /* log area start address to be filled by Guest linker */ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, - ACPI_BUILD_TABLE_FILE, + ACPI_BUILD_TPMLOG_FILE, table_data, &tcpa->log_area_start_address, sizeof(tcpa->log_area_start_address)); build_header(linker, table_data, (void *)tcpa, "TCPA", sizeof(*tcpa), 2); - /* now only get the log area and with that modify table_data */ - acpi_data_push(table_data, TPM_LOG_AREA_MINIMUM_SIZE); + acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE); } static void @@ -1485,6 +1487,7 @@ typedef struct AcpiBuildTables { GArray *table_data; GArray *rsdp; + GArray *tcpalog; GArray *linker; } AcpiBuildTables; @@ -1492,17 +1495,17 @@ static inline void acpi_build_tables_init(AcpiBuildTables *tables) { tables->rsdp = g_array_new(false, true /* clear */, 1); tables->table_data = g_array_new(false, true /* clear */, 1); + tables->tcpalog = g_array_new(false, true /* clear */, 1); tables->linker = bios_linker_loader_init(); } static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre) { void *linker_data = bios_linker_loader_cleanup(tables->linker); - if (mfre) { - g_free(linker_data); - } + g_free(linker_data); g_array_free(tables->rsdp, mfre); - g_array_free(tables->table_data, mfre); + g_array_free(tables->table_data, true); + g_array_free(tables->tcpalog, mfre); } typedef @@ -1612,7 +1615,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables) } if (misc.has_tpm) { acpi_add_table(table_offsets, tables->table_data); - build_tpm_tcpa(tables->table_data, tables->linker); + build_tpm_tcpa(tables->table_data, tables->linker, tables->tcpalog); acpi_add_table(table_offsets, tables->table_data); build_tpm_ssdt(tables->table_data, tables->linker); @@ -1778,6 +1781,9 @@ void acpi_setup(PcGuestInfo *guest_info) acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader"); + fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE, + tables.tcpalog->data, acpi_data_len(tables.tcpalog)); + /* * RSDP is small so it's easy to keep it immutable, no need to * bother with ROM blobs. diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 889e888c6a..1205db83bc 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -355,30 +355,15 @@ static void pc_cmos_init_late(void *opaque) qemu_unregister_reset(pc_cmos_init_late, opaque); } -typedef struct RTCCPUHotplugArg { - Notifier cpu_added_notifier; - ISADevice *rtc_state; -} RTCCPUHotplugArg; - -static void rtc_notify_cpu_added(Notifier *notifier, void *data) -{ - RTCCPUHotplugArg *arg = container_of(notifier, RTCCPUHotplugArg, - cpu_added_notifier); - ISADevice *s = arg->rtc_state; - - /* increment the number of CPUs */ - rtc_set_memory(s, 0x5f, rtc_get_memory(s, 0x5f) + 1); -} - void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, - const char *boot_device, + const char *boot_device, MachineState *machine, ISADevice *floppy, BusState *idebus0, BusState *idebus1, ISADevice *s) { int val, nb, i; FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE }; static pc_cmos_init_late_arg arg; - static RTCCPUHotplugArg cpu_hotplug_cb; + PCMachineState *pc_machine = PC_MACHINE(machine); /* various important CMOS locations needed by PC/Bochs bios */ @@ -417,10 +402,14 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, /* set the number of CPU */ rtc_set_memory(s, 0x5f, smp_cpus - 1); - /* init CPU hotplug notifier */ - cpu_hotplug_cb.rtc_state = s; - cpu_hotplug_cb.cpu_added_notifier.notify = rtc_notify_cpu_added; - qemu_register_cpu_added_notifier(&cpu_hotplug_cb.cpu_added_notifier); + + object_property_add_link(OBJECT(machine), "rtc_state", + TYPE_ISA_DEVICE, + (Object **)&pc_machine->rtc, + object_property_allow_set_link, + OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort); + object_property_set_link(OBJECT(machine), OBJECT(s), + "rtc_state", &error_abort); if (set_boot_dev(s, boot_device)) { exit(1); @@ -1516,6 +1505,7 @@ static void pc_generic_machine_class_init(ObjectClass *oc, void *data) MachineClass *mc = MACHINE_CLASS(oc); QEMUMachine *qm = data; + mc->family = qm->family; mc->name = qm->name; mc->alias = qm->alias; mc->desc = qm->desc; @@ -1536,6 +1526,7 @@ static void pc_generic_machine_class_init(ObjectClass *oc, void *data) mc->is_default = qm->is_default; mc->default_machine_opts = qm->default_machine_opts; mc->default_boot_order = qm->default_boot_order; + mc->default_display = qm->default_display; mc->compat_props = qm->compat_props; mc->hw_version = qm->hw_version; } @@ -1617,11 +1608,42 @@ out: error_propagate(errp, local_err); } +static void pc_cpu_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + HotplugHandlerClass *hhc; + Error *local_err = NULL; + PCMachineState *pcms = PC_MACHINE(hotplug_dev); + + if (!dev->hotplugged) { + goto out; + } + + if (!pcms->acpi_dev) { + error_setg(&local_err, + "cpu hotplug is not enabled: missing acpi device"); + goto out; + } + + hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev); + hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); + if (local_err) { + goto out; + } + + /* increment the number of CPUs */ + rtc_set_memory(pcms->rtc, 0x5f, rtc_get_memory(pcms->rtc, 0x5f) + 1); +out: + error_propagate(errp, local_err); +} + static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { pc_dimm_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + pc_cpu_plug(hotplug_dev, dev, errp); } } @@ -1630,7 +1652,8 @@ static HotplugHandler *pc_get_hotpug_handler(MachineState *machine, { PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine); - if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || + object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { return HOTPLUG_HANDLER(machine); } diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 1cda5dd068..537bcf28da 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -63,6 +63,7 @@ static bool has_acpi_build = true; static int legacy_acpi_table_size; static bool smbios_defaults = true; static bool smbios_legacy_mode; +static bool smbios_uuid_encoded = 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. @@ -172,7 +173,7 @@ static void pc_init1(MachineState *machine, MachineClass *mc = MACHINE_GET_CLASS(machine); /* These values are guest ABI, do not change */ smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)", - mc->name, smbios_legacy_mode); + mc->name, smbios_legacy_mode, smbios_uuid_encoded); } /* allocate ram and load rom/bios */ @@ -266,7 +267,7 @@ static void pc_init1(MachineState *machine, } pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order, - floppy, idebus[0], idebus[1], rtc_state); + machine, floppy, idebus[0], idebus[1], rtc_state); if (pci_enabled && usb_enabled(false)) { pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci"); @@ -302,8 +303,14 @@ static void pc_init_pci(MachineState *machine) pc_init1(machine, 1, 1); } +static void pc_compat_2_1(MachineState *machine) +{ + smbios_uuid_encoded = false; +} + static void pc_compat_2_0(MachineState *machine) { + pc_compat_2_1(machine); /* This value depends on the actual DSDT and SSDT compiled into * the source QEMU; unfortunately it depends on the binary and * not on the machine type, so we cannot make pc-i440fx-1.7 work on @@ -368,6 +375,12 @@ static void pc_compat_1_2(MachineState *machine) x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI); } +static void pc_init_pci_2_1(MachineState *machine) +{ + pc_compat_2_1(machine); + pc_init_pci(machine); +} + static void pc_init_pci_2_0(MachineState *machine) { pc_compat_2_0(machine); @@ -451,12 +464,14 @@ static void pc_xen_hvm_init(MachineState *machine) #define PC_I440FX_MACHINE_OPTIONS \ PC_DEFAULT_MACHINE_OPTIONS, \ + .family = "pc_piix", \ .desc = "Standard PC (i440FX + PIIX, 1996)", \ .hot_add_cpu = pc_hot_add_cpu #define PC_I440FX_2_2_MACHINE_OPTIONS \ PC_I440FX_MACHINE_OPTIONS, \ - .default_machine_opts = "firmware=bios-256k.bin" + .default_machine_opts = "firmware=bios-256k.bin", \ + .default_display = "std" static QEMUMachine pc_i440fx_machine_v2_2 = { PC_I440FX_2_2_MACHINE_OPTIONS, @@ -466,14 +481,16 @@ static QEMUMachine pc_i440fx_machine_v2_2 = { .is_default = 1, }; -#define PC_I440FX_2_1_MACHINE_OPTIONS PC_I440FX_2_2_MACHINE_OPTIONS +#define PC_I440FX_2_1_MACHINE_OPTIONS \ + PC_I440FX_MACHINE_OPTIONS, \ + .default_machine_opts = "firmware=bios-256k.bin" static QEMUMachine pc_i440fx_machine_v2_1 = { PC_I440FX_2_1_MACHINE_OPTIONS, .name = "pc-i440fx-2.1", - .init = pc_init_pci, + .init = pc_init_pci_2_1, .compat_props = (GlobalProperty[]) { - PC_COMPAT_2_1, + HW_COMPAT_2_1, { /* end of list */ } }, }; @@ -661,7 +678,7 @@ static QEMUMachine pc_machine_v1_1 = { .property = "class",\ .value = stringify(PCI_CLASS_MEMORY_RAM),\ },{\ - .driver = "apic",\ + .driver = "apic-common",\ .property = "vapic",\ .value = "off",\ },{\ diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 4d9e3cd69d..296bdecc80 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -52,6 +52,7 @@ static bool has_acpi_build = true; static bool smbios_defaults = true; static bool smbios_legacy_mode; +static bool smbios_uuid_encoded = 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. @@ -163,7 +164,7 @@ static void pc_q35_init(MachineState *machine) MachineClass *mc = MACHINE_GET_CLASS(machine); /* These values are guest ABI, do not change */ smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", - mc->name, smbios_legacy_mode); + mc->name, smbios_legacy_mode, smbios_uuid_encoded); } /* allocate ram and load rom/bios */ @@ -271,7 +272,7 @@ static void pc_q35_init(MachineState *machine) 8, NULL, 0); pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order, - floppy, idebus[0], idebus[1], rtc_state); + machine, floppy, idebus[0], idebus[1], rtc_state); /* the rest devices to which pci devfn is automatically assigned */ pc_vga_init(isa_bus, host_bus); @@ -281,8 +282,14 @@ static void pc_q35_init(MachineState *machine) } } +static void pc_compat_2_1(MachineState *machine) +{ + smbios_uuid_encoded = false; +} + static void pc_compat_2_0(MachineState *machine) { + pc_compat_2_1(machine); smbios_legacy_mode = true; has_reserved_memory = false; pc_set_legacy_acpi_data_size(); @@ -316,6 +323,12 @@ static void pc_compat_1_4(MachineState *machine) x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); } +static void pc_q35_init_2_1(MachineState *machine) +{ + pc_compat_2_1(machine); + pc_q35_init(machine); +} + static void pc_q35_init_2_0(MachineState *machine) { pc_compat_2_0(machine); @@ -348,13 +361,15 @@ static void pc_q35_init_1_4(MachineState *machine) #define PC_Q35_MACHINE_OPTIONS \ PC_DEFAULT_MACHINE_OPTIONS, \ + .family = "pc_q35", \ .desc = "Standard PC (Q35 + ICH9, 2009)", \ .hot_add_cpu = pc_hot_add_cpu, \ .units_per_default_bus = 1 #define PC_Q35_2_2_MACHINE_OPTIONS \ PC_Q35_MACHINE_OPTIONS, \ - .default_machine_opts = "firmware=bios-256k.bin" + .default_machine_opts = "firmware=bios-256k.bin", \ + .default_display = "std" static QEMUMachine pc_q35_machine_v2_2 = { PC_Q35_2_2_MACHINE_OPTIONS, @@ -363,14 +378,16 @@ static QEMUMachine pc_q35_machine_v2_2 = { .init = pc_q35_init, }; -#define PC_Q35_2_1_MACHINE_OPTIONS PC_Q35_2_2_MACHINE_OPTIONS +#define PC_Q35_2_1_MACHINE_OPTIONS \ + PC_Q35_MACHINE_OPTIONS, \ + .default_machine_opts = "firmware=bios-256k.bin" static QEMUMachine pc_q35_machine_v2_1 = { PC_Q35_2_1_MACHINE_OPTIONS, .name = "pc-q35-2.1", - .init = pc_q35_init, + .init = pc_q35_init_2_1, .compat_props = (GlobalProperty[]) { - PC_COMPAT_2_1, + HW_COMPAT_2_1, { /* end of list */ } }, }; diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index e3fa1b2fc1..8a7ad48921 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -48,6 +48,7 @@ struct smbios_table { static uint8_t *smbios_entries; static size_t smbios_entries_len; static bool smbios_legacy = true; +static bool smbios_uuid_encoded = true; /* end: legacy structures & constants for <= 2.0 machines */ @@ -391,6 +392,11 @@ static void smbios_build_type_1_fields(void) smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str), type1.family); if (qemu_uuid_set) { + /* We don't encode the UUID in the "wire format" here because this + * function is for legacy mode and needs to keep the guest ABI, and + * because we don't know what's the SMBIOS version advertised by the + * BIOS. + */ smbios_add_field(1, offsetof(struct smbios_type_1, uuid), qemu_uuid, 16); } @@ -523,6 +529,19 @@ static void smbios_build_type_0_table(void) SMBIOS_BUILD_TABLE_POST; } +/* Encode UUID from the big endian encoding described on RFC4122 to the wire + * format specified by SMBIOS version 2.6. + */ +static void smbios_encode_uuid(struct smbios_uuid *uuid, const uint8_t *buf) +{ + memcpy(uuid, buf, 16); + if (smbios_uuid_encoded) { + uuid->time_low = bswap32(uuid->time_low); + uuid->time_mid = bswap16(uuid->time_mid); + uuid->time_hi_and_version = bswap16(uuid->time_hi_and_version); + } +} + static void smbios_build_type_1_table(void) { SMBIOS_BUILD_TABLE_PRE(1, 0x100, true); /* required */ @@ -532,9 +551,9 @@ static void smbios_build_type_1_table(void) SMBIOS_TABLE_SET_STR(1, version_str, type1.version); SMBIOS_TABLE_SET_STR(1, serial_number_str, type1.serial); if (qemu_uuid_set) { - memcpy(t->uuid, qemu_uuid, 16); + smbios_encode_uuid(&t->uuid, qemu_uuid); } else { - memset(t->uuid, 0, 16); + memset(&t->uuid, 0, 16); } t->wake_up_type = 0x06; /* power switch */ SMBIOS_TABLE_SET_STR(1, sku_number_str, type1.sku); @@ -746,10 +765,12 @@ void smbios_set_cpuid(uint32_t version, uint32_t features) } void smbios_set_defaults(const char *manufacturer, const char *product, - const char *version, bool legacy_mode) + const char *version, bool legacy_mode, + bool uuid_encoded) { smbios_have_defaults = true; smbios_legacy = legacy_mode; + smbios_uuid_encoded = uuid_encoded; /* drop unwanted version of command-line file blob(s) */ if (smbios_legacy) { @@ -821,7 +842,7 @@ void smbios_get_tables(uint8_t **tables, size_t *tables_len, smbios_build_type_2_table(); smbios_build_type_3_table(); - smbios_smp_sockets = smp_cpus / (smp_cores * smp_threads); + smbios_smp_sockets = DIV_ROUND_UP(smp_cpus, smp_cores * smp_threads); assert(smbios_smp_sockets >= 1); for (i = 0; i < smbios_smp_sockets; i++) { diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 6ce75aa940..371699cf86 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1776,7 +1776,12 @@ static int pci_qdev_init(DeviceState *qdev) pci_dev->romfile = g_strdup(pc->romfile); is_default_rom = true; } - pci_add_option_rom(pci_dev, is_default_rom); + + rc = pci_add_option_rom(pci_dev, is_default_rom); + if (rc != 0) { + pci_unregister_device(DEVICE(pci_dev)); + return rc; + } return 0; } @@ -1937,6 +1942,15 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) * for 0.11 compatibility. */ int class = pci_get_word(pdev->config + PCI_CLASS_DEVICE); + + /* + * Hot-plugged devices can't use the option ROM + * if the rom bar is disabled. + */ + if (DEVICE(pdev)->hotplugged) { + return -1; + } + if (class == 0x0300) { rom_add_vga(pdev->romfile); } else { diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index b64a004631..58455bd854 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -529,7 +529,7 @@ bool pcie_cap_is_arifwd_enabled(const PCIDevice *dev) } /************************************************************************** - * pci express extended capability allocation functions + * pci express extended capability list management functions * uint16_t ext_cap_id (16 bit) * uint8_t cap_ver (4 bit) * uint16_t cap_offset (12 bit) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 45764a7032..0a2bfe6565 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -57,6 +57,8 @@ #include "trace.h" #include "hw/nmi.h" +#include "hw/compat.h" + #include <libfdt.h> /* SLOF memory layout: @@ -1689,10 +1691,15 @@ static const TypeInfo spapr_machine_info = { static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + static GlobalProperty compat_props[] = { + HW_COMPAT_2_1, + { /* end of list */ } + }; mc->name = "pseries-2.1"; mc->desc = "pSeries Logical Partition (PAPR compliant) v2.1"; mc->is_default = 0; + mc->compat_props = compat_props; } static const TypeInfo spapr_machine_2_1_info = { diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 372706a234..61f6d83686 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -352,10 +352,6 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, goto out; } - if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { - vring_avail_event(&vring->vr) = vring->vr.avail->idx; - } - i = head; do { if (unlikely(i >= num)) { @@ -392,6 +388,10 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, /* On success, increment avail index. */ vring->last_avail_idx++; + if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { + vring_avail_event(&vring->vr) = vring->last_avail_idx; + } + return head; out: diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 4e88d9c5e9..aefe0bbaaf 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -226,7 +226,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request, msg.memory.regions[fd_num].memory_size = reg->memory_size; msg.memory.regions[fd_num].guest_phys_addr = reg->guest_phys_addr; msg.memory.regions[fd_num].mmap_offset = reg->userspace_addr - - (uintptr_t) qemu_get_ram_block_host_ptr(reg->guest_phys_addr); + (uintptr_t) qemu_get_ram_block_host_ptr(ram_addr); assert(fd_num < VHOST_MEMORY_MAX_NREGIONS); fds[fd_num++] = fd; } diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index e490adeb80..dde1d73b56 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -86,9 +86,6 @@ * 12 is historical, and due to x86 page size. */ #define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 -/* Flags track per-device state like workarounds for quirks in older guests. */ -#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG (1 << 0) - static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, VirtIOPCIProxy *dev); @@ -323,14 +320,6 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) proxy->pci_dev.config[PCI_COMMAND] | PCI_COMMAND_MASTER, 1); } - - /* Linux before 2.6.34 sets the device as OK without enabling - the PCI device bus master bit. In this case we need to disable - some safety checks. */ - if ((val & VIRTIO_CONFIG_S_DRIVER_OK) && - !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { - proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG; - } break; case VIRTIO_MSI_CONFIG_VECTOR: msix_vector_unuse(&proxy->pci_dev, vdev->config_vector); @@ -483,8 +472,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, pci_default_write_config(pci_dev, address, val, len); if (range_covers_byte(address, len, PCI_COMMAND) && - !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) && - !(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) { + !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { virtio_pci_stop_ioeventfd(proxy); virtio_set_status(vdev, vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK); } @@ -895,11 +883,15 @@ static void virtio_pci_vmstate_change(DeviceState *d, bool running) VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); if (running) { - /* Try to find out if the guest has bus master disabled, but is - in ready state. Then we have a buggy guest OS. */ - if ((vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) && + /* Old QEMU versions did not set bus master enable on status write. + * Detect DRIVER set and enable it. + */ + if ((proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION) && + (vdev->status & VIRTIO_CONFIG_S_DRIVER) && !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { - proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG; + pci_default_write_config(&proxy->pci_dev, PCI_COMMAND, + proxy->pci_dev.config[PCI_COMMAND] | + PCI_COMMAND_MASTER, 1); } virtio_pci_start_ioeventfd(proxy); } else { @@ -1040,10 +1032,11 @@ static void virtio_pci_reset(DeviceState *qdev) virtio_pci_stop_ioeventfd(proxy); virtio_bus_reset(bus); msix_unuse_all_vectors(&proxy->pci_dev); - proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG; } static Property virtio_pci_properties[] = { + DEFINE_PROP_BIT("virtio-pci-bus-master-bug-migration", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT, false), DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 1cea157a47..8873b6d138 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -53,6 +53,11 @@ typedef struct VirtioBusClass VirtioPCIBusClass; #define VIRTIO_PCI_BUS_CLASS(klass) \ OBJECT_CLASS_CHECK(VirtioPCIBusClass, klass, TYPE_VIRTIO_PCI_BUS) +/* Need to activate work-arounds for buggy guests at vmstate load. */ +#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT 0 +#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION \ + (1 << VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT) + /* Performance improves when virtqueue kick processing is decoupled from the * vcpu thread using ioeventfd for some devices. */ #define VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT 1 diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 2c236bf271..013979a6b8 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -469,7 +469,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) i = head = virtqueue_get_head(vq, vq->last_avail_idx++); if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { - vring_avail_event(vq, vring_avail_idx(vq)); + vring_avail_event(vq, vq->last_avail_idx); } if (vring_desc_flags(vdev, desc_pa, i) & VRING_DESC_F_INDIRECT) { |