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>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJUV65JAAoJECgfDbjSjVRpqzgIAJJDaU95xdtl/snSJVbSGsgR
 2YW8mC8pjkZnV8fbu7F1vOTJSpAhj0eeXaDTqtbBhgAqBlqQ5tWAT9xDnUIlBlHN
 GVTWzWaifVOGMj087Ovvy9+4NyfsuvTlf3aOjvLfqlaDqI5dbZQAyIdHNFyV7Qy9
 txgAcERp+caZ4rN8XgAv82KV1JGj8PXermTgLJ+DcqYxhwWm66eEviQ+f+F5YImJ
 CJQ6HFPXjclxHCuyKBL334SIwq8IfYyUUkIsGgKCNuHPUud7r2rqsIlRfeZBwLf9
 igUgf4iPQL5TNVq9qwQmnTK6ddHTqHZmGyu902WxHK/N0EDq4dLw8diqFhZxo9Y=
 =f7Rb
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2014-11-03 22:51:07 +00:00
commit 949ca9e479
28 changed files with 334 additions and 173 deletions

View File

@ -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); CPUClass *k = CPU_GET_CLASS(cpu);
int64_t cpu_id; int64_t cpu_id;
*gpe->sts = *gpe->sts | ACPI_CPU_HOTPLUG_STATUS; cpu_id = k->get_arch_id(cpu);
cpu_id = k->get_arch_id(CPU(cpu)); if ((cpu_id / 8) >= ACPI_GPE_PROC_LEN) {
g_assert((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)); g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
} }
void AcpiCpuHotplug_init(MemoryRegion *parent, Object *owner, void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
AcpiCpuHotplug *gpe_cpu, uint16_t base) 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; CPUState *cpu;
CPU_FOREACH(cpu) { CPU_FOREACH(cpu) {
CPUClass *cc = CPU_GET_CLASS(cpu); acpi_set_cpu_present_bit(gpe_cpu, cpu, &error_abort);
int64_t id = cc->get_arch_id(cpu);
g_assert((id / 8) < ACPI_GPE_PROC_LEN);
gpe_cpu->sts[id / 8] |= (1 << (id % 8));
} }
memory_region_init_io(&gpe_cpu->io, owner, &AcpiCpuHotplug_ops, memory_region_init_io(&gpe_cpu->io, owner, &AcpiCpuHotplug_ops,
gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN); gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);

View File

