Skip to content

Commit

Permalink
ppc/pnv: Create BMC devices only when defaults are enabled
Browse files Browse the repository at this point in the history
Commit e2392d4 ("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: e2392d4 ("ppc/pnv: Create BMC devices at machine init")
Reported-by: Nathan Chancellor <[email protected]>
Signed-off-by: Cédric Le Goater <[email protected]>
Message-Id: <[email protected]>
Tested-by: Nathan Chancellor <[email protected]>
Signed-off-by: David Gibson <[email protected]>
  • Loading branch information
legoater authored and dgibson committed Apr 6, 2020
1 parent a872e43 commit 25f3170
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 5 deletions.
32 changes: 27 additions & 5 deletions hw/ppc/pnv.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,10 +571,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 */
Expand Down Expand Up @@ -833,9 +852,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);

Expand All @@ -845,8 +861,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
Expand Down
45 changes: 45 additions & 0 deletions hw/ppc/pnv_bmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 changes: 2 additions & 0 deletions include/hw/ppc/pnv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 25f3170

Please sign in to comment.