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/i386 | |
parent | 47e8acb45feddcbc340583781b53935459330db2 (diff) | |
parent | d43f0d641e366251bd9c63005241775f672bf3ec (diff) |
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/i386')
-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 |
5 files changed, 134 insertions, 50 deletions
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++) { |