@ -209,15 +209,6 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
acpi_pm1_evt_power_down(&pm->acpi_regs); acpi_pm1_evt_power_down(&pm->acpi_regs);
} }
static void ich9_cpu_added_req(Notifier *n, void *opaque)
{
ICH9LPCPMRegs *pm = container_of(n, ICH9LPCPMRegs, cpu_added_notifier);
assert(pm != NULL);
AcpiCpuHotplug_add(&pm->acpi_regs.gpe, &pm->gpe_cpu, CPU(opaque));
acpi_update_sci(&pm->acpi_regs, pm->irq);
}
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
qemu_irq sci_irq) qemu_irq sci_irq)
{ {
@ -244,10 +235,8 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
pm->powerdown_notifier.notify = pm_powerdown_req; pm->powerdown_notifier.notify = pm_powerdown_req;
qemu_register_powerdown_notifier(&pm->powerdown_notifier); qemu_register_powerdown_notifier(&pm->powerdown_notifier);
AcpiCpuHotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci), acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
&pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE); &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);
if (pm->acpi_memory_hotplug.is_enabled) { if (pm->acpi_memory_hotplug.is_enabled) {
acpi_memory_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci), 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)) { object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
acpi_memory_plug_cb(&pm->acpi_regs, pm->irq, &pm->acpi_memory_hotplug, acpi_memory_plug_cb(&pm->acpi_regs, pm->irq, &pm->acpi_memory_hotplug,
dev, errp); 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 { } else {
error_setg(errp, "acpi: device plug request for not supported device" error_setg(errp, "acpi: device plug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev))); " type: %s", object_get_typename(OBJECT(dev)));

View File

@ -83,7 +83,6 @@ typedef struct PIIX4PMState {
uint8_t s4_val; uint8_t s4_val;
AcpiCpuHotplug gpe_cpu; AcpiCpuHotplug gpe_cpu;
Notifier cpu_added_notifier;
MemHotplugState acpi_memory_hotplug; MemHotplugState acpi_memory_hotplug;
} PIIX4PMState; } PIIX4PMState;
@ -348,6 +347,8 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev,
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev, acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
errp); errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
acpi_cpu_plug_cb(&s->ar, s->irq, &s->gpe_cpu, dev, errp);
} else { } else {
error_setg(errp, "acpi: device plug request for not supported device" error_setg(errp, "acpi: device plug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev))); " type: %s", object_get_typename(OBJECT(dev)));
@ -544,15 +545,6 @@ static const MemoryRegionOps piix4_gpe_ops = {
.endianness = DEVICE_LITTLE_ENDIAN, .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, static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
PCIBus *bus, PIIX4PMState *s) 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, acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent,
s->use_acpi_pci_hotplug); s->use_acpi_pci_hotplug);
AcpiCpuHotplug_init(parent, OBJECT(s), &s->gpe_cpu, acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu,
PIIX4_CPU_HOTPLUG_IO_BASE); PIIX4_CPU_HOTPLUG_IO_BASE);
s->cpu_added_notifier.notify = piix4_cpu_added_req;
qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
if (s->acpi_memory_hotplug.is_enabled) { if (s->acpi_memory_hotplug.is_enabled) {
acpi_memory_hotplug_init(parent, OBJECT(s), &s->acpi_memory_hotplug); acpi_memory_hotplug_init(parent, OBJECT(s), &s->acpi_memory_hotplug);

View File

@ -249,6 +249,7 @@ static void acpi_get_pci_info(PcPciInfo *info)
#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables" #define ACPI_BUILD_TABLE_FILE "etc/acpi/tables"
#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp" #define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp"
#define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log"
static void static void
build_header(GArray *linker, GArray *table_data, build_header(GArray *linker, GArray *table_data,
@ -1214,27 +1215,28 @@ build_hpet(GArray *table_data, GArray *linker)
} }
static void 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); 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(tcpalog);
uint64_t log_area_start_address = acpi_data_len(table_data);
tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT); 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_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
tcpa->log_area_start_address = cpu_to_le64(log_area_start_address); 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 */ /* log area start address to be filled by Guest linker */
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, 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, table_data, &tcpa->log_area_start_address,
sizeof(tcpa->log_area_start_address)); sizeof(tcpa->log_area_start_address));
build_header(linker, table_data, build_header(linker, table_data,
(void *)tcpa, "TCPA", sizeof(*tcpa), 2); (void *)tcpa, "TCPA", sizeof(*tcpa), 2);
/* now only get the log area and with that modify table_data */ acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
acpi_data_push(table_data, TPM_LOG_AREA_MINIMUM_SIZE);
} }
static void static void
@ -1485,6 +1487,7 @@ typedef
struct AcpiBuildTables { struct AcpiBuildTables {
GArray *table_data; GArray *table_data;
GArray *rsdp; GArray *rsdp;
GArray *tcpalog;
GArray *linker; GArray *linker;
} AcpiBuildTables; } AcpiBuildTables;
@ -1492,17 +1495,17 @@ static inline void acpi_build_tables_init(AcpiBuildTables *tables)
{ {
tables->rsdp = g_array_new(false, true /* clear */, 1); tables->rsdp = g_array_new(false, true /* clear */, 1);
tables->table_data = 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(); tables->linker = bios_linker_loader_init();
} }
static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre) static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
{ {
void *linker_data = bios_linker_loader_cleanup(tables->linker); 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->rsdp, mfre);
g_array_free(tables->table_data, mfre); g_array_free(tables->table_data, true);
g_array_free(tables->tcpalog, mfre);
} }
typedef typedef
@ -1612,7 +1615,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
} }
if (misc.has_tpm) { if (misc.has_tpm) {
acpi_add_table(table_offsets, tables->table_data); 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); acpi_add_table(table_offsets, tables->table_data);
build_tpm_ssdt(tables->table_data, tables->linker); 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"); 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 * RSDP is small so it's easy to keep it immutable, no need to
* bother with ROM blobs. * bother with ROM blobs.

View File

@ -355,30 +355,15 @@ static void pc_cmos_init_late(void *opaque)
qemu_unregister_reset(pc_cmos_init_late, 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, 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 *floppy, BusState *idebus0, BusState *idebus1,
ISADevice *s) ISADevice *s)
{ {
int val, nb, i; int val, nb, i;
FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE }; FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
static pc_cmos_init_late_arg arg; 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 */ /* 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 */ /* set the number of CPU */
rtc_set_memory(s, 0x5f, smp_cpus - 1); rtc_set_memory(s, 0x5f, smp_cpus - 1);
/* init CPU hotplug notifier */
cpu_hotplug_cb.rtc_state = s; object_property_add_link(OBJECT(machine), "rtc_state",
cpu_hotplug_cb.cpu_added_notifier.notify = rtc_notify_cpu_added; TYPE_ISA_DEVICE,
qemu_register_cpu_added_notifier(&cpu_hotplug_cb.cpu_added_notifier); (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)) { if (set_boot_dev(s, boot_device)) {
exit(1); exit(1);
@ -1516,6 +1505,7 @@ static void pc_generic_machine_class_init(ObjectClass *oc, void *data)
MachineClass *mc = MACHINE_CLASS(oc); MachineClass *mc = MACHINE_CLASS(oc);
QEMUMachine *qm = data; QEMUMachine *qm = data;
mc->family = qm->family;
mc->name = qm->name; mc->name = qm->name;
mc->alias = qm->alias; mc->alias = qm->alias;
mc->desc = qm->desc; 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->is_default = qm->is_default;
mc->default_machine_opts = qm->default_machine_opts; mc->default_machine_opts = qm->default_machine_opts;
mc->default_boot_order = qm->default_boot_order; mc->default_boot_order = qm->default_boot_order;
mc->default_display = qm->default_display;
mc->compat_props = qm->compat_props; mc->compat_props = qm->compat_props;
mc->hw_version = qm->hw_version; mc->hw_version = qm->hw_version;
} }
@ -1617,11 +1608,42 @@ out:
error_propagate(errp, local_err); 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, static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp) DeviceState *dev, Error **errp)
{ {
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
pc_dimm_plug(hotplug_dev, dev, errp); 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); 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); return HOTPLUG_HANDLER(machine);
} }

