As a rough outline for a pnv-phb device, I'd aim for creating a proxy for the
underlying device rather than manually invoking the QOM instance and
qdev-related functions:
struct PnvPHB {
....
uint32_t version;
Object *phb_dev; /* Could be PHBCommonBase if it exists */
};
DECLARE_SIMPLE_OBJECT_TYPE(...)
...
...
static Property pnv_phb_properties[] = {
DEFINE_PROP_UINT32("version", PnvPHB, version, 0),
DEFINE_PROP_END_OF_LIST(),
};
static void pnv_phb_realize(DeviceState *dev, Error **errp)
{
PnvPHB *pnv_phb = PNV_PHB(dev);
g_autofree char *phb_typename;
if (!pnv_phb->version) {
error_setg("version not specified", errp);
return;
}
switch (pnv_phb->version) {
case 3:
phb_typename = g_strdup(TYPE_PNV_PHB3);
break;
case 4:
phb_typename = g_strdup(TYPE_PNV_PHB4);
break;
default:
g_assert_unreached();
}
pnv_phb->phb_dev = object_new(phb_typename);
object_property_add_child(OBJECT(dev), "phb-device", pnv_phb->phb_dev);
if (!qdev_realize(DEVICE(pnv_phb->phb_dev), errp)) {
return;
}
/* Passthrough child device properties to the proxy device */
qdev_alias_all_properties(dev, OBJECT(pnv_phb->phb_dev));
}
Finally you can set the pnv-phb version on a per-machine basis by adding the
version to the machine compat_props:
static GlobalProperty compat[] = {
{ TYPE_PHB_PNV, "version", 3},
};