|
|
8be556 |
From fbfb411fd95ec7653edbc9e15a9ce5315c744c1a Mon Sep 17 00:00:00 2001
|
|
|
8be556 |
From: Laurent Vivier <lvivier@redhat.com>
|
|
|
8be556 |
Date: Thu, 25 Jun 2015 13:44:33 +0200
|
|
|
8be556 |
Subject: [PATCH 094/217] spapr_rtas: add ibm, configure-connector RTAS
|
|
|
8be556 |
interface
|
|
|
8be556 |
|
|
|
8be556 |
Message-id: <1435239881-28541-7-git-send-email-lvivier@redhat.com>
|
|
|
8be556 |
Patchwork-id: 66486
|
|
|
8be556 |
O-Subject: [RHEL7.2 qemu-kvm-rhev PATCH 06/14] spapr_rtas: add ibm, configure-connector RTAS interface
|
|
|
8be556 |
Bugzilla: 1172478
|
|
|
8be556 |
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
8be556 |
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
|
|
8be556 |
RH-Acked-by: David Gibson <dgibson@redhat.com>
|
|
|
8be556 |
|
|
|
8be556 |
From: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
|
8be556 |
|
|
|
8be556 |
This interface is used to fetch an OF device-tree nodes that describes a
|
|
|
8be556 |
newly-attached device to guest. It is called multiple times to walk the
|
|
|
8be556 |
device-tree node and fetch individual properties into a 'workarea'/buffer
|
|
|
8be556 |
provided by the guest.
|
|
|
8be556 |
|
|
|
8be556 |
The device-tree is generated by QEMU and passed to an sPAPRDRConnector during
|
|
|
8be556 |
the initial hotplug operation, and the state of these RTAS calls is tracked by
|
|
|
8be556 |
the sPAPRDRConnector. When the last of these properties is successfully
|
|
|
8be556 |
fetched, we report as special return value to the guest and transition
|
|
|
8be556 |
the device to a 'configured' state on the QEMU/DRC side.
|
|
|
8be556 |
|
|
|
8be556 |
See docs/specs/ppc-spapr-hotplug.txt for a complete description of
|
|
|
8be556 |
this interface.
|
|
|
8be556 |
|
|
|
8be556 |
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
|
8be556 |
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
|
8be556 |
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
|
8be556 |
(cherry picked from commit 46503c2bc047bfe8c26440e17298fcbc59d7bbbe)
|
|
|
8be556 |
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
8be556 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
8be556 |
---
|
|
|
8be556 |
hw/ppc/spapr.c | 4 ++
|
|
|
8be556 |
hw/ppc/spapr_rtas.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
8be556 |
include/hw/ppc/spapr.h | 14 ++++
|
|
|
8be556 |
3 files changed, 198 insertions(+)
|
|
|
8be556 |
|
|
|
8be556 |
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
|
|
|
8be556 |
index 3fe98ff..8b21a71 100644
|
|
|
8be556 |
--- a/hw/ppc/spapr.c
|
|
|
8be556 |
+++ b/hw/ppc/spapr.c
|
|
|
8be556 |
@@ -1663,6 +1663,10 @@ static void ppc_spapr_init(MachineState *machine)
|
|
|
8be556 |
kernel_cmdline, spapr->epow_irq);
|
|
|
8be556 |
assert(spapr->fdt_skel != NULL);
|
|
|
8be556 |
|
|
|
8be556 |
+ /* used by RTAS */
|
|
|
8be556 |
+ QTAILQ_INIT(&spapr->ccs_list);
|
|
|
8be556 |
+ qemu_register_reset(spapr_ccs_reset_hook, spapr);
|
|
|
8be556 |
+
|
|
|
8be556 |
qemu_register_boot_set(spapr_boot_set, spapr);
|
|
|
8be556 |
}
|
|
|
8be556 |
|
|
|
8be556 |
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
|
|
|
8be556 |
index f80beb2..fa28d43 100644
|
|
|
8be556 |
--- a/hw/ppc/spapr_rtas.c
|
|
|
8be556 |
+++ b/hw/ppc/spapr_rtas.c
|
|
|
8be556 |
@@ -47,6 +47,43 @@
|
|
|
8be556 |
do { } while (0)
|
|
|
8be556 |
#endif
|
|
|
8be556 |
|
|
|
8be556 |
+static sPAPRConfigureConnectorState *spapr_ccs_find(sPAPREnvironment *spapr,
|
|
|
8be556 |
+ uint32_t drc_index)
|
|
|
8be556 |
+{
|
|
|
8be556 |
+ sPAPRConfigureConnectorState *ccs = NULL;
|
|
|
8be556 |
+
|
|
|
8be556 |
+ QTAILQ_FOREACH(ccs, &spapr->ccs_list, next) {
|
|
|
8be556 |
+ if (ccs->drc_index == drc_index) {
|
|
|
8be556 |
+ break;
|
|
|
8be556 |
+ }
|
|
|
8be556 |
+ }
|
|
|
8be556 |
+
|
|
|
8be556 |
+ return ccs;
|
|
|
8be556 |
+}
|
|
|
8be556 |
+
|
|
|
8be556 |
+static void spapr_ccs_add(sPAPREnvironment *spapr,
|
|
|
8be556 |
+ sPAPRConfigureConnectorState *ccs)
|
|
|
8be556 |
+{
|
|
|
8be556 |
+ g_assert(!spapr_ccs_find(spapr, ccs->drc_index));
|
|
|
8be556 |
+ QTAILQ_INSERT_HEAD(&spapr->ccs_list, ccs, next);
|
|
|
8be556 |
+}
|
|
|
8be556 |
+
|
|
|
8be556 |
+static void spapr_ccs_remove(sPAPREnvironment *spapr,
|
|
|
8be556 |
+ sPAPRConfigureConnectorState *ccs)
|
|
|
8be556 |
+{
|
|
|
8be556 |
+ QTAILQ_REMOVE(&spapr->ccs_list, ccs, next);
|
|
|
8be556 |
+ g_free(ccs);
|
|
|
8be556 |
+}
|
|
|
8be556 |
+
|
|
|
8be556 |
+void spapr_ccs_reset_hook(void *opaque)
|
|
|
8be556 |
+{
|
|
|
8be556 |
+ sPAPREnvironment *spapr = opaque;
|
|
|
8be556 |
+ sPAPRConfigureConnectorState *ccs, *ccs_tmp;
|
|
|
8be556 |
+
|
|
|
8be556 |
+ QTAILQ_FOREACH_SAFE(ccs, &spapr->ccs_list, next, ccs_tmp) {
|
|
|
8be556 |
+ spapr_ccs_remove(spapr, ccs);
|
|
|
8be556 |
+ }
|
|
|
8be556 |
+}
|
|
|
8be556 |
|
|
|
8be556 |
static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|
|
8be556 |
uint32_t token, uint32_t nargs,
|
|
|
8be556 |
@@ -355,6 +392,19 @@ static void rtas_set_indicator(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|
|
8be556 |
|
|
|
8be556 |
switch (sensor_type) {
|
|
|
8be556 |
case RTAS_SENSOR_TYPE_ISOLATION_STATE:
|
|
|
8be556 |
+ /* if the guest is configuring a device attached to this
|
|
|
8be556 |
+ * DRC, we should reset the configuration state at this
|
|
|
8be556 |
+ * point since it may no longer be reliable (guest released
|
|
|
8be556 |
+ * device and needs to start over, or unplug occurred so
|
|
|
8be556 |
+ * the FDT is no longer valid)
|
|
|
8be556 |
+ */
|
|
|
8be556 |
+ if (sensor_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) {
|
|
|
8be556 |
+ sPAPRConfigureConnectorState *ccs = spapr_ccs_find(spapr,
|
|
|
8be556 |
+ sensor_index);
|
|
|
8be556 |
+ if (ccs) {
|
|
|
8be556 |
+ spapr_ccs_remove(spapr, ccs);
|
|
|
8be556 |
+ }
|
|
|
8be556 |
+ }
|
|
|
8be556 |
drck->set_isolation_state(drc, sensor_state);
|
|
|
8be556 |
break;
|
|
|
8be556 |
case RTAS_SENSOR_TYPE_DR:
|
|
|
8be556 |
@@ -418,6 +468,134 @@ static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|
|
8be556 |
rtas_st(rets, 1, entity_sense);
|
|
|
8be556 |
}
|
|
|
8be556 |
|
|
|
8be556 |
+/* configure-connector work area offsets, int32_t units for field
|
|
|
8be556 |
+ * indexes, bytes for field offset/len values.
|
|
|
8be556 |
+ *
|
|
|
8be556 |
+ * as documented by PAPR+ v2.7, 13.5.3.5
|
|
|
8be556 |
+ */
|
|
|
8be556 |
+#define CC_IDX_NODE_NAME_OFFSET 2
|
|
|
8be556 |
+#define CC_IDX_PROP_NAME_OFFSET 2
|
|
|
8be556 |
+#define CC_IDX_PROP_LEN 3
|
|
|
8be556 |
+#define CC_IDX_PROP_DATA_OFFSET 4
|
|
|
8be556 |
+#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4)
|
|
|
8be556 |
+#define CC_WA_LEN 4096
|
|
|
8be556 |
+
|
|
|
8be556 |
+static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
|
|
|
8be556 |
+ sPAPREnvironment *spapr,
|
|
|
8be556 |
+ uint32_t token, uint32_t nargs,
|
|
|
8be556 |
+ target_ulong args, uint32_t nret,
|
|
|
8be556 |
+ target_ulong rets)
|
|
|
8be556 |
+{
|
|
|
8be556 |
+ uint64_t wa_addr;
|
|
|
8be556 |
+ uint64_t wa_offset;
|
|
|
8be556 |
+ uint32_t drc_index;
|
|
|
8be556 |
+ sPAPRDRConnector *drc;
|
|
|
8be556 |
+ sPAPRDRConnectorClass *drck;
|
|
|
8be556 |
+ sPAPRConfigureConnectorState *ccs;
|
|
|
8be556 |
+ sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;
|
|
|
8be556 |
+ int rc;
|
|
|
8be556 |
+ const void *fdt;
|
|
|
8be556 |
+
|
|
|
8be556 |
+ if (nargs != 2 || nret != 1) {
|
|
|
8be556 |
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
|
|
8be556 |
+ return;
|
|
|
8be556 |
+ }
|
|
|
8be556 |
+
|
|
|
8be556 |
+ wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0);
|
|
|
8be556 |
+
|
|
|
8be556 |
+ drc_index = rtas_ld(wa_addr, 0);
|
|
|
8be556 |
+ drc = spapr_dr_connector_by_index(drc_index);
|
|
|
8be556 |
+ if (!drc) {
|
|
|
8be556 |
+ DPRINTF("rtas_ibm_configure_connector: invalid DRC index: %xh\n",
|
|
|
8be556 |
+ drc_index);
|
|
|
8be556 |
+ rc = RTAS_OUT_PARAM_ERROR;
|
|
|
8be556 |
+ goto out;
|
|
|
8be556 |
+ }
|
|
|
8be556 |
+
|
|
|
8be556 |
+ drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
|
|
8be556 |
+ fdt = drck->get_fdt(drc, NULL);
|
|
|
8be556 |
+
|
|
|
8be556 |
+ ccs = spapr_ccs_find(spapr, drc_index);
|
|
|
8be556 |
+ if (!ccs) {
|
|
|
8be556 |
+ ccs = g_new0(sPAPRConfigureConnectorState, 1);
|
|
|
8be556 |
+ (void)drck->get_fdt(drc, &ccs->fdt_offset);
|
|
|
8be556 |
+ ccs->drc_index = drc_index;
|
|
|
8be556 |
+ spapr_ccs_add(spapr, ccs);
|
|
|
8be556 |
+ }
|
|
|
8be556 |
+
|
|
|
8be556 |
+ do {
|
|
|
8be556 |
+ uint32_t tag;
|
|
|
8be556 |
+ const char *name;
|
|
|
8be556 |
+ const struct fdt_property *prop;
|
|
|
8be556 |
+ int fdt_offset_next, prop_len;
|
|
|
8be556 |
+
|
|
|
8be556 |
+ tag = fdt_next_tag(fdt, ccs->fdt_offset, &fdt_offset_next);
|
|
|
8be556 |
+
|
|
|
8be556 |
+ switch (tag) {
|
|
|
8be556 |
+ case FDT_BEGIN_NODE:
|
|
|
8be556 |
+ ccs->fdt_depth++;
|
|
|
8be556 |
+ name = fdt_get_name(fdt, ccs->fdt_offset, NULL);
|
|
|
8be556 |
+
|
|
|
8be556 |
+ /* provide the name of the next OF node */
|
|
|
8be556 |
+ wa_offset = CC_VAL_DATA_OFFSET;
|
|
|
8be556 |
+ rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset);
|
|
|
8be556 |
+ rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,
|
|
|
8be556 |
+ (uint8_t *)name, strlen(name) + 1);
|
|
|
8be556 |
+ resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD;
|
|
|
8be556 |
+ break;
|
|
|
8be556 |
+ case FDT_END_NODE:
|
|
|
8be556 |
+ ccs->fdt_depth--;
|
|
|
8be556 |
+ if (ccs->fdt_depth == 0) {
|
|
|
8be556 |
+ /* done sending the device tree, don't need to track
|
|
|
8be556 |
+ * the state anymore
|
|
|
8be556 |
+ */
|
|
|
8be556 |
+ drck->set_configured(drc);
|
|
|
8be556 |
+ spapr_ccs_remove(spapr, ccs);
|
|
|
8be556 |
+ ccs = NULL;
|
|
|
8be556 |
+ resp = SPAPR_DR_CC_RESPONSE_SUCCESS;
|
|
|
8be556 |
+ } else {
|
|
|
8be556 |
+ resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;
|
|
|
8be556 |
+ }
|
|
|
8be556 |
+ break;
|
|
|
8be556 |
+ case FDT_PROP:
|
|
|
8be556 |
+ prop = fdt_get_property_by_offset(fdt, ccs->fdt_offset,
|
|
|
8be556 |
+ &prop_len);
|
|
|
8be556 |
+ name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
|
|
|
8be556 |
+
|
|
|
8be556 |
+ /* provide the name of the next OF property */
|
|
|
8be556 |
+ wa_offset = CC_VAL_DATA_OFFSET;
|
|
|
8be556 |
+ rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset);
|
|
|
8be556 |
+ rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,
|
|
|
8be556 |
+ (uint8_t *)name, strlen(name) + 1);
|
|
|
8be556 |
+
|
|
|
8be556 |
+ /* provide the length and value of the OF property. data gets
|
|
|
8be556 |
+ * placed immediately after NULL terminator of the OF property's
|
|
|
8be556 |
+ * name string
|
|
|
8be556 |
+ */
|
|
|
8be556 |
+ wa_offset += strlen(name) + 1,
|
|
|
8be556 |
+ rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len);
|
|
|
8be556 |
+ rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset);
|
|
|
8be556 |
+ rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,
|
|
|
8be556 |
+ (uint8_t *)((struct fdt_property *)prop)->data,
|
|
|
8be556 |
+ prop_len);
|
|
|
8be556 |
+ resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY;
|
|
|
8be556 |
+ break;
|
|
|
8be556 |
+ case FDT_END:
|
|
|
8be556 |
+ resp = SPAPR_DR_CC_RESPONSE_ERROR;
|
|
|
8be556 |
+ default:
|
|
|
8be556 |
+ /* keep seeking for an actionable tag */
|
|
|
8be556 |
+ break;
|
|
|
8be556 |
+ }
|
|
|
8be556 |
+ if (ccs) {
|
|
|
8be556 |
+ ccs->fdt_offset = fdt_offset_next;
|
|
|
8be556 |
+ }
|
|
|
8be556 |
+ } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE);
|
|
|
8be556 |
+
|
|
|
8be556 |
+ rc = resp;
|
|
|
8be556 |
+out:
|
|
|
8be556 |
+ rtas_st(rets, 0, rc);
|
|
|
8be556 |
+}
|
|
|
8be556 |
+
|
|
|
8be556 |
static struct rtas_call {
|
|
|
8be556 |
const char *name;
|
|
|
8be556 |
spapr_rtas_fn fn;
|
|
|
8be556 |
@@ -551,6 +729,8 @@ static void core_rtas_register_types(void)
|
|
|
8be556 |
rtas_set_indicator);
|
|
|
8be556 |
spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state",
|
|
|
8be556 |
rtas_get_sensor_state);
|
|
|
8be556 |
+ spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector",
|
|
|
8be556 |
+ rtas_ibm_configure_connector);
|
|
|
8be556 |
}
|
|
|
8be556 |
|
|
|
8be556 |
type_init(core_rtas_register_types)
|
|
|
8be556 |
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
|
|
|
8be556 |
index 919eec6..673fd89 100644
|
|
|
8be556 |
--- a/include/hw/ppc/spapr.h
|
|
|
8be556 |
+++ b/include/hw/ppc/spapr.h
|
|
|
8be556 |
@@ -7,6 +7,7 @@
|
|
|
8be556 |
struct VIOsPAPRBus;
|
|
|
8be556 |
struct sPAPRPHBState;
|
|
|
8be556 |
struct sPAPRNVRAM;
|
|
|
8be556 |
+typedef struct sPAPRConfigureConnectorState sPAPRConfigureConnectorState;
|
|
|
8be556 |
|
|
|
8be556 |
#define HPTE64_V_HPTE_DIRTY 0x0000000000000040ULL
|
|
|
8be556 |
|
|
|
8be556 |
@@ -39,6 +40,9 @@ typedef struct sPAPREnvironment {
|
|
|
8be556 |
bool htab_first_pass;
|
|
|
8be556 |
int htab_fd;
|
|
|
8be556 |
bool htab_fd_stale;
|
|
|
8be556 |
+
|
|
|
8be556 |
+ /* RTAS state */
|
|
|
8be556 |
+ QTAILQ_HEAD(, sPAPRConfigureConnectorState) ccs_list;
|
|
|
8be556 |
} sPAPREnvironment;
|
|
|
8be556 |
|
|
|
8be556 |
#define H_SUCCESS 0
|
|
|
8be556 |
@@ -539,6 +543,16 @@ int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
|
|
|
8be556 |
sPAPRTCETable *tcet);
|
|
|
8be556 |
void spapr_pci_switch_vga(bool big_endian);
|
|
|
8be556 |
|
|
|
8be556 |
+/* rtas-configure-connector state */
|
|
|
8be556 |
+struct sPAPRConfigureConnectorState {
|
|
|
8be556 |
+ uint32_t drc_index;
|
|
|
8be556 |
+ int fdt_offset;
|
|
|
8be556 |
+ int fdt_depth;
|
|
|
8be556 |
+ QTAILQ_ENTRY(sPAPRConfigureConnectorState) next;
|
|
|
8be556 |
+};
|
|
|
8be556 |
+
|
|
|
8be556 |
+void spapr_ccs_reset_hook(void *opaque);
|
|
|
8be556 |
+
|
|
|
8be556 |
#define TYPE_SPAPR_RTC "spapr-rtc"
|
|
|
8be556 |
|
|
|
8be556 |
void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns);
|
|
|
8be556 |
--
|
|
|
8be556 |
1.8.3.1
|
|
|
8be556 |
|