View File

@ -63,6 +63,7 @@ static bool has_acpi_build = true;
static int legacy_acpi_table_size; static int legacy_acpi_table_size;
static bool smbios_defaults = true; static bool smbios_defaults = true;
static bool smbios_legacy_mode; static bool smbios_legacy_mode;
static bool smbios_uuid_encoded = true;
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to /* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte * host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
* pages in the host. * pages in the host.
@ -172,7 +173,7 @@ static void pc_init1(MachineState *machine,
MachineClass *mc = MACHINE_GET_CLASS(machine); MachineClass *mc = MACHINE_GET_CLASS(machine);
/* These values are guest ABI, do not change */ /* These values are guest ABI, do not change */
smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)", 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 */ /* 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, 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)) { if (pci_enabled && usb_enabled(false)) {
pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci"); 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); 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) static void pc_compat_2_0(MachineState *machine)
{ {
pc_compat_2_1(machine);
/* This value depends on the actual DSDT and SSDT compiled into /* This value depends on the actual DSDT and SSDT compiled into
* the source QEMU; unfortunately it depends on the binary and * 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 * 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); 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) static void pc_init_pci_2_0(MachineState *machine)
{ {
pc_compat_2_0(machine); pc_compat_2_0(machine);
@ -451,12 +464,14 @@ static void pc_xen_hvm_init(MachineState *machine)
#define PC_I440FX_MACHINE_OPTIONS \ #define PC_I440FX_MACHINE_OPTIONS \
PC_DEFAULT_MACHINE_OPTIONS, \ PC_DEFAULT_MACHINE_OPTIONS, \
.family = "pc_piix", \
.desc = "Standard PC (i440FX + PIIX, 1996)", \ .desc = "Standard PC (i440FX + PIIX, 1996)", \
.hot_add_cpu = pc_hot_add_cpu .hot_add_cpu = pc_hot_add_cpu
#define PC_I440FX_2_2_MACHINE_OPTIONS \ #define PC_I440FX_2_2_MACHINE_OPTIONS \
PC_I440FX_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 = { static QEMUMachine pc_i440fx_machine_v2_2 = {
PC_I440FX_2_2_MACHINE_OPTIONS, PC_I440FX_2_2_MACHINE_OPTIONS,
@ -466,14 +481,16 @@ static QEMUMachine pc_i440fx_machine_v2_2 = {
.is_default = 1, .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 = { static QEMUMachine pc_i440fx_machine_v2_1 = {
PC_I440FX_2_1_MACHINE_OPTIONS, PC_I440FX_2_1_MACHINE_OPTIONS,
.name = "pc-i440fx-2.1", .name = "pc-i440fx-2.1",
.init = pc_init_pci, .init = pc_init_pci_2_1,
.compat_props = (GlobalProperty[]) { .compat_props = (GlobalProperty[]) {
PC_COMPAT_2_1, HW_COMPAT_2_1,
{ /* end of list */ } { /* end of list */ }
}, },
}; };
@ -661,7 +678,7 @@ static QEMUMachine pc_machine_v1_1 = {
.property = "class",\ .property = "class",\
.value = stringify(PCI_CLASS_MEMORY_RAM),\ .value = stringify(PCI_CLASS_MEMORY_RAM),\
},{\ },{\
.driver = "apic",\ .driver = "apic-common",\
.property = "vapic",\ .property = "vapic",\
.value = "off",\ .value = "off",\
},{\ },{\

View File

@ -52,6 +52,7 @@
static bool has_acpi_build = true; static bool has_acpi_build = true;
static bool smbios_defaults = true; static bool smbios_defaults = true;
static bool smbios_legacy_mode; static bool smbios_legacy_mode;
static bool smbios_uuid_encoded = true;
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to /* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte * host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
* pages in the host. * pages in the host.
@ -163,7 +164,7 @@ static void pc_q35_init(MachineState *machine)
MachineClass *mc = MACHINE_GET_CLASS(machine); MachineClass *mc = MACHINE_GET_CLASS(machine);
/* These values are guest ABI, do not change */ /* These values are guest ABI, do not change */
smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", 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 */ /* allocate ram and load rom/bios */
@ -271,7 +272,7 @@ static void pc_q35_init(MachineState *machine)
8, NULL, 0); 8, NULL, 0);
pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order, 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 */ /* the rest devices to which pci devfn is automatically assigned */
pc_vga_init(isa_bus, host_bus); 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) static void pc_compat_2_0(MachineState *machine)
{ {
pc_compat_2_1(machine);
smbios_legacy_mode = true; smbios_legacy_mode = true;
has_reserved_memory = false; has_reserved_memory = false;
pc_set_legacy_acpi_data_size(); 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); 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) static void pc_q35_init_2_0(MachineState *machine)
{ {
pc_compat_2_0(machine); pc_compat_2_0(machine);
@ -348,13 +361,15 @@ static void pc_q35_init_1_4(MachineState *machine)
#define PC_Q35_MACHINE_OPTIONS \ #define PC_Q35_MACHINE_OPTIONS \
PC_DEFAULT_MACHINE_OPTIONS, \ PC_DEFAULT_MACHINE_OPTIONS, \
.family = "pc_q35", \
.desc = "Standard PC (Q35 + ICH9, 2009)", \ .desc = "Standard PC (Q35 + ICH9, 2009)", \
.hot_add_cpu = pc_hot_add_cpu, \ .hot_add_cpu = pc_hot_add_cpu, \
.units_per_default_bus = 1 .units_per_default_bus = 1
#define PC_Q35_2_2_MACHINE_OPTIONS \ #define PC_Q35_2_2_MACHINE_OPTIONS \
PC_Q35_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 = { static QEMUMachine pc_q35_machine_v2_2 = {
PC_Q35_2_2_MACHINE_OPTIONS, PC_Q35_2_2_MACHINE_OPTIONS,
@ -363,14 +378,16 @@ static QEMUMachine pc_q35_machine_v2_2 = {
.init = pc_q35_init, .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 = { static QEMUMachine pc_q35_machine_v2_1 = {
PC_Q35_2_1_MACHINE_OPTIONS, PC_Q35_2_1_MACHINE_OPTIONS,
.name = "pc-q35-2.1", .name = "pc-q35-2.1",
.init = pc_q35_init, .init = pc_q35_init_2_1,
.compat_props = (GlobalProperty[]) { .compat_props = (GlobalProperty[]) {
PC_COMPAT_2_1, HW_COMPAT_2_1,
{ /* end of list */ } { /* end of list */ }
}, },
}; };

View File

@ -48,6 +48,7 @@ struct smbios_table {
static uint8_t *smbios_entries; static uint8_t *smbios_entries;
static size_t smbios_entries_len; static size_t smbios_entries_len;
static bool smbios_legacy = true; static bool smbios_legacy = true;
static bool smbios_uuid_encoded = true;
/* end: legacy structures & constants for <= 2.0 machines */ /* 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), smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str),
type1.family); type1.family);
if (qemu_uuid_set) { 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), smbios_add_field(1, offsetof(struct smbios_type_1, uuid),
qemu_uuid, 16); qemu_uuid, 16);
} }
@ -523,6 +529,19 @@ static void smbios_build_type_0_table(void)
SMBIOS_BUILD_TABLE_POST; 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) static void smbios_build_type_1_table(void)
{ {
SMBIOS_BUILD_TABLE_PRE(1, 0x100, true); /* required */ 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, version_str, type1.version);
SMBIOS_TABLE_SET_STR(1, serial_number_str, type1.serial); SMBIOS_TABLE_SET_STR(1, serial_number_str, type1.serial);
if (qemu_uuid_set) { if (qemu_uuid_set) {
memcpy(t->uuid, qemu_uuid, 16); smbios_encode_uuid(&t->uuid, qemu_uuid);
} else { } else {
memset(t->uuid, 0, 16); memset(&t->uuid, 0, 16);
} }
t->wake_up_type = 0x06; /* power switch */ t->wake_up_type = 0x06; /* power switch */
SMBIOS_TABLE_SET_STR(1, sku_number_str, type1.sku); 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, 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_have_defaults = true;
smbios_legacy = legacy_mode; smbios_legacy = legacy_mode;
smbios_uuid_encoded = uuid_encoded;
/* drop unwanted version of command-line file blob(s) */ /* drop unwanted version of command-line file blob(s) */
if (smbios_legacy) { 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_2_table();
smbios_build_type_3_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); assert(smbios_smp_sockets >= 1);
for (i = 0; i < smbios_smp_sockets; i++) { for (i = 0; i < smbios_smp_sockets; i++) {

View File

@ -1776,7 +1776,12 @@ static int pci_qdev_init(DeviceState *qdev)
pci_dev->romfile = g_strdup(pc->romfile); pci_dev->romfile = g_strdup(pc->romfile);
is_default_rom = true; 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; return 0;
} }
@ -1937,6 +1942,15 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
* for 0.11 compatibility. * for 0.11 compatibility.
*/ */
int class = pci_get_word(pdev->config + PCI_CLASS_DEVICE); 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) { if (class == 0x0300) {
rom_add_vga(pdev->romfile); rom_add_vga(pdev->romfile);
} else { } else {

View File

@ -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) * uint16_t ext_cap_id (16 bit)
* uint8_t cap_ver (4 bit) * uint8_t cap_ver (4 bit)
* uint16_t cap_offset (12 bit) * uint16_t cap_offset (12 bit)

View File

@ -57,6 +57,8 @@
#include "trace.h" #include "trace.h"
#include "hw/nmi.h" #include "hw/nmi.h"
#include "hw/compat.h"
#include <libfdt.h> #include <libfdt.h>
/* SLOF memory layout: /* 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) static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data)
{ {
MachineClass *mc = MACHINE_CLASS(oc); MachineClass *mc = MACHINE_CLASS(oc);
static GlobalProperty compat_props[] = {
HW_COMPAT_2_1,
{ /* end of list */ }
};
mc->name = "pseries-2.1"; mc->name = "pseries-2.1";
mc->desc = "pSeries Logical Partition (PAPR compliant) v2.1"; mc->desc = "pSeries Logical Partition (PAPR compliant) v2.1";
mc->is_default = 0; mc->is_default = 0;
mc->compat_props = compat_props;
} }
static const TypeInfo spapr_machine_2_1_info = { static const TypeInfo spapr_machine_2_1_info = {

View File

@ -352,10 +352,6 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
goto out; goto out;
} }
if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
vring_avail_event(&vring->vr) = vring->vr.avail->idx;
}
i = head; i = head;
do { do {
if (unlikely(i >= num)) { if (unlikely(i >= num)) {
@ -392,6 +388,10 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
/* On success, increment avail index. */ /* On success, increment avail index. */
vring->last_avail_idx++; 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; return head;
out: out:

View File

@ -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].memory_size = reg->memory_size;
msg.memory.regions[fd_num].guest_phys_addr = reg->guest_phys_addr; msg.memory.regions[fd_num].guest_phys_addr = reg->guest_phys_addr;
msg.memory.regions[fd_num].mmap_offset = reg->userspace_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); assert(fd_num < VHOST_MEMORY_MAX_NREGIONS);
fds[fd_num++] = fd; fds[fd_num++] = fd;
} }

