From patchwork Mon Oct 3 18:24:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianjun Duan X-Patchwork-Id: 9360785 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A4AD6601C0 for ; Mon, 3 Oct 2016 18:26:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 877B8287CB for ; Mon, 3 Oct 2016 18:26:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7AB8D288E3; Mon, 3 Oct 2016 18:26:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 13525287CB for ; Mon, 3 Oct 2016 18:26:18 +0000 (UTC) Received: from localhost ([::1]:38572 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1br7wP-00018G-N8 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 03 Oct 2016 14:26:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36280) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1br7vT-0000kR-Av for qemu-devel@nongnu.org; Mon, 03 Oct 2016 14:25:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1br7vP-0004HU-1H for qemu-devel@nongnu.org; Mon, 03 Oct 2016 14:25:18 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:59027 helo=mx0a-001b2d01.pphosted.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1br7vO-0004Gz-Nm for qemu-devel@nongnu.org; Mon, 03 Oct 2016 14:25:14 -0400 Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.17/8.16.0.17) with SMTP id u93INlp4046553 for ; Mon, 3 Oct 2016 14:25:13 -0400 Received: from e18.ny.us.ibm.com (e18.ny.us.ibm.com [129.33.205.208]) by mx0b-001b2d01.pphosted.com with ESMTP id 25utg0qy0x-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 03 Oct 2016 14:25:13 -0400 Received: from localhost by e18.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 3 Oct 2016 14:25:13 -0400 Received: from d01dlp01.pok.ibm.com (9.56.250.166) by e18.ny.us.ibm.com (146.89.104.205) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 3 Oct 2016 14:25:08 -0400 Received: from b01cxnp23032.gho.pok.ibm.com (b01cxnp23032.gho.pok.ibm.com [9.57.198.27]) by d01dlp01.pok.ibm.com (Postfix) with ESMTP id 9671338C8046; Mon, 3 Oct 2016 14:25:07 -0400 (EDT) Received: from b01ledav001.gho.pok.ibm.com (b01ledav001.gho.pok.ibm.com [9.57.199.106]) by b01cxnp23032.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u93IP6Vk12779884; Mon, 3 Oct 2016 18:25:13 GMT Received: from b01ledav001.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 999732803E; Mon, 3 Oct 2016 14:25:07 -0400 (EDT) Received: from jianjun-w530.ibm.com (unknown [9.48.109.118]) by b01ledav001.gho.pok.ibm.com (Postfix) with ESMTP id 66C2128059; Mon, 3 Oct 2016 14:25:04 -0400 (EDT) From: Jianjun Duan To: qemu-devel@nongnu.org Date: Mon, 3 Oct 2016 11:24:53 -0700 X-Mailer: git-send-email 1.9.1 In-Reply-To: <1475519097-27611-1-git-send-email-duanj@linux.vnet.ibm.com> References: <1475519097-27611-1-git-send-email-duanj@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16100318-0044-0000-0000-0000015C26D6 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00005848; HX=3.00000240; KW=3.00000007; PH=3.00000004; SC=3.00000186; SDB=6.00763933; UDB=6.00364697; IPR=6.00539579; BA=6.00004779; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00012860; XFM=3.00000011; UTC=2016-10-03 18:25:12 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16100318-0045-0000-0000-000005893025 Message-Id: <1475519097-27611-3-git-send-email-duanj@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-10-03_11:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1609280000 definitions=main-1610030317 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] X-Received-From: 148.163.158.5 Subject: [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: veroniabahaa@gmail.com, peter.maydell@linaro.org, dgilbert@redhat.com, duanj@linux.vnet.ibm.com, mst@redhat.com, quintela@redhat.com, mark.cave-ayland@ilande.co.uk, mdroth@linux.vnet.ibm.com, mreitz@redhat.com, blauwirbel@gmail.com, amit.shah@redhat.com, qemu-ppc@nongnu.org, kraxel@redhat.com, kwolf@redhat.com, dmitry@daynix.com, pbonzini@redhat.com, rth@twiddle.net, leon.alrae@imgtec.com, aurelien@aurel32.net, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP To manage hotplug/unplug of dynamic resources such as PCI cards, memory, and CPU on sPAPR guests, a firmware abstraction known as a Dynamic Resource Connector (DRC) is used to assign a particular dynamic resource to the guest, and provide an interface for the guest to manage configuration/removal of the resource associated with it. To migrate the hotplugged resources in migration, the associated DRC state need be migrated. To migrate the DRC state, we defined the VMStateDescription struct for spapr_drc to enable the transmission of spapr_drc state in migration. Not all the elements in the DRC state are migrated. Only those ones modifiable or needed by guest actions or device add/remove operation are migrated. From the perspective of device hotplugging, if we hotplug a device on the source, we need to "coldplug" it on the target. The states across two hosts for the same device are not the same. Ideally we want the states be same after migration so that the device would function as hotplugged on the target. For example we can unplug it. The minimum DRC state we need to transfer should cover all the pieces changed by hotplugging. Out of the elements of the DRC state, isolation_state, allocation_sate, and configured are involved in the DR state transition diagram from PAPR+ 2.7, 13.4. configured and signalled are needed in attaching and detaching devices. indicator_state provides users with hardware state information. These 6 elements are migrated. detach_cb in the DRC state is a function pointer that cannot be migrated. We set it right after DRC state is migrated so that a migrated hot-unplug event could finish its work. The instance_id is used to identify objects in migration. We set instance_id of DRC using the unique index so that it is the same across migration. Signed-off-by: Jianjun Duan --- hw/ppc/spapr_drc.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ hw/ppc/spapr_pci.c | 22 +++++++++++++++ include/hw/ppc/spapr_drc.h | 9 ++++++ 3 files changed, 100 insertions(+) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 6e54fd4..369ec02 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -615,6 +615,71 @@ static void spapr_dr_connector_instance_init(Object *obj) NULL, NULL, NULL, NULL); } +static bool spapr_drc_needed(void *opaque) +{ + sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque; + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + bool rc = false; + sPAPRDREntitySense value; + + drck->entity_sense(drc, &value); + /* If no dev is plugged in there is no need to migrate the DRC state */ + if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) { + return false; + } + /* + * If there is dev plugged in, we need to migrate the DRC state when + * it is different from cold-plugged state + */ + switch(drc->type) { + /* for PCI type */ + case SPAPR_DR_CONNECTOR_TYPE_PCI: + rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) && + (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) && + drc->configured && drc->signalled && !drc->awaiting_release); + break; + /* for LMB type */ + case SPAPR_DR_CONNECTOR_TYPE_LMB: + rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) && + (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) && + drc->configured && drc->signalled && !drc->awaiting_release); + break; + default: + ; + } + + return rc; +} + +/* detach_cb needs be set since it is not migrated */ +static void postmigrate_set_detach_cb(sPAPRDRConnector *drc, + spapr_drc_detach_cb *detach_cb) +{ + drc->detach_cb = detach_cb; +} + +/* return the unique drc index as instance_id for qom interfaces*/ +static int get_instance_id(DeviceState *dev) +{ + return (int)get_index(SPAPR_DR_CONNECTOR(OBJECT(dev))); +} + +static const VMStateDescription vmstate_spapr_drc = { + .name = "spapr_drc", + .version_id = 1, + .minimum_version_id = 1, + .needed = spapr_drc_needed, + .fields = (VMStateField []) { + VMSTATE_UINT32(isolation_state, sPAPRDRConnector), + VMSTATE_UINT32(allocation_state, sPAPRDRConnector), + VMSTATE_UINT32(indicator_state, sPAPRDRConnector), + VMSTATE_BOOL(configured, sPAPRDRConnector), + VMSTATE_BOOL(awaiting_release, sPAPRDRConnector), + VMSTATE_BOOL(signalled, sPAPRDRConnector), + VMSTATE_END_OF_LIST() + } +}; + static void spapr_dr_connector_class_init(ObjectClass *k, void *data) { DeviceClass *dk = DEVICE_CLASS(k); @@ -623,6 +688,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) dk->reset = reset; dk->realize = realize; dk->unrealize = unrealize; + dk->vmsd = &vmstate_spapr_drc; + dk->dev_get_instance_id = get_instance_id; drck->set_isolation_state = set_isolation_state; drck->set_indicator_state = set_indicator_state; drck->set_allocation_state = set_allocation_state; @@ -636,6 +703,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) drck->detach = detach; drck->release_pending = release_pending; drck->set_signalled = set_signalled; + drck->postmigrate_set_detach_cb = postmigrate_set_detach_cb; + /* * Reason: it crashes FIXME find and document the real reason */ diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 4f00865..080471c 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1594,11 +1594,33 @@ static void spapr_pci_pre_save(void *opaque) } } +/* + * detach_cb in the DRC state is a function pointer that cannot be + * migrated. We set it right after migration so that a migrated + * hot-unplug event could finish its work. + */ +static void spapr_pci_set_detach_cb(PCIBus *bus, PCIDevice *pdev, + void *opaque) +{ + sPAPRPHBState *sphb = opaque; + sPAPRDRConnector *drc = spapr_phb_get_pci_drc(sphb, pdev); + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + drck->postmigrate_set_detach_cb(drc, spapr_phb_remove_pci_device_cb); +} + static int spapr_pci_post_load(void *opaque, int version_id) { sPAPRPHBState *sphb = opaque; gpointer key, value; int i; + PCIBus *bus = PCI_HOST_BRIDGE(sphb)->bus; + unsigned int bus_no = 0; + + /* Set detach_cb for the drc unconditionally after migration */ + if (bus) { + pci_for_each_device(bus, pci_bus_num(bus), spapr_pci_set_detach_cb, + &bus_no); + } for (i = 0; i < sphb->msi_devs_num; ++i) { key = g_memdup(&sphb->msi_devs[i].key, diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index fa531d5..17589c8 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -192,6 +192,15 @@ typedef struct sPAPRDRConnectorClass { void *detach_cb_opaque, Error **errp); bool (*release_pending)(sPAPRDRConnector *drc); void (*set_signalled)(sPAPRDRConnector *drc); + + /* + * QEMU interface for setting detach_cb after migration. + * detach_cb in the DRC state is a function pointer that cannot be + * migrated. We set it right after migration so that a migrated + * hot-unplug event could finish its work. + */ + void (*postmigrate_set_detach_cb)(sPAPRDRConnector *drc, + spapr_drc_detach_cb *detach_cb); } sPAPRDRConnectorClass; sPAPRDRConnector *spapr_dr_connector_new(Object *owner,