From patchwork Fri Dec 18 10:33:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kurz X-Patchwork-Id: 11981677 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A8CADC4361B for ; Fri, 18 Dec 2020 10:38:58 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5B6E423A9A for ; Fri, 18 Dec 2020 10:38:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5B6E423A9A Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=kaod.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:35720 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kqDA1-00070D-C3 for qemu-devel@archiver.kernel.org; Fri, 18 Dec 2020 05:38:57 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45864) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kqD5Q-0000hR-CJ for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:13 -0500 Received: from us-smtp-delivery-44.mimecast.com ([205.139.111.44]:40806) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kqD5O-0001xX-1H for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:11 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-242-iw4SOYyTM4ecKMcDBR9hAA-1; Fri, 18 Dec 2020 05:34:05 -0500 X-MC-Unique: iw4SOYyTM4ecKMcDBR9hAA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2B82910054FF; Fri, 18 Dec 2020 10:34:04 +0000 (UTC) Received: from bahia.redhat.com (ovpn-114-254.ams2.redhat.com [10.36.114.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id 02A5560BE5; Fri, 18 Dec 2020 10:34:02 +0000 (UTC) From: Greg Kurz To: qemu-devel@nongnu.org Subject: [PATCH 1/6] spapr: Call spapr_drc_reset() for all DRCs at CAS Date: Fri, 18 Dec 2020 11:33:55 +0100 Message-Id: <20201218103400.689660-2-groug@kaod.org> In-Reply-To: <20201218103400.689660-1-groug@kaod.org> References: <20201218103400.689660-1-groug@kaod.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=groug@kaod.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kaod.org Received-SPF: softfail client-ip=205.139.111.44; envelope-from=groug@kaod.org; helo=us-smtp-delivery-44.mimecast.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Henrique Barboza , qemu-ppc@nongnu.org, Greg Kurz , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Non-transient DRCs are either in the empty or the ready state, which means spapr_drc_reset() doesn't change their state. It is thus not needed to do any checking. Call spapr_drc_reset() unconditionally and squash spapr_drc_transient() into its only user, spapr_drc_needed(). Signed-off-by: Greg Kurz Reviewed-by: Daniel Henrique Barboza --- include/hw/ppc/spapr_drc.h | 3 --- hw/ppc/spapr_drc.c | 8 ++------ hw/ppc/spapr_hcall.c | 7 ++++--- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index def3593adc8b..cff5e707d0d9 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -244,9 +244,6 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask); void spapr_drc_attach(SpaprDrc *drc, DeviceState *d); void spapr_drc_detach(SpaprDrc *drc); -/* Returns true if a hot plug/unplug request is pending */ -bool spapr_drc_transient(SpaprDrc *drc); - static inline bool spapr_drc_unplug_requested(SpaprDrc *drc) { return drc->unplug_requested; diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index fc7e321fcdf6..8d62f55066b6 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -462,8 +462,9 @@ static const VMStateDescription vmstate_spapr_drc_unplug_requested = { } }; -bool spapr_drc_transient(SpaprDrc *drc) +static bool spapr_drc_needed(void *opaque) { + SpaprDrc *drc = opaque; SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); /* @@ -483,11 +484,6 @@ bool spapr_drc_transient(SpaprDrc *drc) spapr_drc_unplug_requested(drc); } -static bool spapr_drc_needed(void *opaque) -{ - return spapr_drc_transient(opaque); -} - static const VMStateDescription vmstate_spapr_drc = { .name = "spapr_drc", .version_id = 1, diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index c0ea0bd5794b..4e9d50c254f0 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1650,9 +1650,10 @@ static void spapr_handle_transient_dev_before_cas(SpaprMachineState *spapr) prop->name, &error_abort)); - if (spapr_drc_transient(drc)) { - spapr_drc_reset(drc); - } + /* + * This will complete any pending plug/unplug requests. + */ + spapr_drc_reset(drc); } spapr_clear_pending_hotplug_events(spapr); From patchwork Fri Dec 18 10:33:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kurz X-Patchwork-Id: 11981673 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E1BB9C2BBD4 for ; Fri, 18 Dec 2020 10:36:59 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 933E823A7B for ; Fri, 18 Dec 2020 10:36:59 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 933E823A7B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=kaod.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:58094 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kqD86-0004Tw-MW for qemu-devel@archiver.kernel.org; Fri, 18 Dec 2020 05:36:58 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45912) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kqD5S-0000jC-P1 for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:15 -0500 Received: from us-smtp-delivery-44.mimecast.com ([207.211.30.44]:21623) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kqD5Q-0001yS-5V for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:13 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-335-bwShnYEUPFWPsXAiR96pRg-1; Fri, 18 Dec 2020 05:34:06 -0500 X-MC-Unique: bwShnYEUPFWPsXAiR96pRg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9D53F835DE1; Fri, 18 Dec 2020 10:34:05 +0000 (UTC) Received: from bahia.redhat.com (ovpn-114-254.ams2.redhat.com [10.36.114.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id 77E5460BE5; Fri, 18 Dec 2020 10:34:04 +0000 (UTC) From: Greg Kurz To: qemu-devel@nongnu.org Subject: [PATCH 2/6] spapr: Fix reset of transient DR connectors Date: Fri, 18 Dec 2020 11:33:56 +0100 Message-Id: <20201218103400.689660-3-groug@kaod.org> In-Reply-To: <20201218103400.689660-1-groug@kaod.org> References: <20201218103400.689660-1-groug@kaod.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=groug@kaod.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kaod.org Received-SPF: softfail client-ip=207.211.30.44; envelope-from=groug@kaod.org; helo=us-smtp-delivery-44.mimecast.com X-Spam_score_int: -11 X-Spam_score: -1.2 X-Spam_bar: - X-Spam_report: (-1.2 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Henrique Barboza , qemu-ppc@nongnu.org, Greg Kurz , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Documentation of object_property_iter_init() clearly stipulates that "it is forbidden to modify the property list while iterating". But this is exactly what we do when resetting transient DR connectors during CAS. The call to spapr_drc_reset() can finalize the hot-unplug sequence of a PHB or a PCI bridge, both of which will then in turn destroy their PCI DRCs. This could potentially invalidate the iterator. It is pure luck that this haven't caused any issues so far. Change spapr_drc_reset() to return true if it caused a device to be removed. Restart from scratch in this case. This can potentially increase the overall DRC reset time, especially with a high maxmem which generates a lot of LMB DRCs. But this kind of setup is rare, and so is the use case of rebooting a guest while doing hot-unplug. Signed-off-by: Greg Kurz Reviewed-by: Daniel Henrique Barboza --- include/hw/ppc/spapr_drc.h | 3 ++- hw/ppc/spapr_drc.c | 6 +++++- hw/ppc/spapr_hcall.c | 8 +++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index cff5e707d0d9..5d80019f82e2 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -224,7 +224,8 @@ static inline bool spapr_drc_hotplugged(DeviceState *dev) return dev->hotplugged && !runstate_check(RUN_STATE_INMIGRATE); } -void spapr_drc_reset(SpaprDrc *drc); +/* Returns true if an unplug request completed */ +bool spapr_drc_reset(SpaprDrc *drc); uint32_t spapr_drc_index(SpaprDrc *drc); SpaprDrcType spapr_drc_type(SpaprDrc *drc); diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 8d62f55066b6..5b5e2ac58a7e 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -417,9 +417,10 @@ void spapr_drc_detach(SpaprDrc *drc) spapr_drc_release(drc); } -void spapr_drc_reset(SpaprDrc *drc) +bool spapr_drc_reset(SpaprDrc *drc) { SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + bool unplug_completed = false; trace_spapr_drc_reset(spapr_drc_index(drc)); @@ -428,6 +429,7 @@ void spapr_drc_reset(SpaprDrc *drc) */ if (drc->unplug_requested) { spapr_drc_release(drc); + unplug_completed = true; } if (drc->dev) { @@ -444,6 +446,8 @@ void spapr_drc_reset(SpaprDrc *drc) drc->ccs_offset = -1; drc->ccs_depth = -1; } + + return unplug_completed; } static bool spapr_drc_unplug_requested_needed(void *opaque) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 4e9d50c254f0..aa22830ac4bd 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1639,6 +1639,7 @@ static void spapr_handle_transient_dev_before_cas(SpaprMachineState *spapr) ObjectPropertyIterator iter; drc_container = container_get(object_get_root(), "/dr-connector"); +restart: object_property_iter_init(&iter, drc_container); while ((prop = object_property_iter_next(&iter))) { SpaprDrc *drc; @@ -1652,8 +1653,13 @@ static void spapr_handle_transient_dev_before_cas(SpaprMachineState *spapr) /* * This will complete any pending plug/unplug requests. + * In case of a unplugged PHB or PCI bridge, this will + * cause some DRCs to be destroyed and thus potentially + * invalidate the iterator. */ - spapr_drc_reset(drc); + if (spapr_drc_reset(drc)) { + goto restart; + } } spapr_clear_pending_hotplug_events(spapr); From patchwork Fri Dec 18 10:33:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kurz X-Patchwork-Id: 11981675 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60D45C4361B for ; Fri, 18 Dec 2020 10:38:03 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C9F8A23A7B for ; Fri, 18 Dec 2020 10:38:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C9F8A23A7B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=kaod.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:60758 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kqD97-0005cM-L8 for qemu-devel@archiver.kernel.org; Fri, 18 Dec 2020 05:38:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45920) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kqD5T-0000jH-1N for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:15 -0500 Received: from us-smtp-delivery-44.mimecast.com ([207.211.30.44]:36968) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kqD5R-0001yi-5R for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:14 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-179-xrFI2bRXO6yBgkg2dL775g-1; Fri, 18 Dec 2020 05:34:08 -0500 X-MC-Unique: xrFI2bRXO6yBgkg2dL775g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1B414801B16; Fri, 18 Dec 2020 10:34:07 +0000 (UTC) Received: from bahia.redhat.com (ovpn-114-254.ams2.redhat.com [10.36.114.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id E97A860BE5; Fri, 18 Dec 2020 10:34:05 +0000 (UTC) From: Greg Kurz To: qemu-devel@nongnu.org Subject: [PATCH 3/6] spapr: Introduce spapr_drc_reset_all() Date: Fri, 18 Dec 2020 11:33:57 +0100 Message-Id: <20201218103400.689660-4-groug@kaod.org> In-Reply-To: <20201218103400.689660-1-groug@kaod.org> References: <20201218103400.689660-1-groug@kaod.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kaod.org Received-SPF: softfail client-ip=207.211.30.44; envelope-from=groug@kaod.org; helo=us-smtp-delivery-44.mimecast.com X-Spam_score_int: -11 X-Spam_score: -1.2 X-Spam_bar: - X-Spam_report: (-1.2 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Henrique Barboza , qemu-ppc@nongnu.org, Greg Kurz , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" No need to expose the way DRCs are traversed outside of spapr_drc.c. Signed-off-by: Greg Kurz Reviewed-by: Daniel Henrique Barboza --- include/hw/ppc/spapr_drc.h | 6 ++++++ hw/ppc/spapr_drc.c | 31 +++++++++++++++++++++++++++++ hw/ppc/spapr_hcall.c | 40 ++++++-------------------------------- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index 5d80019f82e2..8982927d5c24 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -245,6 +245,12 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask); void spapr_drc_attach(SpaprDrc *drc, DeviceState *d); void spapr_drc_detach(SpaprDrc *drc); +/* + * Reset all DRCs, causing pending hot-plug/unplug requests to complete. + * Safely handles potential DRC removal (eg. PHBs or PCI bridges). + */ +void spapr_drc_reset_all(struct SpaprMachineState *spapr); + static inline bool spapr_drc_unplug_requested(SpaprDrc *drc) { return drc->unplug_requested; diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 5b5e2ac58a7e..a4d2608017c5 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -949,6 +949,37 @@ out: return ret; } +void spapr_drc_reset_all(SpaprMachineState *spapr) +{ + Object *drc_container; + ObjectProperty *prop; + ObjectPropertyIterator iter; + + drc_container = container_get(object_get_root(), DRC_CONTAINER_PATH); +restart: + object_property_iter_init(&iter, drc_container); + while ((prop = object_property_iter_next(&iter))) { + SpaprDrc *drc; + + if (!strstart(prop->type, "link<", NULL)) { + continue; + } + drc = SPAPR_DR_CONNECTOR(object_property_get_link(drc_container, + prop->name, + &error_abort)); + + /* + * This will complete any pending plug/unplug requests. + * In case of a unplugged PHB or PCI bridge, this will + * cause some DRCs to be destroyed and thus potentially + * invalidate the iterator. + */ + if (spapr_drc_reset(drc)) { + goto restart; + } + } +} + /* * RTAS calls */ diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index aa22830ac4bd..e5dfc1ba7acc 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1632,39 +1632,6 @@ static uint32_t cas_check_pvr(PowerPCCPU *cpu, uint32_t max_compat, return best_compat; } -static void spapr_handle_transient_dev_before_cas(SpaprMachineState *spapr) -{ - Object *drc_container; - ObjectProperty *prop; - ObjectPropertyIterator iter; - - drc_container = container_get(object_get_root(), "/dr-connector"); -restart: - object_property_iter_init(&iter, drc_container); - while ((prop = object_property_iter_next(&iter))) { - SpaprDrc *drc; - - if (!strstart(prop->type, "link<", NULL)) { - continue; - } - drc = SPAPR_DR_CONNECTOR(object_property_get_link(drc_container, - prop->name, - &error_abort)); - - /* - * This will complete any pending plug/unplug requests. - * In case of a unplugged PHB or PCI bridge, this will - * cause some DRCs to be destroyed and thus potentially - * invalidate the iterator. - */ - if (spapr_drc_reset(drc)) { - goto restart; - } - } - - spapr_clear_pending_hotplug_events(spapr); -} - target_ulong do_client_architecture_support(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong vec, @@ -1822,7 +1789,12 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu, spapr_irq_update_active_intc(spapr); - spapr_handle_transient_dev_before_cas(spapr); + /* + * Process all pending hot-plug/unplug requests now. An updated full + * rendered FDT will be returned to the guest. + */ + spapr_drc_reset_all(spapr); + spapr_clear_pending_hotplug_events(spapr); /* * If spapr_machine_reset() did not set up a HPT but one is necessary From patchwork Fri Dec 18 10:33:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kurz X-Patchwork-Id: 11981685 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AB64DC4361B for ; Fri, 18 Dec 2020 10:41:39 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2DC4A23A62 for ; Fri, 18 Dec 2020 10:41:39 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2DC4A23A62 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=kaod.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:44832 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kqDCa-0002XI-LE for qemu-devel@archiver.kernel.org; Fri, 18 Dec 2020 05:41:36 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45952) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kqD5V-0000kO-Nq for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:17 -0500 Received: from us-smtp-delivery-44.mimecast.com ([205.139.111.44]:31670) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kqD5T-0001zM-7M for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:16 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-86-LEGz206sOdCmX2uoMkzq-g-1; Fri, 18 Dec 2020 05:34:09 -0500 X-MC-Unique: LEGz206sOdCmX2uoMkzq-g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 8E8B9104ED15; Fri, 18 Dec 2020 10:34:08 +0000 (UTC) Received: from bahia.redhat.com (ovpn-114-254.ams2.redhat.com [10.36.114.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6796460BE5; Fri, 18 Dec 2020 10:34:07 +0000 (UTC) From: Greg Kurz To: qemu-devel@nongnu.org Subject: [PATCH 4/6] spapr: Use spapr_drc_reset_all() at machine reset Date: Fri, 18 Dec 2020 11:33:58 +0100 Message-Id: <20201218103400.689660-5-groug@kaod.org> In-Reply-To: <20201218103400.689660-1-groug@kaod.org> References: <20201218103400.689660-1-groug@kaod.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=groug@kaod.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kaod.org Received-SPF: softfail client-ip=205.139.111.44; envelope-from=groug@kaod.org; helo=us-smtp-delivery-44.mimecast.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Henrique Barboza , qemu-ppc@nongnu.org, Greg Kurz , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Documentation of object_child_foreach_recursive() clearly stipulates that "it is forbidden to add or remove children from @obj from the @fn callback". But this is exactly what we do during machine reset. The call to spapr_drc_reset() can finalize the hot-unplug sequence of a PHB or a PCI bridge, both of which will then in turn destroy their PCI DRCs. This could potentially invalidate the iterator used by do_object_child_foreach(). It is pure luck that this haven't caused any issues so far. Use spapr_drc_reset_all() since it can cope with DRC removal. Signed-off-by: Greg Kurz Reviewed-by: Daniel Henrique Barboza --- hw/ppc/spapr.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 43dded87f498..8528bc90fec4 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1566,19 +1566,6 @@ void spapr_setup_hpt(SpaprMachineState *spapr) } } -static int spapr_reset_drcs(Object *child, void *opaque) -{ - SpaprDrc *drc = - (SpaprDrc *) object_dynamic_cast(child, - TYPE_SPAPR_DR_CONNECTOR); - - if (drc) { - spapr_drc_reset(drc); - } - - return 0; -} - static void spapr_machine_reset(MachineState *machine) { SpaprMachineState *spapr = SPAPR_MACHINE(machine); @@ -1633,7 +1620,7 @@ static void spapr_machine_reset(MachineState *machine) * will crash QEMU if the DIMM holding the vring goes away). To avoid such * situations, we reset DRCs after all devices have been reset. */ - object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL); + spapr_drc_reset_all(spapr); spapr_clear_pending_events(spapr); From patchwork Fri Dec 18 10:33:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kurz X-Patchwork-Id: 11981679 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 40FADC4361B for ; Fri, 18 Dec 2020 10:39:54 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CDB9823A62 for ; Fri, 18 Dec 2020 10:39:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CDB9823A62 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=kaod.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:38328 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kqDAu-0008Ai-Ti for qemu-devel@archiver.kernel.org; Fri, 18 Dec 2020 05:39:52 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46002) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kqD5Z-0000ta-9u for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:21 -0500 Received: from us-smtp-delivery-44.mimecast.com ([205.139.111.44]:40715) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kqD5V-00020Q-Jr for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:21 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-106-CWDrG8YIPFSicWchJJz8OQ-1; Fri, 18 Dec 2020 05:34:11 -0500 X-MC-Unique: CWDrG8YIPFSicWchJJz8OQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0ED1983DBC7; Fri, 18 Dec 2020 10:34:10 +0000 (UTC) Received: from bahia.redhat.com (ovpn-114-254.ams2.redhat.com [10.36.114.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id DAECB60BE5; Fri, 18 Dec 2020 10:34:08 +0000 (UTC) From: Greg Kurz To: qemu-devel@nongnu.org Subject: [PATCH 5/6] spapr: Add drc_ prefix to the DRC realize and unrealize functions Date: Fri, 18 Dec 2020 11:33:59 +0100 Message-Id: <20201218103400.689660-6-groug@kaod.org> In-Reply-To: <20201218103400.689660-1-groug@kaod.org> References: <20201218103400.689660-1-groug@kaod.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=groug@kaod.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kaod.org Received-SPF: softfail client-ip=205.139.111.44; envelope-from=groug@kaod.org; helo=us-smtp-delivery-44.mimecast.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Henrique Barboza , qemu-ppc@nongnu.org, Greg Kurz , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Use a less generic name for an easier experience with tools such as cscope or grep. Signed-off-by: Greg Kurz Reviewed-by: Daniel Henrique Barboza --- hw/ppc/spapr_drc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index a4d2608017c5..8571d5bafe4e 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -503,7 +503,7 @@ static const VMStateDescription vmstate_spapr_drc = { } }; -static void realize(DeviceState *d, Error **errp) +static void drc_realize(DeviceState *d, Error **errp) { SpaprDrc *drc = SPAPR_DR_CONNECTOR(d); Object *root_container; @@ -530,7 +530,7 @@ static void realize(DeviceState *d, Error **errp) trace_spapr_drc_realize_complete(spapr_drc_index(drc)); } -static void unrealize(DeviceState *d) +static void drc_unrealize(DeviceState *d) { SpaprDrc *drc = SPAPR_DR_CONNECTOR(d); Object *root_container; @@ -579,8 +579,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) { DeviceClass *dk = DEVICE_CLASS(k); - dk->realize = realize; - dk->unrealize = unrealize; + dk->realize = drc_realize; + dk->unrealize = drc_unrealize; /* * Reason: DR connector needs to be wired to either the machine or to a * PHB in spapr_dr_connector_new(). @@ -628,7 +628,7 @@ static void realize_physical(DeviceState *d, Error **errp) SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d); Error *local_err = NULL; - realize(d, &local_err); + drc_realize(d, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -644,7 +644,7 @@ static void unrealize_physical(DeviceState *d) { SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d); - unrealize(d); + drc_unrealize(d); vmstate_unregister(VMSTATE_IF(drcp), &vmstate_spapr_drc_physical, drcp); qemu_unregister_reset(drc_physical_reset, drcp); } From patchwork Fri Dec 18 10:34:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kurz X-Patchwork-Id: 11981671 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8763AC4361B for ; Fri, 18 Dec 2020 10:36:31 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F14F123A7B for ; Fri, 18 Dec 2020 10:36:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F14F123A7B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=kaod.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:55406 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kqD7d-0003P4-UA for qemu-devel@archiver.kernel.org; Fri, 18 Dec 2020 05:36:29 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46006) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kqD5Z-0000uz-Sn for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:21 -0500 Received: from us-smtp-delivery-44.mimecast.com ([205.139.111.44]:53990) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kqD5V-00020M-HH for qemu-devel@nongnu.org; Fri, 18 Dec 2020 05:34:21 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-478-LGMM8i7LN8Ovh-JGaMoIig-1; Fri, 18 Dec 2020 05:34:12 -0500 X-MC-Unique: LGMM8i7LN8Ovh-JGaMoIig-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 848C2800479; Fri, 18 Dec 2020 10:34:11 +0000 (UTC) Received: from bahia.redhat.com (ovpn-114-254.ams2.redhat.com [10.36.114.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5B0E560C47; Fri, 18 Dec 2020 10:34:10 +0000 (UTC) From: Greg Kurz To: qemu-devel@nongnu.org Subject: [PATCH 6/6] spapr: Model DR connectors as simple objects Date: Fri, 18 Dec 2020 11:34:00 +0100 Message-Id: <20201218103400.689660-7-groug@kaod.org> In-Reply-To: <20201218103400.689660-1-groug@kaod.org> References: <20201218103400.689660-1-groug@kaod.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=groug@kaod.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kaod.org Received-SPF: softfail client-ip=205.139.111.44; envelope-from=groug@kaod.org; helo=us-smtp-delivery-44.mimecast.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Henrique Barboza , qemu-ppc@nongnu.org, Greg Kurz , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Modeling DR connectors as individual devices raises some concerns, as already discussed a year ago in this thread: https://patchew.org/QEMU/20191017205953.13122-1-cheloha@linux.vnet.ibm.com/ First, high maxmem settings creates too many DRC devices. This causes scalability issues. It severely increase boot time because the multiple traversals of the DRC list that are performed during machine setup are quadratic operations. This is directly related to the fact that DRCs are modeled as individual devices and added to the composition tree. Second, DR connectors are really an internal concept of PAPR. They aren't something that the user or management layer can manipulate in any way. We already don't allow their creation with device_add by clearing user_creatable. DR connectors don't even need to be modeled as actual devices since they don't sit in a bus. They just need to be associated to an 'owner' object and to have the equivalent of realize/unrealize functions. Downgrade them to be simple objects. Convert the existing realize() and unrealize() to be methods of the DR connector base class. Also have the base class to inherit from the vmstate_if interface directly. The get_id() hook simply returns NULL, just as device_vmstate_if_get_id() does for devices that don't sit in a bus. The DR connector is no longer made a child object. This means that it must be explicitely freed when no longer needed. This is only required for PHBs and PCI bridges actually : have them to free the DRC with spapr_dr_connector_free() instead of object_unparent(). No longer add the DRCs to the QOM composition tree. Track them with a glib hash table using the global DRC index as the key instead. This makes traversal a linear operation. Signed-off-by: Greg Kurz Reviewed-by: Daniel Henrique Barboza --- include/hw/ppc/spapr_drc.h | 8 +- hw/ppc/spapr_drc.c | 166 ++++++++++++++----------------------- hw/ppc/spapr_pci.c | 2 +- 3 files changed, 69 insertions(+), 107 deletions(-) diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index 8982927d5c24..a26aa8b9d4c3 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -170,7 +170,7 @@ typedef enum { typedef struct SpaprDrc { /*< private >*/ - DeviceState parent; + Object parent; uint32_t id; Object *owner; @@ -193,7 +193,7 @@ struct SpaprMachineState; typedef struct SpaprDrcClass { /*< private >*/ - DeviceClass parent; + ObjectClass parent; SpaprDrcState empty_state; SpaprDrcState ready_state; @@ -209,6 +209,9 @@ typedef struct SpaprDrcClass { int (*dt_populate)(SpaprDrc *drc, struct SpaprMachineState *spapr, void *fdt, int *fdt_start_offset, Error **errp); + + void (*realize)(SpaprDrc *drc); + void (*unrealize)(SpaprDrc *drc); } SpaprDrcClass; typedef struct SpaprDrcPhysical { @@ -232,6 +235,7 @@ SpaprDrcType spapr_drc_type(SpaprDrc *drc); SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type, uint32_t id); +void spapr_dr_connector_free(SpaprDrc *drc); SpaprDrc *spapr_drc_by_index(uint32_t index); SpaprDrc *spapr_drc_by_id(const char *type, uint32_t id); int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask); diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 8571d5bafe4e..e26763f8b5a4 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -27,7 +27,6 @@ #include "sysemu/reset.h" #include "trace.h" -#define DRC_CONTAINER_PATH "/dr-connector" #define DRC_INDEX_TYPE_SHIFT 28 #define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1) @@ -503,65 +502,56 @@ static const VMStateDescription vmstate_spapr_drc = { } }; -static void drc_realize(DeviceState *d, Error **errp) +static GHashTable *drc_hash_table(void) { - SpaprDrc *drc = SPAPR_DR_CONNECTOR(d); - Object *root_container; - gchar *link_name; - const char *child_name; + static GHashTable *dht; + if (!dht) { + dht = g_hash_table_new(NULL, NULL); + } + + return dht; +} + + +static void drc_realize(SpaprDrc *drc) +{ trace_spapr_drc_realize(spapr_drc_index(drc)); - /* NOTE: we do this as part of realize/unrealize due to the fact - * that the guest will communicate with the DRC via RTAS calls - * referencing the global DRC index. By unlinking the DRC - * from DRC_CONTAINER_PATH/ we effectively make it - * inaccessible by the guest, since lookups rely on this path - * existing in the composition tree - */ - root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); - link_name = g_strdup_printf("%x", spapr_drc_index(drc)); - child_name = object_get_canonical_path_component(OBJECT(drc)); - trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name); - object_property_add_alias(root_container, link_name, - drc->owner, child_name); - g_free(link_name); + + g_hash_table_insert(drc_hash_table(), + GUINT_TO_POINTER(spapr_drc_index(drc)), drc); vmstate_register(VMSTATE_IF(drc), spapr_drc_index(drc), &vmstate_spapr_drc, drc); trace_spapr_drc_realize_complete(spapr_drc_index(drc)); } -static void drc_unrealize(DeviceState *d) +static void drc_unrealize(SpaprDrc *drc) { - SpaprDrc *drc = SPAPR_DR_CONNECTOR(d); - Object *root_container; - gchar *name; - trace_spapr_drc_unrealize(spapr_drc_index(drc)); vmstate_unregister(VMSTATE_IF(drc), &vmstate_spapr_drc, drc); - root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); - name = g_strdup_printf("%x", spapr_drc_index(drc)); - object_property_del(root_container, name); - g_free(name); + g_hash_table_remove(drc_hash_table(), + GUINT_TO_POINTER(spapr_drc_index(drc))); } SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type, uint32_t id) { SpaprDrc *drc = SPAPR_DR_CONNECTOR(object_new(type)); - char *prop_name; drc->id = id; - drc->owner = owner; - prop_name = g_strdup_printf("dr-connector[%"PRIu32"]", - spapr_drc_index(drc)); - object_property_add_child(owner, prop_name, OBJECT(drc)); - object_unref(OBJECT(drc)); - qdev_realize(DEVICE(drc), NULL, NULL); - g_free(prop_name); + drc->owner = object_ref(owner); + SPAPR_DR_CONNECTOR_GET_CLASS(drc)->realize(drc); return drc; } +void spapr_dr_connector_free(SpaprDrc *drc) +{ + SPAPR_DR_CONNECTOR_GET_CLASS(drc)->unrealize(drc); + object_unref(drc->owner); + object_unref(drc); +} + static void spapr_dr_connector_instance_init(Object *obj) { SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj); @@ -575,17 +565,19 @@ static void spapr_dr_connector_instance_init(Object *obj) drc->state = drck->empty_state; } +static char *drc_vmstate_if_get_id(VMStateIf *obj) +{ + return NULL; +} + static void spapr_dr_connector_class_init(ObjectClass *k, void *data) { - DeviceClass *dk = DEVICE_CLASS(k); + SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); + VMStateIfClass *vc = VMSTATE_IF_CLASS(k); - dk->realize = drc_realize; - dk->unrealize = drc_unrealize; - /* - * Reason: DR connector needs to be wired to either the machine or to a - * PHB in spapr_dr_connector_new(). - */ - dk->user_creatable = false; + drck->realize = drc_realize; + drck->unrealize = drc_unrealize; + vc->get_id = drc_vmstate_if_get_id; } static bool drc_physical_needed(void *opaque) @@ -623,39 +615,32 @@ static void drc_physical_reset(void *opaque) } } -static void realize_physical(DeviceState *d, Error **errp) +static void realize_physical(SpaprDrc *drc) { - SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d); - Error *local_err = NULL; - - drc_realize(d, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } + SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(drc); + drc_realize(drc); vmstate_register(VMSTATE_IF(drcp), spapr_drc_index(SPAPR_DR_CONNECTOR(drcp)), &vmstate_spapr_drc_physical, drcp); qemu_register_reset(drc_physical_reset, drcp); } -static void unrealize_physical(DeviceState *d) +static void unrealize_physical(SpaprDrc *drc) { - SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d); + SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(drc); - drc_unrealize(d); - vmstate_unregister(VMSTATE_IF(drcp), &vmstate_spapr_drc_physical, drcp); qemu_unregister_reset(drc_physical_reset, drcp); + vmstate_unregister(VMSTATE_IF(drcp), &vmstate_spapr_drc_physical, drcp); + drc_unrealize(drc); } static void spapr_drc_physical_class_init(ObjectClass *k, void *data) { - DeviceClass *dk = DEVICE_CLASS(k); SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); - dk->realize = realize_physical; - dk->unrealize = unrealize_physical; + drck->realize = realize_physical; + drck->unrealize = unrealize_physical; drck->dr_entity_sense = physical_entity_sense; drck->isolate = drc_isolate_physical; drck->unisolate = drc_unisolate_physical; @@ -731,12 +716,16 @@ static void spapr_drc_pmem_class_init(ObjectClass *k, void *data) static const TypeInfo spapr_dr_connector_info = { .name = TYPE_SPAPR_DR_CONNECTOR, - .parent = TYPE_DEVICE, + .parent = TYPE_OBJECT, .instance_size = sizeof(SpaprDrc), .instance_init = spapr_dr_connector_instance_init, .class_size = sizeof(SpaprDrcClass), .class_init = spapr_dr_connector_class_init, .abstract = true, + .interfaces = (InterfaceInfo[]) { + { TYPE_VMSTATE_IF }, + { } + }, }; static const TypeInfo spapr_drc_physical_info = { @@ -789,14 +778,9 @@ static const TypeInfo spapr_drc_pmem_info = { SpaprDrc *spapr_drc_by_index(uint32_t index) { - Object *obj; - gchar *name; - - name = g_strdup_printf("%s/%x", DRC_CONTAINER_PATH, index); - obj = object_resolve_path(name, NULL); - g_free(name); - - return !obj ? NULL : SPAPR_DR_CONNECTOR(obj); + return + SPAPR_DR_CONNECTOR(g_hash_table_lookup(drc_hash_table(), + GUINT_TO_POINTER(index))); } SpaprDrc *spapr_drc_by_id(const char *type, uint32_t id) @@ -824,13 +808,12 @@ SpaprDrc *spapr_drc_by_id(const char *type, uint32_t id) */ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask) { - Object *root_container; - ObjectProperty *prop; - ObjectPropertyIterator iter; + GHashTableIter iter; uint32_t drc_count = 0; GArray *drc_indexes, *drc_power_domains; GString *drc_names, *drc_types; int ret; + SpaprDrc *drc; /* * This should really be only called once per node since it overwrites @@ -851,26 +834,12 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask) drc_names = g_string_set_size(g_string_new(NULL), sizeof(uint32_t)); drc_types = g_string_set_size(g_string_new(NULL), sizeof(uint32_t)); - /* aliases for all DRConnector objects will be rooted in QOM - * composition tree at DRC_CONTAINER_PATH - */ - root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); - - object_property_iter_init(&iter, root_container); - while ((prop = object_property_iter_next(&iter))) { - Object *obj; - SpaprDrc *drc; + g_hash_table_iter_init(&iter, drc_hash_table()); + while (g_hash_table_iter_next(&iter, NULL, (gpointer) &drc)) { SpaprDrcClass *drck; char *drc_name = NULL; uint32_t drc_index, drc_power_domain; - if (!strstart(prop->type, "link<", NULL)) { - continue; - } - - obj = object_property_get_link(root_container, prop->name, - &error_abort); - drc = SPAPR_DR_CONNECTOR(obj); drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); if (owner && (drc->owner != owner)) { @@ -951,23 +920,12 @@ out: void spapr_drc_reset_all(SpaprMachineState *spapr) { - Object *drc_container; - ObjectProperty *prop; - ObjectPropertyIterator iter; + GHashTableIter iter; + SpaprDrc *drc; - drc_container = container_get(object_get_root(), DRC_CONTAINER_PATH); restart: - object_property_iter_init(&iter, drc_container); - while ((prop = object_property_iter_next(&iter))) { - SpaprDrc *drc; - - if (!strstart(prop->type, "link<", NULL)) { - continue; - } - drc = SPAPR_DR_CONNECTOR(object_property_get_link(drc_container, - prop->name, - &error_abort)); - + g_hash_table_iter_init(&iter, drc_hash_table()); + while (g_hash_table_iter_next(&iter, NULL, (gpointer) &drc)) { /* * This will complete any pending plug/unplug requests. * In case of a unplugged PHB or PCI bridge, this will diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 76d7c91e9c64..ca0cca664e3c 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1262,7 +1262,7 @@ static void remove_drcs(SpaprPhbState *phb, PCIBus *bus) SpaprDrc *drc = drc_from_devfn(phb, chassis, i); if (drc) { - object_unparent(OBJECT(drc)); + spapr_dr_connector_free(drc); } } }