On 4/4/20 11:44 PM, Nathan Chancellor wrote: > Hi Cédric, > > On Sat, Apr 04, 2020 at 05:36:55PM +0200, Cédric Le Goater wrote: >> Commit e2392d4395dd ("ppc/pnv: Create BMC devices at machine init") >> introduced default BMC devices which can be a problem when the same >> devices are defined on the command line with : >> >> -device ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10 >> >> QEMU fails with : >> >> qemu-system-ppc64: error creating device tree: node: FDT_ERR_EXISTS >> >> Use defaults_enabled() when creating the default BMC devices to let >> the user provide its own BMC devices using '-nodefaults'. If no BMC >> device are provided, output a warning but let QEMU run as this is a >> supported configuration. However, when multiple BMC devices are >> defined, stop QEMU with a clear error as the results are unexpected. >> >> Fixes: e2392d4395dd ("ppc/pnv: Create BMC devices at machine init") >> Reported-by: Nathan Chancellor <natechancel...@gmail.com> >> Signed-off-by: Cédric Le Goater <c...@kaod.org> > > This fixes my issue when -nodefaults is passed and that does not regress > QEMU 3.1.0 or 4.2.0. Thank you for the quick fix! > > Tested-by: Nathan Chancellor <natechancel...@gmail.com> > > A few comments inline. > >> --- >> include/hw/ppc/pnv.h | 2 ++ >> hw/ppc/pnv.c | 32 ++++++++++++++++++++++++++----- >> hw/ppc/pnv_bmc.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 74 insertions(+), 5 deletions(-) >> >> diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h >> index fb4d0c0234b3..d4b0b0e2ff71 100644 >> --- a/include/hw/ppc/pnv.h >> +++ b/include/hw/ppc/pnv.h >> @@ -241,6 +241,8 @@ struct PnvMachineState { >> void pnv_dt_bmc_sensors(IPMIBmc *bmc, void *fdt); >> void pnv_bmc_powerdown(IPMIBmc *bmc); >> IPMIBmc *pnv_bmc_create(PnvPnor *pnor); >> +IPMIBmc *pnv_bmc_find(Error **errp); >> +void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor); >> >> /* >> * POWER8 MMIO base addresses >> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c >> index ac83b8698b8e..a3b7a8d0ff32 100644 >> --- a/hw/ppc/pnv.c >> +++ b/hw/ppc/pnv.c >> @@ -573,10 +573,29 @@ static void pnv_powerdown_notify(Notifier *n, void >> *opaque) >> >> static void pnv_reset(MachineState *machine) >> { >> + PnvMachineState *pnv = PNV_MACHINE(machine); >> + IPMIBmc *bmc; >> void *fdt; >> >> qemu_devices_reset(); >> >> + /* >> + * The machine should provide by default an internal BMC simulator. >> + * If not, try to use the BMC device that was provided on the command >> + * line. >> + */ >> + bmc = pnv_bmc_find(&error_fatal); >> + if (!pnv->bmc) { >> + if (!bmc) { >> + warn_report("machine has no BMC device. Use '-device " >> + "ipmi-bmc-sim,id=bmc0 -device >> isa-ipmi-bt,bmc=bmc0,irq=10' " >> + "to define one"); > > If I pass no -device flags + -nodefaults, I don't see this message. Is > that expected?
yes. Because the machine instantiates the default BMC devices. > >> + } else { >> + pnv_bmc_set_pnor(bmc, pnv->pnor); >> + pnv->bmc = bmc; >> + } >> + } >> + >> fdt = pnv_dt_create(machine); >> >> /* Pack resulting tree */ >> @@ -835,9 +854,6 @@ static void pnv_init(MachineState *machine) >> } >> g_free(chip_typename); >> >> - /* Create the machine BMC simulator */ >> - pnv->bmc = pnv_bmc_create(pnv->pnor); >> - >> /* Instantiate ISA bus on chip 0 */ >> pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); >> >> @@ -847,8 +863,14 @@ static void pnv_init(MachineState *machine) >> /* Create an RTC ISA device too */ >> mc146818_rtc_init(pnv->isa_bus, 2000, NULL); >> >> - /* Create the IPMI BT device for communication with the BMC */ >> - pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); >> + /* >> + * Create the machine BMC simulator and the IPMI BT device for >> + * communication with the BMC >> + */ >> + if (defaults_enabled()) { >> + pnv->bmc = pnv_bmc_create(pnv->pnor); >> + pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); >> + } >> >> /* >> * OpenPOWER systems use a IPMI SEL Event message to notify the >> diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c >> index 8863354c1c08..4e018b8b70e4 100644 >> --- a/hw/ppc/pnv_bmc.c >> +++ b/hw/ppc/pnv_bmc.c >> @@ -213,6 +213,18 @@ static const IPMINetfn hiomap_netfn = { >> .cmd_handlers = hiomap_cmds >> }; >> >> + >> +void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor) >> +{ >> + object_ref(OBJECT(pnor)); >> + object_property_add_const_link(OBJECT(bmc), "pnor", OBJECT(pnor), >> + &error_abort); >> + >> + /* Install the HIOMAP protocol handlers to access the PNOR */ >> + ipmi_sim_register_netfn(IPMI_BMC_SIMULATOR(bmc), IPMI_NETFN_OEM, >> + &hiomap_netfn); >> +} >> + >> /* >> * Instantiate the machine BMC. PowerNV uses the QEMU internal >> * simulator but it could also be external. >> @@ -232,3 +244,36 @@ IPMIBmc *pnv_bmc_create(PnvPnor *pnor) >> >> return IPMI_BMC(obj); >> } >> + >> +typedef struct ForeachArgs { >> + const char *name; >> + Object *obj; >> +} ForeachArgs; >> + >> +static int bmc_find(Object *child, void *opaque) >> +{ >> + ForeachArgs *args = opaque; >> + >> + if (object_dynamic_cast(child, args->name)) { >> + if (args->obj) { >> + return 1; >> + } >> + args->obj = child; >> + } >> + return 0; >> +} >> + >> +IPMIBmc *pnv_bmc_find(Error **errp) >> +{ >> + ForeachArgs args = { TYPE_IPMI_BMC_SIMULATOR, NULL }; >> + int ret; >> + >> + ret = object_child_foreach_recursive(object_get_root(), bmc_find, >> &args); >> + if (ret) { >> + error_setg(errp, "machine should have only one BMC device. " >> + "Use '-nodefaults'"); > > When passing the -device flags in the commit message as I did in my > original command without -nodefaults, I still see the > > qemu-system-ppc64: error creating device tree: node: FDT_ERR_EXISTS > > message. Is that expected? object_child_foreach_recursive() is broken. Here is the fix : http://patchwork.ozlabs.org/patch/1266419/ Sorry. I should have copied you. But there are other ways to find multiple instances of the same type. May be we will need to rework that part a bit. Thanks, C. > >> + return NULL; >> + } >> + >> + return args.obj ? IPMI_BMC(args.obj) : NULL; >> +} >> -- >> 2.25.1 >>