View File

@ -86,9 +86,6 @@
* 12 is historical, and due to x86 page size. */ * 12 is historical, and due to x86 page size. */
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 #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, static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
VirtIOPCIProxy *dev); 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] | proxy->pci_dev.config[PCI_COMMAND] |
PCI_COMMAND_MASTER, 1); 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; break;
case VIRTIO_MSI_CONFIG_VECTOR: case VIRTIO_MSI_CONFIG_VECTOR:
msix_vector_unuse(&proxy->pci_dev, vdev->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); pci_default_write_config(pci_dev, address, val, len);
if (range_covers_byte(address, len, PCI_COMMAND) && if (range_covers_byte(address, len, PCI_COMMAND) &&
!(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) && !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
virtio_pci_stop_ioeventfd(proxy); virtio_pci_stop_ioeventfd(proxy);
virtio_set_status(vdev, vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK); 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); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
if (running) { if (running) {
/* Try to find out if the guest has bus master disabled, but is /* Old QEMU versions did not set bus master enable on status write.
in ready state. Then we have a buggy guest OS. */ * Detect DRIVER set and enable it.
if ((vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) && */
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->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); virtio_pci_start_ioeventfd(proxy);
} else { } else {
@ -1040,10 +1032,11 @@ static void virtio_pci_reset(DeviceState *qdev)
virtio_pci_stop_ioeventfd(proxy); virtio_pci_stop_ioeventfd(proxy);
virtio_bus_reset(bus); virtio_bus_reset(bus);
msix_unuse_all_vectors(&proxy->pci_dev); msix_unuse_all_vectors(&proxy->pci_dev);
proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
} }
static Property virtio_pci_properties[] = { 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_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}; };

