include/hw/ppc/pnv.h | 2 ++ hw/ppc/pnv.c | 32 ++++++++++++++++++++++++++----- hw/ppc/pnv_bmc.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 5 deletions(-)
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 <natechancellor@gmail.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
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");
+ } 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'");
+ return NULL;
+ }
+
+ return args.obj ? IPMI_BMC(args.obj) : NULL;
+}
--
2.25.1
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 <natechancellor@gmail.com> > Signed-off-by: Cédric Le Goater <clg@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 <natechancellor@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? > + } 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? > + return NULL; > + } > + > + return args.obj ? IPMI_BMC(args.obj) : NULL; > +} > -- > 2.25.1 >
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 <natechancellor@gmail.com> >> Signed-off-by: Cédric Le Goater <clg@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 <natechancellor@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 >>
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 <natechancellor@gmail.com> > Signed-off-by: Cédric Le Goater <clg@kaod.org> As a regression fix, applied to ppc-for-5.0. > --- > 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"); > + } 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'"); > + return NULL; > + } > + > + return args.obj ? IPMI_BMC(args.obj) : NULL; > +} -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
© 2016 - 2024 Red Hat, Inc.