From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42147) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yn02z-0001fi-Dt for qemu-devel@nongnu.org; Tue, 28 Apr 2015 03:35:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Yn02p-0006dC-FD for qemu-devel@nongnu.org; Tue, 28 Apr 2015 03:35:13 -0400 Date: Tue, 28 Apr 2015 17:23:43 +1000 From: David Gibson Message-ID: <20150428072343.GA24753@voom.redhat.com> References: <1429684100-13354-1-git-send-email-mdroth@linux.vnet.ibm.com> <1429684100-13354-8-git-send-email-mdroth@linux.vnet.ibm.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="FL5UXtIhxfXey3p5" Content-Disposition: inline In-Reply-To: <1429684100-13354-8-git-send-email-mdroth@linux.vnet.ibm.com> Subject: Re: [Qemu-devel] [PATCH v8 07/16] spapr_rtas: add ibm, configure-connector RTAS interface List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Michael Roth Cc: aik@ozlabs.ru, qemu-devel@nongnu.org, agraf@suse.de, qemu-ppc@nongnu.org, tyreld@linux.vnet.ibm.com, bharata.rao@gmail.com, nfont@linux.vnet.ibm.com --FL5UXtIhxfXey3p5 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Wed, Apr 22, 2015 at 01:28:11AM -0500, Michael Roth wrote: > This interface is used to fetch an OF device-tree nodes that describes a > newly-attached device to guest. It is called multiple times to walk the > device-tree node and fetch individual properties into a 'workarea'/buffer > provided by the guest. >=20 > The device-tree is generated by QEMU and passed to an sPAPRDRConnector du= ring > the initial hotplug operation, and the state of these RTAS calls is track= ed by > the sPAPRDRConnector. When the last of these properties is successfully > fetched, we report as special return value to the guest and transition > the device to a 'configured' state on the QEMU/DRC side. >=20 > See docs/specs/ppc-spapr-hotplug.txt for a complete description of > this interface. >=20 > Signed-off-by: Michael Roth Apart from some details noted below, Reviewed-by: David Gibson > --- > hw/ppc/spapr.c | 4 ++ > hw/ppc/spapr_rtas.c | 179 +++++++++++++++++++++++++++++++++++++++++++= ++++++ > include/hw/ppc/spapr.h | 14 ++++ > 3 files changed, 197 insertions(+) >=20 > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index 7febff7..6b68ebc 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -1650,6 +1650,10 @@ static void ppc_spapr_init(MachineState *machine) > boot_device, kernel_cmdline, > spapr->epow_irq); > assert(spapr->fdt_skel !=3D NULL); > + > + /* used by RTAS */ > + QTAILQ_INIT(&spapr->ccs_list); > + qemu_register_reset(spapr_ccs_reset_hook, spapr); It seems kind of awkward to have this list in spapr, rather than just having a pointer to the ccs in the drc, but whatever. > } > =20 > static int spapr_kvm_type(const char *vm_type) > diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c > index f80beb2..874380d 100644 > --- a/hw/ppc/spapr_rtas.c > +++ b/hw/ppc/spapr_rtas.c > @@ -47,6 +47,43 @@ > do { } while (0) > #endif > =20 > +static sPAPRConfigureConnectorState *spapr_ccs_find(sPAPREnvironment *sp= apr, > + uint32_t drc_index) > +{ > + sPAPRConfigureConnectorState *ccs =3D NULL; > + > + QTAILQ_FOREACH(ccs, &spapr->ccs_list, next) { > + if (ccs->drc_index =3D=3D drc_index) { > + break; > + } > + } > + > + return ccs; > +} > + > +static void spapr_ccs_add(sPAPREnvironment *spapr, > + sPAPRConfigureConnectorState *ccs) > +{ > + g_assert(!spapr_ccs_find(spapr, ccs->drc_index)); > + QTAILQ_INSERT_HEAD(&spapr->ccs_list, ccs, next); > +} > + > +static void spapr_ccs_remove(sPAPREnvironment *spapr, > + sPAPRConfigureConnectorState *ccs) > +{ > + QTAILQ_REMOVE(&spapr->ccs_list, ccs, next); > + g_free(ccs); > +} > + > +void spapr_ccs_reset_hook(void *opaque) > +{ > + sPAPREnvironment *spapr =3D opaque; > + sPAPRConfigureConnectorState *ccs, *ccs_tmp; > + > + QTAILQ_FOREACH_SAFE(ccs, &spapr->ccs_list, next, ccs_tmp) { > + spapr_ccs_remove(spapr, ccs); > + } > +} > =20 > static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *sp= apr, > uint32_t token, uint32_t nargs, > @@ -355,6 +392,18 @@ static void rtas_set_indicator(PowerPCCPU *cpu, sPAP= REnvironment *spapr, > =20 > switch (sensor_type) { > case RTAS_SENSOR_TYPE_ISOLATION_STATE: > + /* if the guest is configuring a device attached to this > + * DRC, we should reset the configuration state at this > + * point since it may no longer be reliable (guest released > + * device and needs to start over, or unplug occurred so > + * the FDT is no longer valid) > + */ > + if (sensor_state =3D=3D SPAPR_DR_ISOLATION_STATE_ISOLATED) { > + sPAPRConfigureConnectorState *ccs =3D spapr_ccs_find(spapr, = sensor_index); > + if (ccs) { > + spapr_ccs_remove(spapr, ccs); > + } > + } > drck->set_isolation_state(drc, sensor_state); > break; > case RTAS_SENSOR_TYPE_DR: > @@ -418,6 +467,134 @@ static void rtas_get_sensor_state(PowerPCCPU *cpu, = sPAPREnvironment *spapr, > rtas_st(rets, 1, entity_sense); > } > =20 > +/* configure-connector work area offsets, int32_t units for field > + * indexes, bytes for field offset/len values. > + * > + * as documented by PAPR+ v2.7, 13.5.3.5 > + */ > +#define CC_IDX_NODE_NAME_OFFSET 2 > +#define CC_IDX_PROP_NAME_OFFSET 2 > +#define CC_IDX_PROP_LEN 3 > +#define CC_IDX_PROP_DATA_OFFSET 4 > +#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4) > +#define CC_WA_LEN 4096 > + > +static void rtas_ibm_configure_connector(PowerPCCPU *cpu, > + sPAPREnvironment *spapr, > + uint32_t token, uint32_t nargs, > + target_ulong args, uint32_t nre= t, > + target_ulong rets) > +{ > + uint64_t wa_addr; > + uint64_t wa_offset; > + uint32_t drc_index; > + sPAPRDRConnector *drc; > + sPAPRDRConnectorClass *drck; > + sPAPRConfigureConnectorState *ccs; > + sPAPRDRCCResponse resp =3D SPAPR_DR_CC_RESPONSE_CONTINUE; > + int rc; > + const void *fdt; > + > + if (nargs !=3D 2 || nret !=3D 1) { > + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); > + return; > + } > + > + wa_addr =3D ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0); > + > + drc_index =3D rtas_ld(wa_addr, 0); > + drc =3D spapr_dr_connector_by_index(drc_index); > + if (!drc) { > + DPRINTF("rtas_ibm_configure_connector: invalid DRC index: %xh\n", > + drc_index); > + rc =3D RTAS_OUT_PARAM_ERROR; > + goto out; > + } > + > + drck =3D SPAPR_DR_CONNECTOR_GET_CLASS(drc); > + fdt =3D drck->get_fdt(drc, NULL); > + > + ccs =3D spapr_ccs_find(spapr, drc_index); > + if (!ccs) { > + ccs =3D g_new0(sPAPRConfigureConnectorState, 1); > + (void)drck->get_fdt(drc, &ccs->fdt_offset); So, I think we can avoid the awkwardness with getting fdt_offset out by making the DT fragment have the relevant node at the root, instead of as an immediate subnode of the root. But that's a cleanup we can probably do later. Alternatively fdt_first_subnode() could be used to find the starting offset. > + ccs->drc_index =3D drc_index; > + spapr_ccs_add(spapr, ccs); > + } > + > + do { > + uint32_t tag; > + const char *name; > + const struct fdt_property *prop; > + int fdt_offset_next, prop_len; > + > + tag =3D fdt_next_tag(fdt, ccs->fdt_offset, &fdt_offset_next); > + > + switch (tag) { > + case FDT_BEGIN_NODE: > + ccs->fdt_depth++; > + name =3D fdt_get_name(fdt, ccs->fdt_offset, NULL); > + > + /* provide the name of the next OF node */ > + wa_offset =3D CC_VAL_DATA_OFFSET; > + rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset); > + rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_of= fset, > + (uint8_t *)name, strlen(name) + 1); > + resp =3D SPAPR_DR_CC_RESPONSE_NEXT_CHILD; > + break; > + case FDT_END_NODE: > + ccs->fdt_depth--; > + if (ccs->fdt_depth =3D=3D 0) { > + /* done sending the device tree, don't need to track > + * the state anymore > + */ > + drck->set_configured(drc); > + spapr_ccs_remove(spapr, ccs); > + ccs =3D NULL; > + resp =3D SPAPR_DR_CC_RESPONSE_SUCCESS; > + } else { > + resp =3D SPAPR_DR_CC_RESPONSE_PREV_PARENT; > + } > + break; > + case FDT_PROP: > + prop =3D fdt_get_property_by_offset(fdt, ccs->fdt_offset, > + &prop_len); > + name =3D fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); > + > + /* provide the name of the next OF property */ > + wa_offset =3D CC_VAL_DATA_OFFSET; > + rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset); > + rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_of= fset, > + (uint8_t *)name, strlen(name) + 1); > + > + /* provide the length and value of the OF property. data gets > + * placed immediately after NULL terminator of the OF proper= ty's > + * name string > + */ > + wa_offset +=3D strlen(name) + 1, > + rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len); > + rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset); > + rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_of= fset, > + (uint8_t *)((struct fdt_property *)pro= p)->data, > + prop_len); > + resp =3D SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY; > + break; > + case FDT_END: > + resp =3D SPAPR_DR_CC_RESPONSE_ERROR; > + default: > + /* keep seeking for an actionable tag */ > + break; > + } > + if (ccs) { > + ccs->fdt_offset =3D fdt_offset_next; > + } > + } while (resp =3D=3D SPAPR_DR_CC_RESPONSE_CONTINUE); > + > + rc =3D resp; > +out: > + rtas_st(rets, 0, rc); > +} > + > static struct rtas_call { > const char *name; > spapr_rtas_fn fn; > @@ -551,6 +728,8 @@ static void core_rtas_register_types(void) > rtas_set_indicator); > spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state", > rtas_get_sensor_state); > + spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-con= nector", > + rtas_ibm_configure_connector); > } > =20 > type_init(core_rtas_register_types) > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h > index f046a89..b021ead 100644 > --- a/include/hw/ppc/spapr.h > +++ b/include/hw/ppc/spapr.h > @@ -7,6 +7,7 @@ > struct VIOsPAPRBus; > struct sPAPRPHBState; > struct sPAPRNVRAM; > +typedef struct sPAPRConfigureConnectorState sPAPRConfigureConnectorState; > =20 > #define HPTE64_V_HPTE_DIRTY 0x0000000000000040ULL > =20 > @@ -39,6 +40,9 @@ typedef struct sPAPREnvironment { > bool htab_first_pass; > int htab_fd; > bool htab_fd_stale; > + > + /* RTAS state */ > + QTAILQ_HEAD(, sPAPRConfigureConnectorState) ccs_list; > } sPAPREnvironment; > =20 > #define H_SUCCESS 0 > @@ -544,6 +548,16 @@ int spapr_tcet_dma_dt(void *fdt, int node_off, const= char *propname, > sPAPRTCETable *tcet); > void spapr_pci_switch_vga(bool big_endian); > =20 > +/* rtas-configure-connector state */ > +struct sPAPRConfigureConnectorState { > + uint32_t drc_index; > + int fdt_offset; > + int fdt_depth; > + QTAILQ_ENTRY(sPAPRConfigureConnectorState) next; > +}; > + > +void spapr_ccs_reset_hook(void *opaque); > + > #define TYPE_SPAPR_RTC "spapr-rtc" > =20 > void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns); --=20 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 --FL5UXtIhxfXey3p5 Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBAgAGBQJVPzV/AAoJEGw4ysog2bOSXdMP/iBBos9GvVecQJRrfMaWMgMZ AQG55qPaikPBedvbdsJkFK1qBczNaT/U6acHgsQkyjeWSCBDq7m5NCqarjIwD3tL 3SLzpJope6GseN5u013p/a+BPU4fGfQzJD/7w6OXG+Ijn0mWe2WfHvs33vhtGKVh MgvSs5VwkfaS7XyhVUojw5o10uHKlhovaIzdb0ZiJwD7paffFooiBY2hFLIVW6tb VKHVQaIF65m4GI8wuBmeT02IjoKTpRe2Sl60ZC3GAnuFvKg/5ffcfI+F9h3aCZPO 5ERmXQIEkfjMg8jPvl7jQkqVeav9JFWU8BGyQ+UYC1xM1BOITcO5y2fE7uMEND6S v/70iB9UW9hUkfkEhxEPCvWv/GJnD0CG5HB94eiknQQ6ssQi706QzaNeK++Ip4OX cCRU2ozTG+4w3bvoYq0/iNmHpwnqpw6ph7tZL1AtNQugTQ+OP8Ll9yBxWBIdRxF7 tUnz/bVH50f0QuZB9jsunt5zmX65Hx2qvu/LaVui6GM3WnR5qVzeEIx+5fcNZrbw NccLrgwoiiAPiCIwTSq6b0gqLr1saJO3bSkNY+bx4HPcAMbO8erTlLnJSlO4QBW9 XQBiUb5qkrkiAJ5aEV76/8q7tn0vXICSPwp+SYwvL8TIFL4fof68ovqyxMLAkU4h /1iF1IQCxvzGvfbUJ9Cd =8ZXp -----END PGP SIGNATURE----- --FL5UXtIhxfXey3p5--