diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 2edb7d1e9c..66b965a0a7 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -22,6 +22,7 @@ #include "qemu/error-report.h" #include "hw/ppc/spapr.h" /* for RTAS return codes */ #include "hw/pci-host/spapr.h" /* spapr_phb_remove_pci_device_cb callback */ +#include "sysemu/device_tree.h" #include "trace.h" #define DRC_CONTAINER_PATH "/dr-connector" @@ -376,6 +377,8 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, int fdt_start_offset, Error **errp) { + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + trace_spapr_drc_attach(spapr_drc_index(drc)); if (drc->dev) { @@ -384,11 +387,14 @@ void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, } g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE) || (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON)); - g_assert(fdt); + g_assert(fdt || drck->dt_populate); drc->dev = d; - drc->fdt = fdt; - drc->fdt_start_offset = fdt_start_offset; + + if (fdt) { + drc->fdt = fdt; + drc->fdt_start_offset = fdt_start_offset; + } object_property_add_link(OBJECT(drc), "device", object_get_typename(OBJECT(drc->dev)), @@ -1102,10 +1108,30 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu, goto out; } - g_assert(drc->fdt); - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + g_assert(drc->fdt || drck->dt_populate); + + if (!drc->fdt) { + Error *local_err = NULL; + void *fdt; + int fdt_size; + + fdt = create_device_tree(&fdt_size); + + if (drck->dt_populate(drc, spapr, fdt, &drc->fdt_start_offset, + &local_err)) { + g_free(fdt); + error_free(local_err); + rc = SPAPR_DR_CC_RESPONSE_ERROR; + goto out; + } + + drc->fdt = fdt; + drc->ccs_offset = drc->fdt_start_offset; + drc->ccs_depth = 0; + } + do { uint32_t tag; const char *name; diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index f6ff32e7e2..2aa919f0cf 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -18,6 +18,7 @@ #include "qom/object.h" #include "sysemu/sysemu.h" #include "hw/qdev.h" +#include "qapi/error.h" #define TYPE_SPAPR_DR_CONNECTOR "spapr-dr-connector" #define SPAPR_DR_CONNECTOR_GET_CLASS(obj) \ @@ -213,6 +214,8 @@ typedef struct sPAPRDRConnector { int fdt_start_offset; } sPAPRDRConnector; +struct sPAPRMachineState; + typedef struct sPAPRDRConnectorClass { /*< private >*/ DeviceClass parent; @@ -228,6 +231,9 @@ typedef struct sPAPRDRConnectorClass { uint32_t (*isolate)(sPAPRDRConnector *drc); uint32_t (*unisolate)(sPAPRDRConnector *drc); void (*release)(DeviceState *dev); + + int (*dt_populate)(sPAPRDRConnector *drc, struct sPAPRMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp); } sPAPRDRConnectorClass; typedef struct sPAPRDRCPhysical {