diff options
Diffstat (limited to 'hw/ppc')
| -rw-r--r-- | hw/ppc/e500.c | 1 | ||||
| -rw-r--r-- | hw/ppc/ppc.c | 6 | ||||
| -rw-r--r-- | hw/ppc/spapr.c | 186 | ||||
| -rw-r--r-- | hw/ppc/spapr_drc.c | 8 | ||||
| -rw-r--r-- | hw/ppc/spapr_events.c | 21 | ||||
| -rw-r--r-- | hw/ppc/spapr_hcall.c | 7 | ||||
| -rw-r--r-- | hw/ppc/spapr_irq.c | 2 | ||||
| -rw-r--r-- | hw/ppc/spapr_nvdimm.c | 11 | ||||
| -rw-r--r-- | hw/ppc/spapr_pci.c | 48 | ||||
| -rw-r--r-- | hw/ppc/trace-events | 2 |
10 files changed, 167 insertions, 125 deletions
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 6a64eb31ab..072e558c2d 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -926,6 +926,7 @@ void ppce500_init(MachineState *machine) ccsr_addr_space); mpicdev = ppce500_init_mpic(pms, ccsr_addr_space, irqs); + g_free(irqs); /* Serial */ if (serial_hd(0)) { diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 4a11fb1640..5cbbff1f8d 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -120,6 +120,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level) } else { cpu_ppc_tb_stop(env); } + break; case PPC6xx_INPUT_INT: /* Level sensitive - active high */ LOG_IRQ("%s: set the external IRQ state to %d\n", @@ -1026,7 +1027,8 @@ static void timebase_save(PPCTimebase *tb) */ tb->guest_timebase = ticks + first_ppc_cpu->env.tb_env->tb_offset; - tb->runstate_paused = runstate_check(RUN_STATE_PAUSED); + tb->runstate_paused = + runstate_check(RUN_STATE_PAUSED) || runstate_check(RUN_STATE_SAVE_VM); } static void timebase_load(PPCTimebase *tb) @@ -1087,7 +1089,7 @@ static int timebase_pre_save(void *opaque) { PPCTimebase *tb = opaque; - /* guest_timebase won't be overridden in case of paused guest */ + /* guest_timebase won't be overridden in case of paused guest or savevm */ if (!tb->runstate_paused) { timebase_save(tb); } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 6abb45d0ed..dee48a0043 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3021,17 +3021,25 @@ static void spapr_machine_init(MachineState *machine) qemu_cond_init(&spapr->fwnmi_machine_check_interlock_cond); } +#define DEFAULT_KVM_TYPE "auto" static int spapr_kvm_type(MachineState *machine, const char *vm_type) { - if (!vm_type) { + /* + * The use of g_ascii_strcasecmp() for 'hv' and 'pr' is to + * accomodate the 'HV' and 'PV' formats that exists in the + * wild. The 'auto' mode is being introduced already as + * lower-case, thus we don't need to bother checking for + * "AUTO". + */ + if (!vm_type || !strcmp(vm_type, DEFAULT_KVM_TYPE)) { return 0; } - if (!strcmp(vm_type, "HV")) { + if (!g_ascii_strcasecmp(vm_type, "hv")) { return 1; } - if (!strcmp(vm_type, "PR")) { + if (!g_ascii_strcasecmp(vm_type, "pr")) { return 2; } @@ -3270,10 +3278,15 @@ static void spapr_instance_init(Object *obj) spapr->htab_fd = -1; spapr->use_hotplug_event_source = true; + spapr->kvm_type = g_strdup(DEFAULT_KVM_TYPE); object_property_add_str(obj, "kvm-type", spapr_get_kvm_type, spapr_set_kvm_type); object_property_set_description(obj, "kvm-type", - "Specifies the KVM virtualization mode (HV, PR)"); + "Specifies the KVM virtualization mode (auto," + " hv, pr). Defaults to 'auto'. This mode will use" + " any available KVM module loaded in the host," + " where kvm_hv takes precedence if both kvm_hv and" + " kvm_pr are loaded."); object_property_add_bool(obj, "modern-hotplug-events", spapr_get_modern_hotplug_events, spapr_set_modern_hotplug_events); @@ -3379,8 +3392,8 @@ int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, return 0; } -static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, - bool dedicated_hp_event_source, Error **errp) +static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, + bool dedicated_hp_event_source) { SpaprDrc *drc; uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; @@ -3393,15 +3406,12 @@ static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); - if (!spapr_drc_attach(drc, dev, errp)) { - while (addr > addr_start) { - addr -= SPAPR_MEMORY_BLOCK_SIZE; - drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, - addr / SPAPR_MEMORY_BLOCK_SIZE); - spapr_drc_detach(drc); - } - return false; - } + /* + * memory_device_get_free_addr() provided a range of free addresses + * that doesn't overlap with any existing mapping at pre-plug. The + * corresponding LMB DRCs are thus assumed to be all attachable. + */ + spapr_drc_attach(drc, dev); if (!hotplugged) { spapr_drc_reset(drc); } @@ -3422,11 +3432,9 @@ static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, nr_lmbs); } } - return true; } -static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) +static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev) { SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev); PCDIMMDevice *dimm = PC_DIMM(dev); @@ -3441,24 +3449,15 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, if (!is_nvdimm) { addr = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, &error_abort); - if (!spapr_add_lmbs(dev, addr, size, - spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), errp)) { - goto out_unplug; - } + spapr_add_lmbs(dev, addr, size, + spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT)); } else { slot = object_property_get_int(OBJECT(dimm), PC_DIMM_SLOT_PROP, &error_abort); /* We should have valid slot number at this point */ g_assert(slot >= 0); - if (!spapr_add_nvdimm(dev, slot, errp)) { - goto out_unplug; - } + spapr_add_nvdimm(dev, slot); } - - return; - -out_unplug: - pc_dimm_unplug(dimm, MACHINE(ms)); } static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, @@ -3752,8 +3751,7 @@ int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, return 0; } -static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) +static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev) { SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); MachineClass *mc = MACHINE_GET_CLASS(spapr); @@ -3768,20 +3766,20 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, int i; core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); - if (!core_slot) { - error_setg(errp, "Unable to find CPU core with core-id: %d", - cc->core_id); - return; - } + g_assert(core_slot); /* Already checked in spapr_core_pre_plug() */ + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, spapr_vcpu_id(spapr, cc->core_id)); g_assert(drc || !mc->has_hotpluggable_cpus); if (drc) { - if (!spapr_drc_attach(drc, dev, errp)) { - return; - } + /* + * spapr_core_pre_plug() already buys us this is a brand new + * core being plugged into a free slot. Nothing should already + * be attached to the corresponding DRC. + */ + spapr_drc_attach(drc, dev); if (hotplugged) { /* @@ -3796,24 +3794,22 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, core_slot->cpu = OBJECT(dev); - if (smc->pre_2_10_has_unused_icps) { - for (i = 0; i < cc->nr_threads; i++) { - cs = CPU(core->threads[i]); - pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); - } - } - /* * Set compatibility mode to match the boot CPU, which was either set - * by the machine reset code or by CAS. + * by the machine reset code or by CAS. This really shouldn't fail at + * this point. */ if (hotplugged) { for (i = 0; i < cc->nr_threads; i++) { - if (ppc_set_compat(core->threads[i], - POWERPC_CPU(first_cpu)->compat_pvr, - errp) < 0) { - return; - } + ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr, + &error_abort); + } + } + + if (smc->pre_2_10_has_unused_icps) { + for (i = 0; i < cc->nr_threads; i++) { + cs = CPU(core->threads[i]); + pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); } } } @@ -3893,38 +3889,45 @@ int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, return 0; } -static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, +static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); const unsigned windows_supported = spapr_phb_windows_supported(sphb); + SpaprDrc *drc; if (dev->hotplugged && !smc->dr_phb_enabled) { error_setg(errp, "PHB hotplug not supported for this machine"); - return; + return false; } if (sphb->index == (uint32_t)-1) { error_setg(errp, "\"index\" for PAPR PHB is mandatory"); - return; + return false; + } + + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); + if (drc && drc->dev) { + error_setg(errp, "PHB %d already attached", sphb->index); + return false; } /* * This will check that sphb->index doesn't exceed the maximum number of * PHBs for the current machine type. */ - smc->phb_placement(spapr, sphb->index, - &sphb->buid, &sphb->io_win_addr, - &sphb->mem_win_addr, &sphb->mem64_win_addr, - windows_supported, sphb->dma_liobn, - &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr, - errp); + return + smc->phb_placement(spapr, sphb->index, + &sphb->buid, &sphb->io_win_addr, + &sphb->mem_win_addr, &sphb->mem64_win_addr, + windows_supported, sphb->dma_liobn, + &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr, + errp); } -static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) +static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev) { SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); @@ -3940,9 +3943,8 @@ static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, /* hotplug hooks should check it's enabled before getting this far */ assert(drc); - if (!spapr_drc_attach(drc, dev, errp)) { - return; - } + /* spapr_phb_pre_plug() already checked the DRC is attachable */ + spapr_drc_attach(drc, dev); if (hotplugged) { spapr_hotplug_req_add_by_index(drc); @@ -3979,17 +3981,28 @@ static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, } } -static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) +static +bool spapr_tpm_proxy_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) { SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); - SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); if (spapr->tpm_proxy != NULL) { error_setg(errp, "Only one TPM proxy can be specified for this machine"); - return; + return false; } + return true; +} + +static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev) +{ + SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); + SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); + + /* Already checked in spapr_tpm_proxy_pre_plug() */ + g_assert(spapr->tpm_proxy == NULL); + spapr->tpm_proxy = tpm_proxy; } @@ -4006,13 +4019,13 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { - spapr_memory_plug(hotplug_dev, dev, errp); + spapr_memory_plug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { - spapr_core_plug(hotplug_dev, dev, errp); + spapr_core_plug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { - spapr_phb_plug(hotplug_dev, dev, errp); + spapr_phb_plug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { - spapr_tpm_proxy_plug(hotplug_dev, dev, errp); + spapr_tpm_proxy_plug(hotplug_dev, dev); } } @@ -4075,6 +4088,8 @@ static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, spapr_core_pre_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { spapr_phb_pre_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { + spapr_tpm_proxy_pre_plug(hotplug_dev, dev, errp); } } @@ -4158,7 +4173,7 @@ static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) return machine->possible_cpus; } -static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, +static bool spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, uint64_t *buid, hwaddr *pio, hwaddr *mmio32, hwaddr *mmio64, unsigned n_dma, uint32_t *liobns, @@ -4196,7 +4211,7 @@ static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, if (index >= SPAPR_MAX_PHBS) { error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", SPAPR_MAX_PHBS - 1); - return; + return false; } *buid = base_buid + index; @@ -4210,6 +4225,7 @@ static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE; *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE; + return true; } static ICSState *spapr_ics_get(XICSFabric *dev, int irq) @@ -4600,18 +4616,21 @@ DEFINE_SPAPR_MACHINE(4_1, "4.1", false); /* * pseries-4.0 */ -static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, +static bool phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, uint64_t *buid, hwaddr *pio, hwaddr *mmio32, hwaddr *mmio64, unsigned n_dma, uint32_t *liobns, hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) { - spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns, - nv2gpa, nv2atsd, errp); + if (!spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, + liobns, nv2gpa, nv2atsd, errp)) { + return false; + } + *nv2gpa = 0; *nv2atsd = 0; + return true; } - static void spapr_machine_4_0_class_options(MachineClass *mc) { SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); @@ -4771,7 +4790,7 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", false); * pseries-2.7 */ -static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, +static bool phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, uint64_t *buid, hwaddr *pio, hwaddr *mmio32, hwaddr *mmio64, unsigned n_dma, uint32_t *liobns, @@ -4803,7 +4822,7 @@ static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, if (index > max_index) { error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", max_index); - return; + return false; } *buid = base_buid + index; @@ -4822,6 +4841,7 @@ static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, *nv2gpa = 0; *nv2atsd = 0; + return true; } static void spapr_machine_2_7_class_options(MachineClass *mc) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 77718cde1f..f991cf89a0 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -369,14 +369,11 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, } while (fdt_depth != 0); } -bool spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp) +void spapr_drc_attach(SpaprDrc *drc, DeviceState *d) { trace_spapr_drc_attach(spapr_drc_index(drc)); - if (drc->dev) { - error_setg(errp, "an attached device is still awaiting release"); - return false; - } + g_assert(!drc->dev); g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE) || (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON)); @@ -386,7 +383,6 @@ bool spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp) object_get_typename(OBJECT(drc->dev)), (Object **)(&drc->dev), NULL, 0); - return true; } static void spapr_drc_release(SpaprDrc *drc) diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 1add53547e..3f37b49fd8 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -480,9 +480,8 @@ static SpaprEventLogEntry *rtas_event_log_dequeue(SpaprMachineState *spapr, return entry; } -static bool rtas_event_log_contains(uint32_t event_mask) +static bool rtas_event_log_contains(SpaprMachineState *spapr, uint32_t event_mask) { - SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); SpaprEventLogEntry *entry = NULL; QTAILQ_FOREACH(entry, &spapr->pending_events, next) { @@ -509,10 +508,10 @@ static void spapr_init_v6hdr(struct rtas_event_log_v6 *v6hdr) v6hdr->company = cpu_to_be32(RTAS_LOG_V6_COMPANY_IBM); } -static void spapr_init_maina(struct rtas_event_log_v6_maina *maina, +static void spapr_init_maina(SpaprMachineState *spapr, + struct rtas_event_log_v6_maina *maina, int section_count) { - SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); struct tm tm; int year; @@ -560,7 +559,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque) entry->extended_length = sizeof(*new_epow); spapr_init_v6hdr(v6hdr); - spapr_init_maina(maina, 3 /* Main-A, Main-B and EPOW */); + spapr_init_maina(spapr, maina, 3 /* Main-A, Main-B and EPOW */); mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB); mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb)); @@ -613,7 +612,7 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action, entry->extended_length = sizeof(*new_hp); spapr_init_v6hdr(v6hdr); - spapr_init_maina(maina, 3 /* Main-A, Main-B, HP */); + spapr_init_maina(spapr, maina, 3 /* Main-A, Main-B, HP */); mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB); mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb)); @@ -808,9 +807,9 @@ static uint32_t spapr_mce_get_elog_type(PowerPCCPU *cpu, bool recovered, return summary; } -static void spapr_mce_dispatch_elog(PowerPCCPU *cpu, bool recovered) +static void spapr_mce_dispatch_elog(SpaprMachineState *spapr, PowerPCCPU *cpu, + bool recovered) { - SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; uint64_t rtas_addr; @@ -927,7 +926,7 @@ void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered) warn_report("Received a fwnmi while migration was in progress"); } - spapr_mce_dispatch_elog(cpu, recovered); + spapr_mce_dispatch_elog(spapr, cpu, recovered); } static void check_exception(PowerPCCPU *cpu, SpaprMachineState *spapr, @@ -980,7 +979,7 @@ static void check_exception(PowerPCCPU *cpu, SpaprMachineState *spapr, * interrupts. */ for (i = 0; i < EVENT_CLASS_MAX; i++) { - if (rtas_event_log_contains(EVENT_CLASS_MASK(i))) { + if (rtas_event_log_contains(spapr, EVENT_CLASS_MASK(i))) { const SpaprEventSource *source = spapr_event_sources_get_source(spapr->event_sources, i); @@ -1007,7 +1006,7 @@ static void event_scan(PowerPCCPU *cpu, SpaprMachineState *spapr, } for (i = 0; i < EVENT_CLASS_MAX; i++) { - if (rtas_event_log_contains(EVENT_CLASS_MASK(i))) { + if (rtas_event_log_contains(spapr, EVENT_CLASS_MASK(i))) { const SpaprEventSource *source = spapr_event_sources_get_source(spapr->event_sources, i); diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 1d8e8e6a88..c0ea0bd579 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1351,6 +1351,7 @@ static target_ulong h_logical_dcbf(PowerPCCPU *cpu, SpaprMachineState *spapr, } static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu, + SpaprMachineState *spapr, target_ulong mflags, target_ulong value1, target_ulong value2) @@ -1365,12 +1366,12 @@ static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu, switch (mflags) { case H_SET_MODE_ENDIAN_BIG: spapr_set_all_lpcrs(0, LPCR_ILE); - spapr_pci_switch_vga(true); + spapr_pci_switch_vga(spapr, true); return H_SUCCESS; case H_SET_MODE_ENDIAN_LITTLE: spapr_set_all_lpcrs(LPCR_ILE, LPCR_ILE); - spapr_pci_switch_vga(false); + spapr_pci_switch_vga(spapr, false); return H_SUCCESS; } @@ -1411,7 +1412,7 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, SpaprMachineState *spapr, switch (resource) { case H_SET_MODE_RESOURCE_LE: - ret = h_set_mode_resource_le(cpu, args[0], args[2], args[3]); + ret = h_set_mode_resource_le(cpu, spapr, args[0], args[2], args[3]); break; case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE: ret = h_set_mode_resource_addr_trans_mode(cpu, args[0], diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index f59960339e..a0d1e1298e 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -186,7 +186,7 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp) if (kvm_enabled() && spapr->irq == &spapr_irq_dual && kvm_kernel_irqchip_required() && - xics_kvm_has_broken_disconnect(spapr)) { + xics_kvm_has_broken_disconnect()) { error_setg(errp, "KVM is incompatible with ic-mode=dual,kernel-irqchip=on"); error_append_hint(errp, diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c index a833a63b5e..73ee006541 100644 --- a/hw/ppc/spapr_nvdimm.c +++ b/hw/ppc/spapr_nvdimm.c @@ -89,7 +89,7 @@ bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm, } -bool spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp) +void spapr_add_nvdimm(DeviceState *dev, uint64_t slot) { SpaprDrc *drc; bool hotplugged = spapr_drc_hotplugged(dev); @@ -97,14 +97,15 @@ bool spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp) drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PMEM, slot); g_assert(drc); - if (!spapr_drc_attach(drc, dev, errp)) { - return false; - } + /* + * pc_dimm_get_free_slot() provided a free slot at pre-plug. The + * corresponding DRC is thus assumed to be attachable. + */ + spapr_drc_attach(drc, dev); if (hotplugged) { spapr_hotplug_req_add_by_index(drc); } - return true; } static int spapr_dt_nvdimm(SpaprMachineState *spapr, void *fdt, diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 88ce87f130..76d7c91e9c 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -747,7 +747,7 @@ static PCIINTxRoute spapr_route_intx_pin_to_irq(void *opaque, int pin) static void spapr_msi_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { - SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); + SpaprMachineState *spapr = opaque; uint32_t irq = data; trace_spapr_pci_msi_write(addr, data, irq); @@ -1532,8 +1532,8 @@ static bool bridge_has_valid_chassis_nr(Object *bridge, Error **errp) return true; } -static void spapr_pci_plug(HotplugHandler *plug_handler, - DeviceState *plugged_dev, Error **errp) +static void spapr_pci_pre_plug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, Error **errp) { SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler)); PCIDevice *pdev = PCI_DEVICE(plugged_dev); @@ -1542,9 +1542,6 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev))); uint32_t slotnr = PCI_SLOT(pdev->devfn); - /* if DR is disabled we don't need to do anything in the case of - * hotplug or coldplug callbacks - */ if (!phb->dr_enabled) { /* if this is a hotplug operation initiated by the user * we need to let them know it's not enabled @@ -1552,17 +1549,14 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, if (plugged_dev->hotplugged) { error_setg(errp, QERR_BUS_NO_HOTPLUG, object_get_typename(OBJECT(phb))); + return; } - return; } - g_assert(drc); - if (pc->is_bridge) { if (!bridge_has_valid_chassis_nr(OBJECT(plugged_dev), errp)) { return; } - spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev)); } /* Following the QEMU convention used for PCIe multifunction @@ -1574,13 +1568,41 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, error_setg(errp, "PCI: slot %d function 0 already occupied by %s," " additional functions can no longer be exposed to guest.", slotnr, bus->devices[PCI_DEVFN(slotnr, 0)]->name); + } + + if (drc && drc->dev) { + error_setg(errp, "PCI: slot %d already occupied by %s", slotnr, + pci_get_function_0(PCI_DEVICE(drc->dev))->name); return; } +} + +static void spapr_pci_plug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, Error **errp) +{ + SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler)); + PCIDevice *pdev = PCI_DEVICE(plugged_dev); + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(plugged_dev); + SpaprDrc *drc = drc_from_dev(phb, pdev); + uint32_t slotnr = PCI_SLOT(pdev->devfn); - if (!spapr_drc_attach(drc, DEVICE(pdev), errp)) { + /* + * If DR is disabled we don't need to do anything in the case of + * hotplug or coldplug callbacks. + */ + if (!phb->dr_enabled) { return; } + g_assert(drc); + + if (pc->is_bridge) { + spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev)); + } + + /* spapr_pci_pre_plug() already checked the DRC is attachable */ + spapr_drc_attach(drc, DEVICE(pdev)); + /* If this is function 0, signal hotplug for all the device functions. * Otherwise defer sending the hotplug event. */ @@ -2223,6 +2245,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) /* Supported by TYPE_SPAPR_MACHINE */ dc->user_creatable = true; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + hp->pre_plug = spapr_pci_pre_plug; hp->plug = spapr_pci_plug; hp->unplug = spapr_pci_unplug; hp->unplug_request = spapr_pci_unplug_request; @@ -2470,9 +2493,8 @@ static int spapr_switch_one_vga(DeviceState *dev, void *opaque) return 0; } -void spapr_pci_switch_vga(bool big_endian) +void spapr_pci_switch_vga(SpaprMachineState *spapr, bool big_endian) { - SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); SpaprPhbState *sphb; /* diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index dcc06d49b5..6d8d095aa2 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -19,7 +19,7 @@ spapr_update_dt_failed_size(unsigned cbold, unsigned cbnew, unsigned magic) "Old spapr_update_dt_failed_check(unsigned cbold, unsigned cbnew, unsigned magic) "Old blob %u bytes, new blob %u bytes, magic 0x%x" # spapr_tpm_proxy.c -spapr_h_tpm_comm(const char *device_path, uint64_t operation) "tpm_device_path=%s operation=0x%"PRIu64 +spapr_h_tpm_comm(const char *device_path, uint64_t operation) "tpm_device_path=%s operation=0x%"PRIx64 spapr_tpm_execute(uint64_t data_in, uint64_t data_in_sz, uint64_t data_out, uint64_t data_out_sz) "data_in=0x%"PRIx64", data_in_sz=%"PRIu64", data_out=0x%"PRIx64", data_out_sz=%"PRIu64 # spapr_iommu.c |