View File

@ -53,6 +53,11 @@ typedef struct VirtioBusClass VirtioPCIBusClass;
#define VIRTIO_PCI_BUS_CLASS(klass) \ #define VIRTIO_PCI_BUS_CLASS(klass) \
OBJECT_CLASS_CHECK(VirtioPCIBusClass, klass, TYPE_VIRTIO_PCI_BUS) 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 /* Performance improves when virtqueue kick processing is decoupled from the
* vcpu thread using ioeventfd for some devices. */ * vcpu thread using ioeventfd for some devices. */
#define VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT 1 #define VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT 1

View File

@ -469,7 +469,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
i = head = virtqueue_get_head(vq, vq->last_avail_idx++); i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_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) { if (vring_desc_flags(vdev, desc_pa, i) & VRING_DESC_F_INDIRECT) {

View File

@ -20,8 +20,9 @@ typedef struct AcpiCpuHotplug {
uint8_t sts[ACPI_GPE_PROC_LEN]; uint8_t sts[ACPI_GPE_PROC_LEN];
} AcpiCpuHotplug; } AcpiCpuHotplug;
void AcpiCpuHotplug_add(ACPIGPE *gpe, AcpiCpuHotplug *g, CPUState *cpu); void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
AcpiCpuHotplug *g, DeviceState *dev, Error **errp);
void AcpiCpuHotplug_init(MemoryRegion *parent, Object *owner, void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
AcpiCpuHotplug *gpe_cpu, uint16_t base); AcpiCpuHotplug *gpe_cpu, uint16_t base);
#endif #endif

View File

@ -47,7 +47,6 @@ typedef struct ICH9LPCPMRegs {
Notifier powerdown_notifier; Notifier powerdown_notifier;
AcpiCpuHotplug gpe_cpu; AcpiCpuHotplug gpe_cpu;
Notifier cpu_added_notifier;
MemHotplugState acpi_memory_hotplug; MemHotplugState acpi_memory_hotplug;
} ICH9LPCPMRegs; } ICH9LPCPMRegs;

View File

