diff options
Diffstat (limited to 'hw')
36 files changed, 430 insertions, 272 deletions
diff --git a/hw/acpi/ipmi.c b/hw/acpi/ipmi.c index a20e57d..39f8f2f 100644 --- a/hw/acpi/ipmi.c +++ b/hw/acpi/ipmi.c @@ -55,7 +55,8 @@ static Aml *aml_ipmi_crs(IPMIFwInfo *info) abort(); } - if (info->interrupt_number) { + /* Should PCI interrupts also be appended? */ + if (info->irq_source == IPMI_ISA_IRQ && info->interrupt_number) { aml_append(crs, aml_irq_no_flags(info->interrupt_number)); } diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c index f17d5db..b5aec06e 100644 --- a/hw/arm/imx8mp-evk.c +++ b/hw/arm/imx8mp-evk.c @@ -15,6 +15,34 @@ #include "system/qtest.h" #include "qemu/error-report.h" #include "qapi/error.h" +#include <libfdt.h> + +static void imx8mp_evk_modify_dtb(const struct arm_boot_info *info, void *fdt) +{ + int i, offset; + + /* Temporarily disable following nodes until they are implemented */ + const char *nodes_to_remove[] = { + "nxp,imx8mp-fspi", + }; + + for (i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) { + const char *dev_str = nodes_to_remove[i]; + + offset = fdt_node_offset_by_compatible(fdt, -1, dev_str); + while (offset >= 0) { + fdt_nop_node(fdt, offset); + offset = fdt_node_offset_by_compatible(fdt, offset, dev_str); + } + } + + /* Remove cpu-idle-states property from CPU nodes */ + offset = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a53"); + while (offset >= 0) { + fdt_nop_property(fdt, offset, "cpu-idle-states"); + offset = fdt_node_offset_by_compatible(fdt, offset, "arm,cortex-a53"); + } +} static void imx8mp_evk_init(MachineState *machine) { @@ -32,6 +60,7 @@ static void imx8mp_evk_init(MachineState *machine) .board_id = -1, .ram_size = machine->ram_size, .psci_conduit = QEMU_PSCI_CONDUIT_SMC, + .modify_dtb = imx8mp_evk_modify_dtb, }; s = FSL_IMX8MP(object_new(TYPE_FSL_IMX8MP)); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index a96452f..3e72ada 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -3408,10 +3408,17 @@ static void machvirt_machine_init(void) } type_init(machvirt_machine_init); +static void virt_machine_10_1_options(MachineClass *mc) +{ +} +DEFINE_VIRT_MACHINE_AS_LATEST(10, 1) + static void virt_machine_10_0_options(MachineClass *mc) { + virt_machine_10_1_options(mc); + compat_props_add(mc->compat_props, hw_compat_10_0, hw_compat_10_0_len); } -DEFINE_VIRT_MACHINE_AS_LATEST(10, 0) +DEFINE_VIRT_MACHINE(10, 0) static void virt_machine_9_2_options(MachineClass *mc) { diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c index f6844bf..11fab184 100644 --- a/hw/avr/atmega.c +++ b/hw/avr/atmega.c @@ -19,6 +19,7 @@ #include "hw/sysbus.h" #include "qom/object.h" #include "hw/misc/unimp.h" +#include "migration/vmstate.h" #include "atmega.h" enum AtmegaPeripheral { @@ -224,8 +225,6 @@ static void atmega_realize(DeviceState *dev, Error **errp) char *devname; size_t i; - assert(mc->io_size <= 0x200); - if (!s->xtal_freq_hz) { error_setg(errp, "\"xtal-frequency-hz\" property must be provided."); return; @@ -240,11 +239,37 @@ static void atmega_realize(DeviceState *dev, Error **errp) qdev_realize(DEVICE(&s->cpu), NULL, &error_abort); cpudev = DEVICE(&s->cpu); - /* SRAM */ - memory_region_init_ram(&s->sram, OBJECT(dev), "sram", mc->sram_size, - &error_abort); - memory_region_add_subregion(get_system_memory(), - OFFSET_DATA + mc->io_size, &s->sram); + /* + * SRAM + * + * Softmmu is not able mix i/o and ram on the same page. + * Therefore in all cases, the first page exclusively contains i/o. + * + * If the MCU's i/o region matches the page size, then we can simply + * allocate all ram starting at the second page. Otherwise, we must + * allocate some ram as i/o to complete the first page. + */ + assert(mc->io_size == 0x100 || mc->io_size == 0x200); + if (mc->io_size >= TARGET_PAGE_SIZE) { + memory_region_init_ram(&s->sram, OBJECT(dev), "sram", mc->sram_size, + &error_abort); + memory_region_add_subregion(get_system_memory(), + OFFSET_DATA + mc->io_size, &s->sram); + } else { + int sram_io_size = TARGET_PAGE_SIZE - mc->io_size; + void *sram_io_mem = g_malloc0(sram_io_size); + + memory_region_init_ram_device_ptr(&s->sram_io, OBJECT(dev), "sram-as-io", + sram_io_size, sram_io_mem); + memory_region_add_subregion(get_system_memory(), + OFFSET_DATA + mc->io_size, &s->sram_io); + vmstate_register_ram(&s->sram_io, dev); + + memory_region_init_ram(&s->sram, OBJECT(dev), "sram", + mc->sram_size - sram_io_size, &error_abort); + memory_region_add_subregion(get_system_memory(), + OFFSET_DATA + TARGET_PAGE_SIZE, &s->sram); + } /* Flash */ memory_region_init_rom(&s->flash, OBJECT(dev), diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h index a99ee15..9ac4678 100644 --- a/hw/avr/atmega.h +++ b/hw/avr/atmega.h @@ -41,6 +41,7 @@ struct AtmegaMcuState { MemoryRegion flash; MemoryRegion eeprom; MemoryRegion sram; + MemoryRegion sram_io; DeviceState *io; AVRMaskState pwr[POWER_MAX]; AVRUsartState usart[USART_MAX]; diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c index 3130c5c..fd8b4e0 100644 --- a/hw/core/machine-qmp-cmds.c +++ b/hw/core/machine-qmp-cmds.c @@ -25,6 +25,7 @@ #include "system/numa.h" #include "system/runstate.h" #include "system/system.h" +#include "hw/s390x/storage-keys.h" /* * fast means: we NEVER interrupt vCPU threads to retrieve @@ -406,3 +407,16 @@ GuidInfo *qmp_query_vm_generation_id(Error **errp) info->guid = qemu_uuid_unparse_strdup(&vms->guid); return info; } + +void qmp_dump_skeys(const char *filename, Error **errp) +{ + ObjectClass *mc = object_get_class(qdev_get_machine()); + ObjectClass *oc = object_class_dynamic_cast(mc, TYPE_DUMP_SKEYS_INTERFACE); + + if (!oc) { + error_setg(errp, "Storage keys information not available" + " for this architecture"); + return; + } + DUMP_SKEYS_INTERFACE_CLASS(oc)->qmp_dump_skeys(filename, errp); +} diff --git a/hw/core/machine.c b/hw/core/machine.c index f52a4f2..abfcedd 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -37,6 +37,9 @@ #include "hw/virtio/virtio-iommu.h" #include "audio/audio.h" +GlobalProperty hw_compat_10_0[] = {}; +const size_t hw_compat_10_0_len = G_N_ELEMENTS(hw_compat_10_0); + GlobalProperty hw_compat_9_2[] = { {"arm-cpu", "backcompat-pauth-default-use-qarma5", "true"}, { "virtio-balloon-pci", "vectors", "0" }, @@ -1731,12 +1734,6 @@ void qdev_machine_creation_done(void) phase_advance(PHASE_MACHINE_READY); qdev_assert_realized_properly(); - /* - * If the user used -machine dumpdtb=file.dtb to request that we - * dump the DTB to a file, do it now, and exit. - */ - handle_machine_dumpdtb(current_machine); - /* TODO: once all bus devices are qdevified, this should be done * when bus is created by qdev.c */ /* @@ -1750,6 +1747,12 @@ void qdev_machine_creation_done(void) notifier_list_notify(&machine_init_done_notifiers, NULL); + /* + * If the user used -machine dumpdtb=file.dtb to request that we + * dump the DTB to a file, do it now, and exit. + */ + handle_machine_dumpdtb(current_machine); + if (rom_check_and_register_reset() != 0) { exit(1); } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 01d0581..1b5d55e 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -79,6 +79,9 @@ { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, }, +GlobalProperty pc_compat_10_0[] = {}; +const size_t pc_compat_10_0_len = G_N_ELEMENTS(pc_compat_10_0); + GlobalProperty pc_compat_9_2[] = {}; const size_t pc_compat_9_2_len = G_N_ELEMENTS(pc_compat_9_2); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 6c91e2d..dbb59df 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -479,12 +479,21 @@ static void pc_i440fx_machine_options(MachineClass *m) "Use a different south bridge than PIIX3"); } -static void pc_i440fx_machine_10_0_options(MachineClass *m) +static void pc_i440fx_machine_10_1_options(MachineClass *m) { pc_i440fx_machine_options(m); } -DEFINE_I440FX_MACHINE_AS_LATEST(10, 0); +DEFINE_I440FX_MACHINE_AS_LATEST(10, 1); + +static void pc_i440fx_machine_10_0_options(MachineClass *m) +{ + pc_i440fx_machine_10_1_options(m); + compat_props_add(m->compat_props, hw_compat_10_0, hw_compat_10_0_len); + compat_props_add(m->compat_props, pc_compat_10_0, pc_compat_10_0_len); +} + +DEFINE_I440FX_MACHINE(10, 0); static void pc_i440fx_machine_9_2_options(MachineClass *m) { diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index fd96d03..c538b3d 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -361,12 +361,21 @@ static void pc_q35_machine_options(MachineClass *m) pc_q35_compat_defaults, pc_q35_compat_defaults_len); } -static void pc_q35_machine_10_0_options(MachineClass *m) +static void pc_q35_machine_10_1_options(MachineClass *m) { pc_q35_machine_options(m); } -DEFINE_Q35_MACHINE_AS_LATEST(10, 0); +DEFINE_Q35_MACHINE_AS_LATEST(10, 1); + +static void pc_q35_machine_10_0_options(MachineClass *m) +{ + pc_q35_machine_10_1_options(m); + compat_props_add(m->compat_props, hw_compat_10_0, hw_compat_10_0_len); + compat_props_add(m->compat_props, pc_compat_10_0, pc_compat_10_0_len); +} + +DEFINE_Q35_MACHINE(10, 0); static void pc_q35_machine_9_2_options(MachineClass *m) { diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index c20f4c1..4fae023 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -470,11 +470,6 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) fsc->inject_crw_mchk = qemu_s390_inject_crw_mchk; } -static const Property s390_flic_common_properties[] = { - DEFINE_PROP_BOOL("migration-enabled", S390FLICState, - migration_enabled, true), -}; - static void s390_flic_common_realize(DeviceState *dev, Error **errp) { S390FLICState *fs = S390_FLIC_COMMON(dev); @@ -486,7 +481,6 @@ static void s390_flic_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - device_class_set_props(dc, s390_flic_common_properties); dc->realize = s390_flic_common_realize; } @@ -515,18 +509,10 @@ static void qemu_s390_flic_register_types(void) type_init(qemu_s390_flic_register_types) -static bool adapter_info_so_needed(void *opaque) -{ - S390FLICState *fs = s390_get_flic(); - - return fs->migration_enabled; -} - const VMStateDescription vmstate_adapter_info_so = { .name = "s390_adapter_info/summary_offset", .version_id = 1, .minimum_version_id = 1, - .needed = adapter_info_so_needed, .fields = (const VMStateField[]) { VMSTATE_UINT32(summary_offset, AdapterInfo), VMSTATE_END_OF_LIST() diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c index d015500..3e9f8c5 100644 --- a/hw/ipmi/ipmi_bmc_extern.c +++ b/hw/ipmi/ipmi_bmc_extern.c @@ -497,8 +497,6 @@ static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp) qemu_chr_fe_set_handlers(&ibe->chr, can_receive, receive, chr_event, NULL, ibe, NULL, true); - - vmstate_register(NULL, 0, &vmstate_ipmi_bmc_extern, ibe); } static void ipmi_bmc_extern_init(Object *obj) @@ -528,6 +526,7 @@ static void ipmi_bmc_extern_class_init(ObjectClass *oc, void *data) bk->handle_reset = ipmi_bmc_extern_handle_reset; dc->hotpluggable = false; dc->realize = ipmi_bmc_extern_realize; + dc->vmsd = &vmstate_ipmi_bmc_extern; device_class_set_props(dc, ipmi_bmc_extern_properties); } diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c index 6157ac7..1c60a71 100644 --- a/hw/ipmi/ipmi_bmc_sim.c +++ b/hw/ipmi/ipmi_bmc_sim.c @@ -70,6 +70,7 @@ #define IPMI_CMD_GET_MSG 0x33 #define IPMI_CMD_SEND_MSG 0x34 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35 +#define IPMI_CMD_GET_CHANNEL_INFO 0x42 #define IPMI_NETFN_STORAGE 0x0a @@ -234,6 +235,7 @@ struct IPMIBmcSim { #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \ (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags) +#define IPMI_BMC_GLOBAL_ENABLES_SUPPORTED 0x0f #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2 @@ -513,7 +515,8 @@ static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert, static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor, unsigned int bit, unsigned int val, - uint8_t evd1, uint8_t evd2, uint8_t evd3) + uint8_t evd1, uint8_t evd2, uint8_t evd3, + bool do_log) { IPMISensor *sens; uint16_t mask; @@ -533,7 +536,7 @@ static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor, return; /* Already asserted */ } sens->assert_states |= mask & sens->assert_suppt; - if (sens->assert_enable & mask & sens->assert_states) { + if (do_log && (sens->assert_enable & mask & sens->assert_states)) { /* Send an event on assert */ gen_event(ibs, sensor, 0, evd1, evd2, evd3); } @@ -543,7 +546,7 @@ static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor, return; /* Already deasserted */ } sens->deassert_states |= mask & sens->deassert_suppt; - if (sens->deassert_enable & mask & sens->deassert_states) { + if (do_log && (sens->deassert_enable & mask & sens->deassert_states)) { /* Send an event on deassert */ gen_event(ibs, sensor, 1, evd1, evd2, evd3); } @@ -699,6 +702,7 @@ static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs) { IPMIInterface *s = ibs->parent.intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); + bool do_log = !IPMI_BMC_WATCHDOG_GET_DONT_LOG(ibs); if (!ibs->watchdog_running) { goto out; @@ -710,14 +714,16 @@ static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs) ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK; k->do_hw_op(s, IPMI_SEND_NMI, 0); sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1, - 0xc8, (2 << 4) | 0xf, 0xff); + 0xc8, (2 << 4) | 0xf, 0xff, + do_log); break; case IPMI_BMC_WATCHDOG_PRE_MSG_INT: ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK; k->set_atn(s, 1, attn_irq_enabled(ibs)); sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1, - 0xc8, (3 << 4) | 0xf, 0xff); + 0xc8, (3 << 4) | 0xf, 0xff, + do_log); break; default: @@ -737,24 +743,28 @@ static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs) switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) { case IPMI_BMC_WATCHDOG_ACTION_NONE: sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1, - 0xc0, ibs->watchdog_use & 0xf, 0xff); + 0xc0, ibs->watchdog_use & 0xf, 0xff, + do_log); break; case IPMI_BMC_WATCHDOG_ACTION_RESET: sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1, - 0xc1, ibs->watchdog_use & 0xf, 0xff); + 0xc1, ibs->watchdog_use & 0xf, 0xff, + do_log); k->do_hw_op(s, IPMI_RESET_CHASSIS, 0); break; case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN: sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1, - 0xc2, ibs->watchdog_use & 0xf, 0xff); + 0xc2, ibs->watchdog_use & 0xf, 0xff, + do_log); k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0); break; case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE: sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1, - 0xc3, ibs->watchdog_use & 0xf, 0xff); + 0xc3, ibs->watchdog_use & 0xf, 0xff, + do_log); k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0); break; } @@ -925,7 +935,14 @@ static void set_bmc_global_enables(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, RspBuffer *rsp) { - set_global_enables(ibs, cmd[2]); + uint8_t val = cmd[2]; + + if (val & ~IPMI_BMC_GLOBAL_ENABLES_SUPPORTED) { + rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); + return; + } + + set_global_enables(ibs, val); } static void get_bmc_global_enables(IPMIBmcSim *ibs, @@ -1020,8 +1037,8 @@ static void send_msg(IPMIBmcSim *ibs, uint8_t *buf; uint8_t netfn, rqLun, rsLun, rqSeq; - if (cmd[2] != 0) { - /* We only handle channel 0 with no options */ + if (cmd[2] != IPMI_CHANNEL_IPMB) { + /* We only handle channel 0h (IPMB) with no options */ rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); return; } @@ -1219,6 +1236,68 @@ static void get_watchdog_timer(IPMIBmcSim *ibs, } } +static void get_channel_info(IPMIBmcSim *ibs, + uint8_t *cmd, unsigned int cmd_len, + RspBuffer *rsp) +{ + IPMIInterface *s = ibs->parent.intf; + IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); + IPMIFwInfo info = {}; + uint8_t ch = cmd[2] & 0x0f; + + /* Only define channel 0h (IPMB) and Fh (system interface) */ + + if (ch == 0x0e) { /* "This channel" */ + ch = IPMI_CHANNEL_SYSTEM; + } + rsp_buffer_push(rsp, ch); + + if (ch != IPMI_CHANNEL_IPMB && ch != IPMI_CHANNEL_SYSTEM) { + /* Not a supported channel */ + rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); + return; + } + + if (k->get_fwinfo) { + k->get_fwinfo(s, &info); + } + + if (ch == IPMI_CHANNEL_IPMB) { + rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_IPMB); + rsp_buffer_push(rsp, IPMI_CHANNEL_PROTOCOL_IPMB); + } else { /* IPMI_CHANNEL_SYSTEM */ + rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_SYSTEM); + rsp_buffer_push(rsp, info.ipmi_channel_protocol); + } + + rsp_buffer_push(rsp, 0x00); /* Session-less */ + + /* IPMI Enterprise Number for Vendor ID */ + rsp_buffer_push(rsp, 0xf2); + rsp_buffer_push(rsp, 0x1b); + rsp_buffer_push(rsp, 0x00); + + if (ch == IPMI_CHANNEL_SYSTEM) { + uint8_t irq; + + if (info.irq_source == IPMI_ISA_IRQ) { + irq = info.interrupt_number; + } else if (info.irq_source == IPMI_PCI_IRQ) { + irq = 0x10 + info.interrupt_number; + } else { + irq = 0xff; /* no interrupt / unspecified */ + } + + /* Both interrupts use the same irq number */ + rsp_buffer_push(rsp, irq); + rsp_buffer_push(rsp, irq); + } else { + /* Reserved */ + rsp_buffer_push(rsp, 0x00); + rsp_buffer_push(rsp, 0x00); + } +} + static void get_sdr_rep_info(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, RspBuffer *rsp) @@ -2015,6 +2094,7 @@ static const IPMICmdHandler app_cmds[] = { [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer }, [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 }, [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer }, + [IPMI_CMD_GET_CHANNEL_INFO] = { get_channel_info, 3 }, }; static const IPMINetfn app_netfn = { .cmd_nums = ARRAY_SIZE(app_cmds), @@ -2187,8 +2267,6 @@ static void ipmi_sim_realize(DeviceState *dev, Error **errp) register_cmds(ibs); ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs); - - vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs); } static const Property ipmi_sim_properties[] = { @@ -2212,6 +2290,7 @@ static void ipmi_sim_class_init(ObjectClass *oc, void *data) dc->hotpluggable = false; dc->realize = ipmi_sim_realize; + dc->vmsd = &vmstate_ipmi_sim; device_class_set_props(dc, ipmi_sim_properties); bk->handle_command = ipmi_sim_handle_command; } diff --git a/hw/ipmi/ipmi_bt.c b/hw/ipmi/ipmi_bt.c index 583fc64..28cf6ab 100644 --- a/hw/ipmi/ipmi_bt.c +++ b/hw/ipmi/ipmi_bt.c @@ -419,6 +419,8 @@ void ipmi_bt_get_fwinfo(struct IPMIBT *ib, IPMIFwInfo *info) info->interface_type = IPMI_SMBIOS_BT; info->ipmi_spec_major_revision = 2; info->ipmi_spec_minor_revision = 0; + /* BT System Interface Format, IPMI v1.5 */ + info->ipmi_channel_protocol = IPMI_CHANNEL_PROTOCOL_BT_15; info->base_address = ib->io_base; info->register_length = ib->io_length; info->register_spacing = 1; diff --git a/hw/ipmi/ipmi_kcs.c b/hw/ipmi/ipmi_kcs.c index c15977c..578dd7c 100644 --- a/hw/ipmi/ipmi_kcs.c +++ b/hw/ipmi/ipmi_kcs.c @@ -405,6 +405,7 @@ void ipmi_kcs_get_fwinfo(IPMIKCS *ik, IPMIFwInfo *info) info->interface_type = IPMI_SMBIOS_KCS; info->ipmi_spec_major_revision = 2; info->ipmi_spec_minor_revision = 0; + info->ipmi_channel_protocol = IPMI_CHANNEL_PROTOCOL_KCS; info->base_address = ik->io_base; info->i2c_slave_address = ik->bmc->slave_addr; info->register_length = ik->io_length; diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c index a1b66d5..76585e7 100644 --- a/hw/ipmi/isa_ipmi_bt.c +++ b/hw/ipmi/isa_ipmi_bt.c @@ -49,6 +49,7 @@ static void isa_ipmi_bt_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info) ISAIPMIBTDevice *iib = ISA_IPMI_BT(ii); ipmi_bt_get_fwinfo(&iib->bt, info); + info->irq_source = IPMI_ISA_IRQ; info->interrupt_number = iib->isairq; info->i2c_slave_address = iib->bt.bmc->slave_addr; info->uuid = iib->uuid; @@ -117,8 +118,6 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp) qdev_set_legacy_instance_id(dev, iib->bt.io_base, iib->bt.io_length); isa_register_ioport(isadev, &iib->bt.io, iib->bt.io_base); - - vmstate_register(NULL, 0, &vmstate_ISAIPMIBTDevice, dev); } static void isa_ipmi_bt_init(Object *obj) @@ -147,6 +146,7 @@ static void isa_ipmi_bt_class_init(ObjectClass *oc, void *data) AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(oc); dc->realize = isa_ipmi_bt_realize; + dc->vmsd = &vmstate_ISAIPMIBTDevice; device_class_set_props(dc, ipmi_isa_properties); iic->get_backend_data = isa_ipmi_bt_get_backend_data; diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c index d9ebdd5..ba3ae20 100644 --- a/hw/ipmi/isa_ipmi_kcs.c +++ b/hw/ipmi/isa_ipmi_kcs.c @@ -49,6 +49,7 @@ static void isa_ipmi_kcs_get_fwinfo(IPMIInterface *ii, IPMIFwInfo *info) ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(ii); ipmi_kcs_get_fwinfo(&iik->kcs, info); + info->irq_source = IPMI_ISA_IRQ; info->interrupt_number = iik->isairq; info->uuid = iik->uuid; } @@ -72,6 +73,10 @@ static bool vmstate_kcs_before_version2(void *opaque, int version) return version <= 1; } +/* + * Version 1 had an incorrect name, it clashed with the BT IPMI + * device, so receive it, but transmit a different version. + */ static const VMStateDescription vmstate_ISAIPMIKCSDevice = { .name = TYPE_IPMI_INTERFACE, .version_id = 2, @@ -119,13 +124,6 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp) qdev_set_legacy_instance_id(dev, iik->kcs.io_base, iik->kcs.io_length); isa_register_ioport(isadev, &iik->kcs.io, iik->kcs.io_base); - - /* - * Version 1 had an incorrect name, it clashed with the BT - * IPMI device, so receive it, but transmit a different - * version. - */ - vmstate_register(NULL, 0, &vmstate_ISAIPMIKCSDevice, iik); } static void isa_ipmi_kcs_init(Object *obj) @@ -154,6 +152,7 @@ static void isa_ipmi_kcs_class_init(ObjectClass *oc, void *data) AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(oc); dc->realize = ipmi_isa_realize; + dc->vmsd = &vmstate_ISAIPMIKCSDevice; device_class_set_props(dc, ipmi_isa_properties); iic->get_backend_data = isa_ipmi_kcs_get_backend_data; diff --git a/hw/ipmi/pci_ipmi_bt.c b/hw/ipmi/pci_ipmi_bt.c index afeea6f..7ba8b3a 100644 --- a/hw/ipmi/pci_ipmi_bt.c +++ b/hw/ipmi/pci_ipmi_bt.c @@ -38,49 +38,60 @@ struct PCIIPMIBTDevice { uint32_t uuid; }; -static void pci_ipmi_raise_irq(IPMIBT *ik) +static void pci_ipmi_bt_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info) { - PCIIPMIBTDevice *pik = ik->opaque; + PCIIPMIBTDevice *pib = PCI_IPMI_BT(ii); - pci_set_irq(&pik->dev, true); + ipmi_bt_get_fwinfo(&pib->bt, info); + info->irq_source = IPMI_PCI_IRQ; + info->interrupt_number = pci_intx(&pib->dev); + info->i2c_slave_address = pib->bt.bmc->slave_addr; + info->uuid = pib->uuid; } -static void pci_ipmi_lower_irq(IPMIBT *ik) +static void pci_ipmi_raise_irq(IPMIBT *ib) { - PCIIPMIBTDevice *pik = ik->opaque; + PCIIPMIBTDevice *pib = ib->opaque; - pci_set_irq(&pik->dev, false); + pci_set_irq(&pib->dev, true); +} + +static void pci_ipmi_lower_irq(IPMIBT *ib) +{ + PCIIPMIBTDevice *pib = ib->opaque; + + pci_set_irq(&pib->dev, false); } static void pci_ipmi_bt_realize(PCIDevice *pd, Error **errp) { Error *err = NULL; - PCIIPMIBTDevice *pik = PCI_IPMI_BT(pd); + PCIIPMIBTDevice *pib = PCI_IPMI_BT(pd); IPMIInterface *ii = IPMI_INTERFACE(pd); IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); - if (!pik->bt.bmc) { + if (!pib->bt.bmc) { error_setg(errp, "IPMI device requires a bmc attribute to be set"); return; } - pik->uuid = ipmi_next_uuid(); + pib->uuid = ipmi_next_uuid(); - pik->bt.bmc->intf = ii; - pik->bt.opaque = pik; + pib->bt.bmc->intf = ii; + pib->bt.opaque = pib; pci_config_set_prog_interface(pd->config, 0x02); /* BT */ pci_config_set_interrupt_pin(pd->config, 0x01); - pik->bt.use_irq = 1; - pik->bt.raise_irq = pci_ipmi_raise_irq; - pik->bt.lower_irq = pci_ipmi_lower_irq; + pib->bt.use_irq = 1; + pib->bt.raise_irq = pci_ipmi_raise_irq; + pib->bt.lower_irq = pci_ipmi_lower_irq; iic->init(ii, 8, &err); if (err) { error_propagate(errp, err); return; } - pci_register_bar(pd, 0, PCI_BASE_ADDRESS_SPACE_IO, &pik->bt.io); + pci_register_bar(pd, 0, PCI_BASE_ADDRESS_SPACE_IO, &pib->bt.io); } const VMStateDescription vmstate_PCIIPMIBTDevice = { @@ -96,16 +107,16 @@ const VMStateDescription vmstate_PCIIPMIBTDevice = { static void pci_ipmi_bt_instance_init(Object *obj) { - PCIIPMIBTDevice *pik = PCI_IPMI_BT(obj); + PCIIPMIBTDevice *pib = PCI_IPMI_BT(obj); - ipmi_bmc_find_and_link(obj, (Object **) &pik->bt.bmc); + ipmi_bmc_find_and_link(obj, (Object **) &pib->bt.bmc); } static void *pci_ipmi_bt_get_backend_data(IPMIInterface *ii) { - PCIIPMIBTDevice *pik = PCI_IPMI_BT(ii); + PCIIPMIBTDevice *pib = PCI_IPMI_BT(ii); - return &pik->bt; + return &pib->bt; } static void pci_ipmi_bt_class_init(ObjectClass *oc, void *data) @@ -125,6 +136,7 @@ static void pci_ipmi_bt_class_init(ObjectClass *oc, void *data) iic->get_backend_data = pci_ipmi_bt_get_backend_data; ipmi_bt_class_init(iic); + iic->get_fwinfo = pci_ipmi_bt_get_fwinfo; } static const TypeInfo pci_ipmi_bt_info = { diff --git a/hw/ipmi/pci_ipmi_kcs.c b/hw/ipmi/pci_ipmi_kcs.c index 05ba97e..0aa3514 100644 --- a/hw/ipmi/pci_ipmi_kcs.c +++ b/hw/ipmi/pci_ipmi_kcs.c @@ -38,6 +38,16 @@ struct PCIIPMIKCSDevice { uint32_t uuid; }; +static void pci_ipmi_kcs_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info) +{ + PCIIPMIKCSDevice *pik = PCI_IPMI_KCS(ii); + + ipmi_kcs_get_fwinfo(&pik->kcs, info); + info->irq_source = IPMI_PCI_IRQ; + info->interrupt_number = pci_intx(&pik->dev); + info->uuid = pik->uuid; +} + static void pci_ipmi_raise_irq(IPMIKCS *ik) { PCIIPMIKCSDevice *pik = ik->opaque; @@ -125,6 +135,7 @@ static void pci_ipmi_kcs_class_init(ObjectClass *oc, void *data) iic->get_backend_data = pci_ipmi_kcs_get_backend_data; ipmi_kcs_class_init(iic); + iic->get_fwinfo = pci_ipmi_kcs_get_fwinfo; } static const TypeInfo pci_ipmi_kcs_info = { diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index e258642..65c9027 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -936,29 +936,15 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { CPUArchId *cpu_slot; - Error *err = NULL; LoongArchCPU *cpu = LOONGARCH_CPU(dev); LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev); /* Notify ipi and extioi irqchip to remove interrupt routing to CPU */ - hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->ipi), dev, &err); - if (err) { - error_propagate(errp, err); - return; - } - - hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->extioi), dev, &err); - if (err) { - error_propagate(errp, err); - return; - } + hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->ipi), dev, &error_abort); + hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->extioi), dev, &error_abort); /* Notify acpi ged CPU removed */ - hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->acpi_ged), dev, &err); - if (err) { - error_propagate(errp, err); - return; - } + hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->acpi_ged), dev, &error_abort); cpu_slot = virt_find_cpu_slot(MACHINE(lvms), cpu->phy_id); cpu_slot->cpu = NULL; @@ -971,33 +957,22 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, CPUArchId *cpu_slot; LoongArchCPU *cpu = LOONGARCH_CPU(dev); LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev); - Error *err = NULL; - cpu_slot = virt_find_cpu_slot(MACHINE(lvms), cpu->phy_id); - cpu_slot->cpu = CPU(dev); if (lvms->ipi) { - hotplug_handler_plug(HOTPLUG_HANDLER(lvms->ipi), dev, &err); - if (err) { - error_propagate(errp, err); - return; - } + hotplug_handler_plug(HOTPLUG_HANDLER(lvms->ipi), dev, &error_abort); } if (lvms->extioi) { - hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), dev, &err); - if (err) { - error_propagate(errp, err); - return; - } + hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), dev, &error_abort); } if (lvms->acpi_ged) { - hotplug_handler_plug(HOTPLUG_HANDLER(lvms->acpi_ged), dev, &err); - if (err) { - error_propagate(errp, err); - } + hotplug_handler_plug(HOTPLUG_HANDLER(lvms->acpi_ged), dev, + &error_abort); } + cpu_slot = virt_find_cpu_slot(MACHINE(lvms), cpu->phy_id); + cpu_slot->cpu = CPU(dev); return; } diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index d967bdd..295a614 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -366,10 +366,17 @@ type_init(virt_machine_register_types) #define DEFINE_VIRT_MACHINE(major, minor) \ DEFINE_VIRT_MACHINE_IMPL(false, major, minor) +static void virt_machine_10_1_options(MachineClass *mc) +{ +} +DEFINE_VIRT_MACHINE_AS_LATEST(10, 1) + static void virt_machine_10_0_options(MachineClass *mc) { + virt_machine_10_1_options(mc); + compat_props_add(mc->compat_props, hw_compat_10_0, hw_compat_10_0_len); } -DEFINE_VIRT_MACHINE_AS_LATEST(10, 0) +DEFINE_VIRT_MACHINE(10, 0) static void virt_machine_9_2_options(MachineClass *mc) { diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 340c6b6..bd37651 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1702,44 +1702,41 @@ static void virtio_net_hdr_swap(VirtIODevice *vdev, struct virtio_net_hdr *hdr) * cache. */ static void work_around_broken_dhclient(struct virtio_net_hdr *hdr, - size_t *hdr_len, const uint8_t *buf, - size_t buf_size, size_t *buf_offset) + uint8_t *buf, size_t size) { size_t csum_size = ETH_HLEN + sizeof(struct ip_header) + sizeof(struct udp_header); - buf += *buf_offset; - buf_size -= *buf_offset; - if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */ - (buf_size >= csum_size && buf_size < 1500) && /* normal sized MTU */ + (size >= csum_size && size < 1500) && /* normal sized MTU */ (buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */ (buf[23] == 17) && /* ip.protocol == UDP */ (buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */ - memcpy((uint8_t *)hdr + *hdr_len, buf, csum_size); - net_checksum_calculate((uint8_t *)hdr + *hdr_len, csum_size, CSUM_UDP); + net_checksum_calculate(buf, size, CSUM_UDP); hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM; - *hdr_len += csum_size; - *buf_offset += csum_size; } } -static size_t receive_header(VirtIONet *n, struct virtio_net_hdr *hdr, - const void *buf, size_t buf_size, - size_t *buf_offset) +static void receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt, + const void *buf, size_t size) { - size_t hdr_len = n->guest_hdr_len; - - memcpy(hdr, buf, sizeof(struct virtio_net_hdr)); - - *buf_offset = n->host_hdr_len; - work_around_broken_dhclient(hdr, &hdr_len, buf, buf_size, buf_offset); + if (n->has_vnet_hdr) { + /* FIXME this cast is evil */ + void *wbuf = (void *)buf; + work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len, + size - n->host_hdr_len); - if (n->needs_vnet_hdr_swap) { - virtio_net_hdr_swap(VIRTIO_DEVICE(n), hdr); + if (n->needs_vnet_hdr_swap) { + virtio_net_hdr_swap(VIRTIO_DEVICE(n), wbuf); + } + iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr)); + } else { + struct virtio_net_hdr hdr = { + .flags = 0, + .gso_type = VIRTIO_NET_HDR_GSO_NONE + }; + iov_from_buf(iov, iov_cnt, 0, &hdr, sizeof hdr); } - - return hdr_len; } static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) @@ -1907,13 +1904,6 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf, return (index == new_index) ? -1 : new_index; } -typedef struct Header { - struct virtio_net_hdr_v1_hash virtio_net; - struct eth_header eth; - struct ip_header ip; - struct udp_header udp; -} Header; - static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, size_t size) { @@ -1923,15 +1913,15 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE]; size_t lens[VIRTQUEUE_MAX_SIZE]; struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE]; - Header hdr; + struct virtio_net_hdr_v1_hash extra_hdr; unsigned mhdr_cnt = 0; size_t offset, i, guest_offset, j; ssize_t err; - memset(&hdr.virtio_net, 0, sizeof(hdr.virtio_net)); + memset(&extra_hdr, 0, sizeof(extra_hdr)); if (n->rss_data.enabled && n->rss_data.enabled_software_rss) { - int index = virtio_net_process_rss(nc, buf, size, &hdr.virtio_net); + int index = virtio_net_process_rss(nc, buf, size, &extra_hdr); if (index >= 0) { nc = qemu_get_subqueue(n->nic, index % n->curr_queue_pairs); } @@ -1996,20 +1986,23 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, if (n->mergeable_rx_bufs) { mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg), sg, elem->in_num, - offsetof(typeof(hdr), - virtio_net.hdr.num_buffers), - sizeof(hdr.virtio_net.hdr.num_buffers)); + offsetof(typeof(extra_hdr), hdr.num_buffers), + sizeof(extra_hdr.hdr.num_buffers)); } else { - hdr.virtio_net.hdr.num_buffers = cpu_to_le16(1); + extra_hdr.hdr.num_buffers = cpu_to_le16(1); } - guest_offset = n->has_vnet_hdr ? - receive_header(n, (struct virtio_net_hdr *)&hdr, - buf, size, &offset) : - n->guest_hdr_len; - - iov_from_buf(sg, elem->in_num, 0, &hdr, guest_offset); - total += guest_offset; + receive_header(n, sg, elem->in_num, buf, size); + if (n->rss_data.populate_hash) { + offset = offsetof(typeof(extra_hdr), hash_value); + iov_from_buf(sg, elem->in_num, offset, + (char *)&extra_hdr + offset, + sizeof(extra_hdr.hash_value) + + sizeof(extra_hdr.hash_report)); + } + offset = n->host_hdr_len; + total += n->guest_hdr_len; + guest_offset = n->guest_hdr_len; } else { guest_offset = 0; } @@ -2035,11 +2028,11 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, } if (mhdr_cnt) { - virtio_stw_p(vdev, &hdr.virtio_net.hdr.num_buffers, i); + virtio_stw_p(vdev, &extra_hdr.hdr.num_buffers, i); iov_from_buf(mhdr_sg, mhdr_cnt, 0, - &hdr.virtio_net.hdr.num_buffers, - sizeof hdr.virtio_net.hdr.num_buffers); + &extra_hdr.hdr.num_buffers, + sizeof extra_hdr.hdr.num_buffers); } for (j = 0; j < i; j++) { diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 518d02d..d6b77d4 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -7755,7 +7755,11 @@ static int nvme_start_ctrl(NvmeCtrl *n) for (int i = 1; i <= NVME_MAX_NAMESPACES; i++) { NvmeNamespace *ns = nvme_subsys_ns(n->subsys, i); - if (ns && nvme_csi_supported(n, ns->csi) && !ns->params.detached) { + if (!ns || (!ns->params.shared && ns->ctrl != n)) { + continue; + } + + if (nvme_csi_supported(n, ns->csi) && !ns->params.detached) { if (!ns->attached || ns->params.shared) { nvme_attach_ns(n, ns); } @@ -8988,6 +8992,7 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) if (n->namespace.blkconf.blk) { ns = &n->namespace; ns->params.nsid = 1; + ns->ctrl = n; if (nvme_ns_setup(ns, errp)) { return; diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 98c1e75..4ab8ba7 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -763,6 +763,10 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp) ns->id_ns.endgid = cpu_to_le16(0x1); ns->id_ns_ind.endgrpid = cpu_to_le16(0x1); + + if (!ns->params.shared) { + ns->ctrl = n; + } } static const Property nvme_ns_props[] = { diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 6f782ba..b5c9378 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -268,6 +268,9 @@ typedef struct NvmeNamespace { NvmeSubsystem *subsys; NvmeEnduranceGroup *endgrp; + /* NULL for shared namespaces; set to specific controller if private */ + NvmeCtrl *ctrl; + struct { uint32_t err_rec; } features; diff --git a/hw/nvme/subsys.c b/hw/nvme/subsys.c index 2ae56f1..b617ac3 100644 --- a/hw/nvme/subsys.c +++ b/hw/nvme/subsys.c @@ -56,7 +56,7 @@ int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp) { NvmeSubsystem *subsys = n->subsys; NvmeSecCtrlEntry *sctrl = nvme_sctrl(n); - int cntlid, nsid, num_rsvd, num_vfs = n->params.sriov_max_vfs; + int cntlid, num_rsvd, num_vfs = n->params.sriov_max_vfs; if (pci_is_vf(&n->parent_obj)) { cntlid = le16_to_cpu(sctrl->scid); @@ -92,13 +92,6 @@ int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp) subsys->ctrls[cntlid] = n; - for (nsid = 1; nsid < ARRAY_SIZE(subsys->namespaces); nsid++) { - NvmeNamespace *ns = subsys->namespaces[nsid]; - if (ns && ns->params.shared && !ns->params.detached) { - nvme_attach_ns(n, ns); - } - } - return cntlid; } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index b0a0f8c..6fef1d1 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -4767,14 +4767,25 @@ static void spapr_machine_latest_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE_IMPL(false, major, minor) /* + * pseries-10.1 + */ +static void spapr_machine_10_1_class_options(MachineClass *mc) +{ + /* Defaults for the latest behaviour inherited from the base class */ +} + +DEFINE_SPAPR_MACHINE_AS_LATEST(10, 1); + +/* * pseries-10.0 */ static void spapr_machine_10_0_class_options(MachineClass *mc) { - /* Defaults for the latest behaviour inherited from the base class */ + spapr_machine_10_1_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_10_0, hw_compat_10_0_len); } -DEFINE_SPAPR_MACHINE_AS_LATEST(10, 0); +DEFINE_SPAPR_MACHINE(10, 0); /* * pseries-9.2 diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 738800c..17afcbb 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -23,8 +23,6 @@ #include "hw/s390x/s390-virtio-ccw.h" #include "hw/s390x/s390-ccw.h" -bool css_migration_enabled = true; - typedef struct CrwContainer { CRW crw; QTAILQ_ENTRY(CrwContainer) sibling; @@ -180,16 +178,10 @@ static const VMStateDescription vmstate_orb = { } }; -static bool vmstate_schdev_orb_needed(void *opaque) -{ - return css_migration_enabled; -} - static const VMStateDescription vmstate_schdev_orb = { .name = "s390_subch_dev/orb", .version_id = 1, .minimum_version_id = 1, - .needed = vmstate_schdev_orb_needed, .fields = (const VMStateField[]) { VMSTATE_STRUCT(orb, SubchDev, 1, vmstate_orb, ORB), VMSTATE_END_OF_LIST() @@ -390,33 +382,12 @@ static int subch_dev_post_load(void *opaque, int version_id) css_subch_assign(s->cssid, s->ssid, s->schid, s->devno, s); } - if (css_migration_enabled) { - /* No compat voodoo to do ;) */ - return 0; - } - /* - * Hack alert. If we don't migrate the channel subsystem status - * we still need to find out if the guest enabled mss/mcss-e. - * If the subchannel is enabled, it certainly was able to access it, - * so adjust the max_ssid/max_cssid values for relevant ssid/cssid - * values. This is not watertight, but better than nothing. - */ - if (s->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA) { - if (s->ssid) { - channel_subsys.max_ssid = MAX_SSID; - } - if (s->cssid != channel_subsys.default_cssid) { - channel_subsys.max_cssid = MAX_CSSID; - } - } return 0; } void css_register_vmstate(void) { - if (css_migration_enabled) { - vmstate_register(NULL, 0, &vmstate_css, &channel_subsys); - } + vmstate_register(NULL, 0, &vmstate_css, &channel_subsys); } IndAddr *get_indicator(hwaddr ind_addr, int len) diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c index 811d892..067ea03 100644 --- a/hw/s390x/s390-skeys.c +++ b/hw/s390x/s390-skeys.c @@ -15,6 +15,7 @@ #include "hw/qdev-properties.h" #include "hw/s390x/storage-keys.h" #include "qapi/error.h" +#include "qapi/qapi-commands-machine.h" #include "qapi/qapi-commands-misc-target.h" #include "qobject/qdict.h" #include "qemu/error-report.h" @@ -142,7 +143,7 @@ void hmp_dump_skeys(Monitor *mon, const QDict *qdict) } } -void qmp_dump_skeys(const char *filename, Error **errp) +void s390_qmp_dump_skeys(const char *filename, Error **errp) { S390SKeysState *ss = s390_get_skeys_device(); S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); @@ -316,14 +317,6 @@ static void qemu_s390_skeys_class_init(ObjectClass *oc, void *data) dc->user_creatable = false; } -static const TypeInfo qemu_s390_skeys_info = { - .name = TYPE_QEMU_S390_SKEYS, - .parent = TYPE_S390_SKEYS, - .instance_size = sizeof(QEMUS390SKeysState), - .class_init = qemu_s390_skeys_class_init, - .class_size = sizeof(S390SKeysClass), -}; - static void s390_storage_keys_save(QEMUFile *f, void *opaque) { S390SKeysState *ss = S390_SKEYS(opaque); @@ -481,19 +474,27 @@ static void s390_skeys_class_init(ObjectClass *oc, void *data) set_bit(DEVICE_CATEGORY_MISC, dc->categories); } -static const TypeInfo s390_skeys_info = { - .name = TYPE_S390_SKEYS, - .parent = TYPE_DEVICE, - .instance_size = sizeof(S390SKeysState), - .class_init = s390_skeys_class_init, - .class_size = sizeof(S390SKeysClass), - .abstract = true, +static const TypeInfo s390_skeys_types[] = { + { + .name = TYPE_DUMP_SKEYS_INTERFACE, + .parent = TYPE_INTERFACE, + .class_size = sizeof(DumpSKeysInterface), + }, + { + .name = TYPE_S390_SKEYS, + .parent = TYPE_DEVICE, + .instance_size = sizeof(S390SKeysState), + .class_init = s390_skeys_class_init, + .class_size = sizeof(S390SKeysClass), + .abstract = true, + }, + { + .name = TYPE_QEMU_S390_SKEYS, + .parent = TYPE_S390_SKEYS, + .instance_size = sizeof(QEMUS390SKeysState), + .class_init = qemu_s390_skeys_class_init, + .class_size = sizeof(S390SKeysClass), + }, }; -static void qemu_s390_skeys_register_types(void) -{ - type_register_static(&s390_skeys_info); - type_register_static(&qemu_s390_skeys_info); -} - -type_init(qemu_s390_skeys_register_types) +DEFINE_TYPES(s390_skeys_types) diff --git a/hw/s390x/s390-stattrib-kvm.c b/hw/s390x/s390-stattrib-kvm.c index 2a8e317..d0ff043 100644 --- a/hw/s390x/s390-stattrib-kvm.c +++ b/hw/s390x/s390-stattrib-kvm.c @@ -185,7 +185,7 @@ static long long kvm_s390_stattrib_get_dirtycount(S390StAttribState *sa) static int kvm_s390_stattrib_get_active(S390StAttribState *sa) { - return kvm_s390_cmma_active() && sa->migration_enabled; + return kvm_s390_cmma_active(); } static void kvm_s390_stattrib_class_init(ObjectClass *oc, void *data) diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c index be07c28..35bf697 100644 --- a/hw/s390x/s390-stattrib.c +++ b/hw/s390x/s390-stattrib.c @@ -304,7 +304,7 @@ static int qemu_s390_set_migrationmode_stub(S390StAttribState *sa, bool value, static int qemu_s390_get_active(S390StAttribState *sa) { - return sa->migration_enabled; + return true; } static void qemu_s390_stattrib_class_init(ObjectClass *oc, void *data) @@ -360,10 +360,6 @@ static void s390_stattrib_realize(DeviceState *dev, Error **errp) &savevm_s390_stattrib_handlers, dev); } -static const Property s390_stattrib_props[] = { - DEFINE_PROP_BOOL("migration-enabled", S390StAttribState, migration_enabled, true), -}; - static void s390_stattrib_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -371,7 +367,6 @@ static void s390_stattrib_class_init(ObjectClass *oc, void *data) dc->hotpluggable = false; set_bit(DEVICE_CATEGORY_MISC, dc->categories); dc->realize = s390_stattrib_realize; - device_class_set_props(dc, s390_stattrib_props); } static void s390_stattrib_instance_init(Object *obj) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 75b3218..5af3c4f 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -810,6 +810,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) NMIClass *nc = NMI_CLASS(oc); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc); + DumpSKeysInterface *dsi = DUMP_SKEYS_INTERFACE_CLASS(oc); s390mc->hpage_1m_allowed = true; s390mc->max_threads = 1; @@ -835,6 +836,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) nc->nmi_monitor_handler = s390_nmi; mc->default_ram_id = "s390.ram"; mc->default_nic = "virtio-net-ccw"; + dsi->qmp_dump_skeys = s390_qmp_dump_skeys; object_class_property_add_bool(oc, "aes-key-wrap", machine_get_aes_key_wrap, @@ -876,6 +878,7 @@ static const TypeInfo ccw_machine_info = { .interfaces = (InterfaceInfo[]) { { TYPE_NMI }, { TYPE_HOTPLUG_HANDLER}, + { TYPE_DUMP_SKEYS_INTERFACE}, { } }, }; @@ -921,14 +924,26 @@ static const TypeInfo ccw_machine_info = { DEFINE_CCW_MACHINE_IMPL(false, major, minor) +static void ccw_machine_10_1_instance_options(MachineState *machine) +{ +} + +static void ccw_machine_10_1_class_options(MachineClass *mc) +{ +} +DEFINE_CCW_MACHINE_AS_LATEST(10, 1); + static void ccw_machine_10_0_instance_options(MachineState *machine) { + ccw_machine_10_1_instance_options(machine); } static void ccw_machine_10_0_class_options(MachineClass *mc) { + ccw_machine_10_1_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_10_0, hw_compat_10_0_len); } -DEFINE_CCW_MACHINE_AS_LATEST(10, 0); +DEFINE_CCW_MACHINE(10, 0); static void ccw_machine_9_2_instance_options(MachineState *machine) { @@ -1270,30 +1285,6 @@ static void ccw_machine_2_10_class_options(MachineClass *mc) } DEFINE_CCW_MACHINE(2, 10); -static void ccw_machine_2_9_instance_options(MachineState *machine) -{ - ccw_machine_2_10_instance_options(machine); - s390_cpudef_featoff_greater(12, 1, S390_FEAT_ESOP); - s390_cpudef_featoff_greater(12, 1, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2); - s390_cpudef_featoff_greater(12, 1, S390_FEAT_ZPCI); - s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_INT_SUPPRESSION); - s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_EVENT_NOTIFICATION); - css_migration_enabled = false; -} - -static void ccw_machine_2_9_class_options(MachineClass *mc) -{ - static GlobalProperty compat[] = { - { TYPE_S390_STATTRIB, "migration-enabled", "off", }, - { TYPE_S390_FLIC_COMMON, "migration-enabled", "off", }, - }; - - ccw_machine_2_10_class_options(mc); - compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); - compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); -} -DEFINE_CCW_MACHINE(2, 9); - #endif static void ccw_machine_register_types(void) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 8da1d5a..e59632e 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -68,10 +68,9 @@ struct SCSIDiskClass { SCSIDeviceClass parent_class; /* * Callbacks receive ret == 0 for success. Errors are represented either as - * negative errno values, or as positive SAM status codes. - * - * Beware: For errors returned in host_status, the function may directly - * complete the request and never call the callback. + * negative errno values, or as positive SAM status codes. For host_status + * errors, the function passes ret == -ENODEV and sets the host_status field + * of the SCSIRequest. */ DMAIOFunc *dma_readv; DMAIOFunc *dma_writev; @@ -225,11 +224,26 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed) SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s)); SCSISense sense = SENSE_CODE(NO_SENSE); + int16_t host_status; int error; bool req_has_sense = false; BlockErrorAction action; int status; + /* + * host_status should only be set for SG_IO requests that came back with a + * host_status error in scsi_block_sgio_complete(). This error path passes + * -ENODEV as the return value. + * + * Reset host_status in the request because we may still want to complete + * the request successfully with the 'stop' or 'ignore' error policy. + */ + host_status = r->req.host_status; + if (host_status != -1) { + assert(ret == -ENODEV); + r->req.host_status = -1; + } + if (ret < 0) { status = scsi_sense_from_errno(-ret, &sense); error = -ret; @@ -289,6 +303,10 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed) if (acct_failed) { block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct); } + if (host_status != -1) { + scsi_req_complete_failed(&r->req, host_status); + return true; + } if (req_has_sense) { sdc->update_sense(&r->req); } else if (status == CHECK_CONDITION) { @@ -409,7 +427,6 @@ done: scsi_req_unref(&r->req); } -/* May not be called in all error cases, don't rely on cleanup here */ static void scsi_dma_complete(void *opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; @@ -448,7 +465,6 @@ done: scsi_req_unref(&r->req); } -/* May not be called in all error cases, don't rely on cleanup here */ static void scsi_read_complete(void *opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; @@ -585,7 +601,6 @@ done: scsi_req_unref(&r->req); } -/* May not be called in all error cases, don't rely on cleanup here */ static void scsi_write_complete(void * opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; @@ -2846,14 +2861,10 @@ static void scsi_block_sgio_complete(void *opaque, int ret) sg_io_hdr_t *io_hdr = &req->io_header; if (ret == 0) { - /* FIXME This skips calling req->cb() and any cleanup in it */ if (io_hdr->host_status != SCSI_HOST_OK) { - scsi_req_complete_failed(&r->req, io_hdr->host_status); - scsi_req_unref(&r->req); - return; - } - - if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) { + r->req.host_status = io_hdr->host_status; + ret = -ENODEV; + } else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) { ret = BUSY; } else { ret = io_hdr->status; diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index 02a09eb..ad4cd67 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -1285,6 +1285,9 @@ static int save_opt_one(void *opaque, g_byte_array_append(data, (guint8 *)buf, ret); } + buf[0] = '\0'; + g_byte_array_append(data, (guint8 *)buf, 1); + qemu_close(fd); *opt->dest = g_renew(char *, *opt->dest, (*opt->ndest) + 1); diff --git a/hw/smbios/smbios_type_38.c b/hw/smbios/smbios_type_38.c index 168b886..e9b856f 100644 --- a/hw/smbios/smbios_type_38.c +++ b/hw/smbios/smbios_type_38.c @@ -72,7 +72,12 @@ static void smbios_build_one_type_38(IPMIFwInfo *info) " SMBIOS, ignoring this entry.", info->register_spacing); return; } - t->interrupt_number = info->interrupt_number; + if (info->irq_source == IPMI_ISA_IRQ) { + t->interrupt_number = info->interrupt_number; + } else { + /* TODO: How to handle PCI? */ + t->interrupt_number = 0; + } SMBIOS_BUILD_TABLE_POST; } diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index ee13eda..542f13b 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -1753,8 +1753,8 @@ static void ufs_init_hc(UfsHc *u) u->geometry_desc.length = sizeof(GeometryDescriptor); u->geometry_desc.descriptor_idn = UFS_QUERY_DESC_IDN_GEOMETRY; u->geometry_desc.max_number_lu = (UFS_MAX_LUS == 32) ? 0x1 : 0x0; - u->geometry_desc.segment_size = cpu_to_be32(0x2000); /* 4KB */ - u->geometry_desc.allocation_unit_size = 0x1; /* 4KB */ + u->geometry_desc.segment_size = cpu_to_be32(0x2000); /* 4MB: 8192 * 512B */ + u->geometry_desc.allocation_unit_size = 0x1; /* 4MB: 1 segment */ u->geometry_desc.min_addr_block_size = 0x8; /* 4KB */ u->geometry_desc.max_in_buffer_size = 0x8; u->geometry_desc.max_out_buffer_size = 0x8; |