@ -19,6 +19,7 @@ typedef void QEMUMachineHotAddCPUFunc(const int64_t id, Error **errp);
typedef int QEMUMachineGetKvmtypeFunc(const char *arg); typedef int QEMUMachineGetKvmtypeFunc(const char *arg);
struct QEMUMachine { struct QEMUMachine {
const char *family; /* NULL iff @name identifies a standalone machtype */
const char *name; const char *name;
const char *alias; const char *alias;
const char *desc; const char *desc;
@ -39,6 +40,7 @@ struct QEMUMachine {
int is_default; int is_default;
const char *default_machine_opts; const char *default_machine_opts;
const char *default_boot_order; const char *default_boot_order;
const char *default_display;
GlobalProperty *compat_props; GlobalProperty *compat_props;
const char *hw_version; const char *hw_version;
}; };
@ -76,6 +78,7 @@ struct MachineClass {
ObjectClass parent_class; ObjectClass parent_class;
/*< public >*/ /*< public >*/
const char *family; /* NULL iff @name identifies a standalone machtype */
const char *name; const char *name;
const char *alias; const char *alias;
const char *desc; const char *desc;
@ -98,6 +101,7 @@ struct MachineClass {
int is_default; int is_default;
const char *default_machine_opts; const char *default_machine_opts;
const char *default_boot_order; const char *default_boot_order;
const char *default_display;
GlobalProperty *compat_props; GlobalProperty *compat_props;
const char *hw_version; const char *hw_version;

35
include/hw/compat.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef HW_COMPAT_H
#define HW_COMPAT_H
#define HW_COMPAT_2_1 \
{\
.driver = "intel-hda",\
.property = "old_msi_addr",\
.value = "on",\
},{\
.driver = "VGA",\
.property = "qemu-extended-regs",\
.value = "off",\
},{\
.driver = "secondary-vga",\
.property = "qemu-extended-regs",\
.value = "off",\
},{\
.driver = "virtio-scsi-pci",\
.property = "any_layout",\
.value = "off",\
},{\
.driver = "usb-mouse",\
.property = "usb_version",\
.value = stringify(1),\
},{\
.driver = "usb-kbd",\
.property = "usb_version",\
.value = stringify(1),\
},{\
.driver = "virtio-pci",\
.property = "virtio-pci-bus-master-bug-migration",\
.value = "on",\
}
#endif /* HW_COMPAT_H */

View File

@ -37,7 +37,7 @@
#define VTD_PCI_DEVFN_MAX 256 #define VTD_PCI_DEVFN_MAX 256
#define VTD_PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define VTD_PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define VTD_PCI_FUNC(devfn) ((devfn) & 0x07) #define VTD_PCI_FUNC(devfn) ((devfn) & 0x07)
#define VTD_SID_TO_BUS(sid) (((sid) >> 8) && 0xff) #define VTD_SID_TO_BUS(sid) (((sid) >> 8) & 0xff)
#define VTD_SID_TO_DEVFN(sid) ((sid) & 0xff) #define VTD_SID_TO_DEVFN(sid) ((sid) & 0xff)
#define DMAR_REG_SIZE 0x230 #define DMAR_REG_SIZE 0x230

View File

@ -14,6 +14,7 @@
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/compat.h"
#define HPET_INTCAP "hpet-intcap" #define HPET_INTCAP "hpet-intcap"
@ -33,6 +34,7 @@ struct PCMachineState {
MemoryRegion hotplug_memory; MemoryRegion hotplug_memory;
HotplugHandler *acpi_dev; HotplugHandler *acpi_dev;
ISADevice *rtc;
uint64_t max_ram_below_4g; uint64_t max_ram_below_4g;
bool vmport; bool vmport;
@ -212,7 +214,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
uint32 hpet_irqs); uint32 hpet_irqs);
void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd); 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, 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 *ide0, BusState *ide1, ISADevice *floppy, BusState *ide0, BusState *ide1,
ISADevice *s); ISADevice *s);
void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus); void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus);
@ -303,31 +305,8 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
int e820_get_num_entries(void); int e820_get_num_entries(void);
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
#define PC_COMPAT_2_1 \
{\
.driver = "intel-hda",\
.property = "old_msi_addr",\
.value = "on",\
},{\
.driver = "VGA",\
.property = "qemu-extended-regs",\
.value = "off",\
},{\
.driver = "secondary-vga",\
.property = "qemu-extended-regs",\
.value = "off",\
},{\
.driver = "usb-mouse",\
.property = "usb_version",\
.value = stringify(1),\
},{\
.driver = "usb-kbd",\
.property = "usb_version",\
.value = stringify(1),\
}
#define PC_COMPAT_2_0 \ #define PC_COMPAT_2_0 \
PC_COMPAT_2_1, \ HW_COMPAT_2_1, \
{\ {\
.driver = "virtio-scsi-pci",\ .driver = "virtio-scsi-pci",\
.property = "any_layout",\ .property = "any_layout",\

View File

@ -20,7 +20,8 @@
void smbios_entry_add(QemuOpts *opts); void smbios_entry_add(QemuOpts *opts);
void smbios_set_cpuid(uint32_t version, uint32_t features); void smbios_set_cpuid(uint32_t version, uint32_t features);
void smbios_set_defaults(const char *manufacturer, const char *product, 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);
uint8_t *smbios_get_table_legacy(size_t *length); uint8_t *smbios_get_table_legacy(size_t *length);
void smbios_get_tables(uint8_t **tables, size_t *tables_len, void smbios_get_tables(uint8_t **tables, size_t *tables_len,
uint8_t **anchor, size_t *anchor_len); uint8_t **anchor, size_t *anchor_len);
@ -72,6 +73,18 @@ struct smbios_type_0 {
uint8_t embedded_controller_minor_release; uint8_t embedded_controller_minor_release;
} QEMU_PACKED; } QEMU_PACKED;
/* UUID encoding. The time_* fields are little-endian, as specified by SMBIOS
* version 2.6.
*/
struct smbios_uuid {
uint32_t time_low;
uint16_t time_mid;
uint16_t time_hi_and_version;
uint8_t clock_seq_hi_and_reserved;
uint8_t clock_seq_low;
uint8_t node[6];
} QEMU_PACKED;
/* SMBIOS type 1 - System Information */ /* SMBIOS type 1 - System Information */
struct smbios_type_1 { struct smbios_type_1 {
struct smbios_structure_header header; struct smbios_structure_header header;
@ -79,7 +92,7 @@ struct smbios_type_1 {
uint8_t product_name_str; uint8_t product_name_str;
uint8_t version_str; uint8_t version_str;
uint8_t serial_number_str; uint8_t serial_number_str;
uint8_t uuid[16]; struct smbios_uuid uuid;
uint8_t wake_up_type; uint8_t wake_up_type;
uint8_t sku_number_str; uint8_t sku_number_str;
uint8_t family_str; uint8_t family_str;

View File

@ -184,9 +184,6 @@ void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
/* generic hotplug */ /* generic hotplug */
void drive_hot_add(Monitor *mon, const QDict *qdict); void drive_hot_add(Monitor *mon, const QDict *qdict);
/* CPU hotplug */
void qemu_register_cpu_added_notifier(Notifier *notifier);
/* pcie aer error injection */ /* pcie aer error injection */
void pcie_aer_inject_error_print(Monitor *mon, const QObject *data); void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
int do_pcie_aer_inject_error(Monitor *mon, int do_pcie_aer_inject_error(Monitor *mon,

View File

@ -107,15 +107,6 @@ static void cpu_common_get_memory_mapping(CPUState *cpu,
error_setg(errp, "Obtaining memory mappings is unsupported on this CPU."); error_setg(errp, "Obtaining memory mappings is unsupported on this CPU.");
} }
/* CPU hot-plug notifiers */
static NotifierList cpu_added_notifiers =
NOTIFIER_LIST_INITIALIZER(cpu_add_notifiers);
void qemu_register_cpu_added_notifier(Notifier *notifier)
{
notifier_list_add(&cpu_added_notifiers, notifier);
}
void cpu_reset_interrupt(CPUState *cpu, int mask) void cpu_reset_interrupt(CPUState *cpu, int mask)
{ {
cpu->interrupt_request &= ~mask; cpu->interrupt_request &= ~mask;
@ -312,7 +303,6 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
if (dev->hotplugged) { if (dev->hotplugged) {
cpu_synchronize_post_init(cpu); cpu_synchronize_post_init(cpu);
notifier_list_notify(&cpu_added_notifiers, dev);
cpu_resume(cpu); cpu_resume(cpu);
} }
} }

View File

@ -139,13 +139,16 @@ def aml_name_string(offset):
offset += 1 offset += 1
return offset; return offset;
# Given data offset, find 8 byte buffer offset # Given data offset, find variable length byte buffer offset
def aml_data_buffer8(offset): def aml_data_buffer(offset, length):
#0x08 NameOp NameString DataRef #0x11 PkgLength BufferSize ByteList
expect = [0x11, 0x0B, 0x0A, 0x08] if (length > 63):
die( "Name offset 0x%x: expected a one byte PkgLength (length<=63)" %
(offset));
expect = [0x11, length+3, 0x0A, length]
if (aml[offset:offset+4] != expect): if (aml[offset:offset+4] != expect):
die( "Name offset 0x%x: expected %s actual %s" % die( "Name offset 0x%x: expected %s actual %s" %
(offset, aml[offset:offset+4], expect)) (offset, expect, aml[offset:offset+4]))
return offset + len(expect) return offset + len(expect)
# Given data offset, find dword const offset # Given data offset, find dword const offset
@ -172,9 +175,9 @@ def aml_data_byte_const(offset):
(offset, aml[offset])); (offset, aml[offset]));
return offset + 1; return offset + 1;
# Find name'd buffer8 # Find name'd buffer
def aml_name_buffer8(offset): def aml_name_buffer(offset, length):
return aml_data_buffer8(aml_name_string(offset) + 4) return aml_data_buffer(aml_name_string(offset) + 4, length)
# Given name offset, find dword const offset # Given name offset, find dword const offset
def aml_name_dword_const(offset): def aml_name_dword_const(offset):
@ -308,7 +311,9 @@ for i in range(len(asl)):
output[array] = aml output[array] = aml
continue continue
if (directive == "ACPI_EXTRACT_NAME_BUFFER8"): if (directive == "ACPI_EXTRACT_NAME_BUFFER8"):
offset = aml_name_buffer8(offset) offset = aml_name_buffer(offset, 8)
elif (directive == "ACPI_EXTRACT_NAME_BUFFER16"):
offset = aml_name_buffer(offset, 16)
elif (directive == "ACPI_EXTRACT_NAME_DWORD_CONST"): elif (directive == "ACPI_EXTRACT_NAME_DWORD_CONST"):
offset = aml_name_dword_const(offset) offset = aml_name_dword_const(offset)
elif (directive == "ACPI_EXTRACT_NAME_WORD_CONST"): elif (directive == "ACPI_EXTRACT_NAME_WORD_CONST"):

View File

@ -23,13 +23,13 @@ else
exit 1; exit 1;
fi fi
if [ ! -e "tests/acpi-test" ]; then if [ ! -e "tests/bios-tables-test" ]; then
echo "Test: acpi-test is required! Run make check before this script." echo "Test: bios-tables-test is required! Run make check before this script."
echo "Run this script from the build directory." echo "Run this script from the build directory."
exit 1; exit 1;
fi fi
TEST_ACPI_REBUILD_AML=y QTEST_QEMU_BINARY=$qemu tests/acpi-test TEST_ACPI_REBUILD_AML=y QTEST_QEMU_BINARY=$qemu tests/bios-tables-test
echo "The files were rebuilt and can be added to git." echo "The files were rebuilt and can be added to git."
echo "However, if new files were created, please copy them manually" \ echo "However, if new files were created, please copy them manually" \

46
vl.c
View File

@ -190,6 +190,9 @@ int nb_numa_nodes;
int max_numa_nodeid; int max_numa_nodeid;
NodeInfo numa_info[MAX_NODES]; NodeInfo numa_info[MAX_NODES];
/* The bytes in qemu_uuid[] are in the order specified by RFC4122, _not_ in the
* little-endian "wire format" described in the SMBIOS 2.6 specification.
*/
uint8_t qemu_uuid[16]; uint8_t qemu_uuid[16];
bool qemu_uuid_set; bool qemu_uuid_set;
@ -1420,6 +1423,7 @@ static void machine_class_init(ObjectClass *oc, void *data)
MachineClass *mc = MACHINE_CLASS(oc); MachineClass *mc = MACHINE_CLASS(oc);
QEMUMachine *qm = data; QEMUMachine *qm = data;
mc->family = qm->family;
mc->name = qm->name; mc->name = qm->name;
mc->alias = qm->alias; mc->alias = qm->alias;
mc->desc = qm->desc; mc->desc = qm->desc;
@ -1440,6 +1444,7 @@ static void machine_class_init(ObjectClass *oc, void *data)
mc->is_default = qm->is_default; mc->is_default = qm->is_default;
mc->default_machine_opts = qm->default_machine_opts; mc->default_machine_opts = qm->default_machine_opts;
mc->default_boot_order = qm->default_boot_order; mc->default_boot_order = qm->default_boot_order;
mc->default_display = qm->default_display;
mc->compat_props = qm->compat_props; mc->compat_props = qm->compat_props;
mc->hw_version = qm->hw_version; mc->hw_version = qm->hw_version;
} }
@ -2492,7 +2497,41 @@ static int debugcon_parse(const char *devname)
return 0; return 0;
} }
static MachineClass *machine_parse(const char *name) static gint machine_class_cmp(gconstpointer a, gconstpointer b)
{
const MachineClass *mc1 = a, *mc2 = b;
int res;
if (mc1->family == NULL) {
if (mc2->family == NULL) {
/* Compare standalone machine types against each other; they sort
* in increasing order.
*/
return strcmp(object_class_get_name(OBJECT_CLASS(mc1)),
object_class_get_name(OBJECT_CLASS(mc2)));
}
/* Standalone machine types sort after families. */
return 1;
}
if (mc2->family == NULL) {
/* Families sort before standalone machine types. */
return -1;
}
/* Families sort between each other alphabetically increasingly. */
res = strcmp(mc1->family, mc2->family);
if (res != 0) {
return res;
}
/* Within the same family, machine types sort in decreasing order. */
return strcmp(object_class_get_name(OBJECT_CLASS(mc2)),
object_class_get_name(OBJECT_CLASS(mc1)));
}
static MachineClass *machine_parse(const char *name)
{ {
MachineClass *mc = NULL; MachineClass *mc = NULL;
GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false);
@ -2508,6 +2547,7 @@ static MachineClass *machine_parse(const char *name)
error_printf("Use -machine help to list supported machines!\n"); error_printf("Use -machine help to list supported machines!\n");
} else { } else {
printf("Supported machines are:\n"); printf("Supported machines are:\n");
machines = g_slist_sort(machines, machine_class_cmp);
for (el = machines; el; el = el->next) { for (el = machines; el; el = el->next) {
MachineClass *mc = el->data; MachineClass *mc = el->data;
if (mc->alias) { if (mc->alias) {
@ -4189,7 +4229,9 @@ int main(int argc, char **argv, char **envp)
/* If no default VGA is requested, the default is "none". */ /* If no default VGA is requested, the default is "none". */
if (default_vga) { if (default_vga) {
if (cirrus_vga_available()) { if (machine_class->default_display) {
vga_model = machine_class->default_display;
} else if (cirrus_vga_available()) {
vga_model = "cirrus"; vga_model = "cirrus";
} else if (vga_available()) { } else if (vga_available()) {
vga_model = "std"; vga_model = "std";