From nobody Wed Nov 27 04:29:45 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linux.intel.com ARC-Seal: i=1; a=rsa-sha256; t=1701355101; cv=none; d=zohomail.com; s=zohoarc; b=h9oTSPupQycIQ1swijumCqhKZtmaGgfqskK0GuGnE7bbzRfEIoaNUfXvwD/cavFqgy+xQjqtIfckpyb7SfwuSnDaOJ/pg1t8FjjkTsIDKMjwu5qY/zYCNSEMVgPlWqyUu7+wCvmcOk4TPs8YIegp0kfqswE3s4776FxMsrt4q9s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1701355101; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=KjSZ/wfBM79oEgKz1AQGUDHLr4Q0RYsd4RudUp23ac0=; b=mwxlDvg0Csq8CoEfJsIit9RLpmy67/POh/7ci99HYMXtNoU+GuwwrGTa9CpqZd57ggZFw9CPqYZltUK2Lh6s/OXQUyuANXALgFp3Q8IbiwGQi4kIs+UR5KtThSlH4C0y2/rbAaOhGwn/KtBqj4/oQRWWKvfHNkeS+7b7EHa/Zcw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701355101498313.81045587783433; Thu, 30 Nov 2023 06:38:21 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r8i5K-0001ie-GF; Thu, 30 Nov 2023 09:32:10 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1r8i5I-0001hu-7H; Thu, 30 Nov 2023 09:32:08 -0500 Received: from mgamail.intel.com ([192.55.52.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1r8i5F-00018C-KC; Thu, 30 Nov 2023 09:32:07 -0500 Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Nov 2023 06:31:29 -0800 Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.36]) by orsmga005.jf.intel.com with ESMTP; 30 Nov 2023 06:31:20 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701354725; x=1732890725; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=g5Zw3I63TJXvQFrzB5uJb/WUPaoeW0TH6JE9nfaHRvc=; b=DtFCgq5ZfYZZwboaVejjXjmZjq1YWiMV8Tyka3PX9RxF249nXPy4xBKJ eCjq9WonXpzxZiJFeJ0/2Xa26ejdFFf3d/uSxBpLyaXMwlVdoXCMb5YdV /Q56YliOUjfXnDS7fwn108iEbof8lbde/Dmfrmg5iQUQ3aHa37ufD/hXH FpgA4YhDtj+UwWU4uFqb0ktigdD451j4XDOP5uYgWQdEKDp0OVqXQ2w8C dLMEpJpTZq0i6T+wpi8sLuzv9BX1dg8ay9WRM6NndGmTKU9HQxvJOy+wF NT0EZyldHicXXXZV8w8LZfgxvcINVSBV2jWK5kdDsIWtuUDnfA2QMxnRX g==; X-IronPort-AV: E=McAfee;i="6600,9927,10910"; a="479531263" X-IronPort-AV: E=Sophos;i="6.04,239,1695711600"; d="scan'208";a="479531263" X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10910"; a="942729699" X-IronPort-AV: E=Sophos;i="6.04,239,1695711600"; d="scan'208";a="942729699" From: Zhao Liu To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Eduardo Habkost , Marcel Apfelbaum , Yanan Wang , Richard Henderson , "Michael S . Tsirkin" , Jason Wang , Nicholas Piggin , Daniel Henrique Barboza , Igor Mammedov , =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Barrat?= , David Gibson , Harsh Prateek Bora , Stefano Stabellini , Anthony Perard , Paul Durrant , Gerd Hoffmann , Peter Maydell , Alistair Francis , "Edgar E . Iglesias" , =?UTF-8?q?Daniel=20P=20=2E=20Berrang=C3=A9?= , Bin Meng , Palmer Dabbelt , Weiwei Li , Liu Zhiwei , qemu-devel@nongnu.org, kvm@vger.kernel.org, qemu-ppc@nongnu.org, xen-devel@lists.xenproject.org, qemu-arm@nongnu.org, qemu-riscv@nongnu.org, qemu-s390x@nongnu.org Cc: Nina Schoetterl-Glausch , Thomas Huth , Zhiyuan Lv , Zhenyu Wang , Yongwei Ma , Zhao Liu Subject: [RFC 06/41] qdev: Introduce user-child interface to collect devices from -device Date: Thu, 30 Nov 2023 22:41:28 +0800 Message-Id: <20231130144203.2307629-7-zhao1.liu@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231130144203.2307629-1-zhao1.liu@linux.intel.com> References: <20231130144203.2307629-1-zhao1.liu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: none client-ip=192.55.52.43; envelope-from=zhao1.liu@linux.intel.com; helo=mgamail.intel.com X-Spam_score_int: -42 X-Spam_score: -4.3 X-Spam_bar: ---- X-Spam_report: (-4.3 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1701355103655000019 Content-Type: text/plain; charset="utf-8" From: Zhao Liu Topology relationship is based on child<> property, therefore introduce a new user-child interface to help bus-less devices create child<> property from cli. User-child interface works in qdev_set_id(), where the child<> property is created for cli devices. With several methods, user-child could provide the specific "parent" device other than the default peripheral/peripheral-anon container. The topology root (cpu-slot) could collect topology devices based on user-child implementation. Signed-off-by: Zhao Liu --- MAINTAINERS | 2 + include/monitor/user-child.h | 57 +++++++++++++++++++++++ include/qom/object.h | 11 +++++ qom/object.c | 13 ++++++ system/meson.build | 1 + system/qdev-monitor.c | 89 +++++++++++++++++++++++++++++++++--- system/user-child.c | 72 +++++++++++++++++++++++++++++ 7 files changed, 239 insertions(+), 6 deletions(-) create mode 100644 include/monitor/user-child.h create mode 100644 system/user-child.c diff --git a/MAINTAINERS b/MAINTAINERS index 695e0bd34fbb..fdbabaa983cc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3208,12 +3208,14 @@ F: hw/core/bus.c F: hw/core/sysbus.c F: include/hw/qdev* F: include/monitor/qdev.h +F: include/monitor/user-child.h F: include/qom/ F: qapi/qom.json F: qapi/qdev.json F: scripts/coccinelle/qom-parent-type.cocci F: scripts/qom-cast-macro-clean-cocci-gen.py F: system/qdev-monitor.c +F: system/user-child.c F: stubs/qdev.c F: qom/ F: tests/unit/check-qom-interface.c diff --git a/include/monitor/user-child.h b/include/monitor/user-child.h new file mode 100644 index 000000000000..e246fcefe40a --- /dev/null +++ b/include/monitor/user-child.h @@ -0,0 +1,57 @@ +/* + * Child configurable interface header. + * + * Copyright (c) 2023 Intel Corporation + * Author: Zhao Liu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef USER_CHILD_H +#define USER_CHILD_H + +#include "qom/object.h" + +#define TYPE_USER_CHILD "user-child" + +typedef struct UserChildClass UserChildClass; +DECLARE_CLASS_CHECKERS(UserChildClass, USER_CHILD, TYPE_USER_CHILD) +#define USER_CHILD(obj) INTERFACE_CHECK(UserChild, (obj), TYPE_USER_CHILD) + +typedef struct UserChild UserChild; + +/** + * UserChildClass: + * @get_parent: Method to get the default parent if user doesn't specify + * the parent in cli. + * @get_child_name: Method to get the default device id for this device + * if user doesn't specify id in cli. + * @check_parent: Method to check if the parent specified by user in cli + * is valid. + */ +struct UserChildClass { + /* */ + InterfaceClass parent_class; + + /* */ + Object *(*get_parent)(UserChild *uc, Error **errp); + char *(*get_child_name)(UserChild *uc, Object *parent); + bool (*check_parent)(UserChild *uc, Object *parent); +}; + +Object *uc_provide_default_parent(Object *obj, Error **errp); +char *uc_name_future_child(Object *obj, Object *parent); +bool uc_check_user_parent(Object *obj, Object *parent); + +#endif /* USER_CHILD_H */ diff --git a/include/qom/object.h b/include/qom/object.h index 494eef801be3..f725d9452c76 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -1484,6 +1484,17 @@ Object *object_get_objects_root(void); */ Object *object_get_internal_root(void); =20 +/** + * object_is_child_from: + * @child: the object. + * @parent: the parent/non-direct parent object. + * + * Check whether @parent is the parent/non-direct parent of @child. + * + * Returns: true iff @parent is the parent/non-direct parent of @child. + */ +bool object_is_child_from(const Object *child, const Object *parent); + /** * object_get_canonical_path_component: * @obj: the object diff --git a/qom/object.c b/qom/object.c index da29e88816b5..d6f55aa59504 100644 --- a/qom/object.c +++ b/qom/object.c @@ -2024,6 +2024,19 @@ object_property_add_const_link(Object *obj, const ch= ar *name, NULL, OBJ_PROP_LINK_DIRECT); } =20 +bool object_is_child_from(const Object *child, const Object *parent) +{ + Object *obj =3D child->parent; + + while (obj) { + if (obj =3D=3D parent) { + return true; + } + obj =3D obj->parent; + } + return false; +} + const char *object_get_canonical_path_component(const Object *obj) { ObjectProperty *prop =3D NULL; diff --git a/system/meson.build b/system/meson.build index 3a64dd89de1f..ac682a3ca9e1 100644 --- a/system/meson.build +++ b/system/meson.build @@ -24,6 +24,7 @@ system_ss.add(files( 'runstate-hmp-cmds.c', 'runstate.c', 'tpm-hmp-cmds.c', + 'user-child.c', 'vl.c', ), sdl, libpmem, libdaxctl) =20 diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index 107411bb50cc..0261937b8462 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -22,6 +22,7 @@ #include "monitor/hmp.h" #include "monitor/monitor.h" #include "monitor/qdev.h" +#include "monitor/user-child.h" #include "sysemu/arch_init.h" #include "qapi/error.h" #include "qapi/qapi-commands-qdev.h" @@ -585,26 +586,93 @@ static BusState *qbus_find(const char *path, Error **= errp) return bus; } =20 +static Object *qdev_find_peripheral_parent(DeviceState *dev, + Error **errp) +{ + Object *parent_obj, *obj =3D OBJECT(dev); + + parent_obj =3D uc_provide_default_parent(obj, errp); + if (*errp) { + return NULL; + } + + if (parent_obj) { + /* + * Non-anonymous parents (under "/peripheral") are allowed to + * be accessed to create child<> properties. + */ + if (object_is_child_from(parent_obj, qdev_get_peripheral())) { + return parent_obj; + } + } + + return NULL; +} + +static bool qdev_pre_check_device_id(char *id, Error **errp) +{ + bool ambiguous =3D false; + Object *obj; + + if (!id) { + return true; + } + + obj =3D object_resolve_path_from(qdev_get_peripheral(), id, &ambiguous= ); + if (obj || ambiguous) { + error_setg(errp, "Duplicate device default ID '%s'. " + "Please specify another 'id'", id); + return false; + } + return true; +} + /* Takes ownership of @id, will be freed when deleting the device */ const char *qdev_set_id(DeviceState *dev, char *id, Error **errp) { + Object *parent_obj =3D NULL; ObjectProperty *prop; + UserChild *uc; =20 assert(!dev->id && !dev->realized); =20 + uc =3D (UserChild *)object_dynamic_cast(OBJECT(dev), TYPE_USER_CHILD); + + if (uc) { + parent_obj =3D qdev_find_peripheral_parent(dev, errp); + if (*errp) { + goto err; + } + + if (!id && parent_obj) { + /* + * Covert anonymous device with user-child interface to + * non-anonymous, then it will be insert under "/peripheral" + * path. + */ + id =3D uc_name_future_child(OBJECT(dev), parent_obj); + if (!qdev_pre_check_device_id(id, errp)) { + goto err; + } + } + } + /* * object_property_[try_]add_child() below will assert the device * has no parent */ if (id) { - prop =3D object_property_try_add_child(qdev_get_peripheral(), id, + if (!parent_obj) { + parent_obj =3D qdev_get_peripheral(); + } + + prop =3D object_property_try_add_child(parent_obj, id, OBJECT(dev), NULL); if (prop) { dev->id =3D id; } else { error_setg(errp, "Duplicate device ID '%s'", id); - g_free(id); - return NULL; + goto err; } } else { static int anon_count; @@ -615,6 +683,9 @@ const char *qdev_set_id(DeviceState *dev, char *id, Err= or **errp) } =20 return prop->name; +err: + g_free(id); + return NULL; } =20 DeviceState *qdev_device_add_from_qdict(const QDict *opts, long *category, @@ -885,12 +956,18 @@ void qmp_device_add(QDict *qdict, QObject **ret_data,= Error **errp) =20 static DeviceState *find_device_state(const char *id, Error **errp) { - Object *obj =3D object_resolve_path_at(qdev_get_peripheral(), id); + bool ambiguous =3D false; DeviceState *dev; + Object *obj; =20 + obj =3D object_resolve_path_from(qdev_get_peripheral(), id, &ambiguous= ); if (!obj) { - error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, - "Device '%s' not found", id); + if (ambiguous) { + error_setg(errp, "Device ID '%s' is ambiguous", id); + } else { + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", id); + } return NULL; } =20 diff --git a/system/user-child.c b/system/user-child.c new file mode 100644 index 000000000000..1e667f09cc87 --- /dev/null +++ b/system/user-child.c @@ -0,0 +1,72 @@ +/* + * Child configurable interface. + * + * Copyright (c) 2023 Intel Corporation + * Author: Zhao Liu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "qemu/osdep.h" + +#include "monitor/user-child.h" + +Object *uc_provide_default_parent(Object *obj, Error **errp) +{ + UserChild *uc =3D USER_CHILD(obj); + UserChildClass *ucc =3D USER_CHILD_GET_CLASS(uc); + + if (ucc->get_parent) { + return ucc->get_parent(uc, errp); + } + + return NULL; +} + +char *uc_name_future_child(Object *obj, Object *parent) +{ + UserChild *uc =3D USER_CHILD(obj); + UserChildClass *ucc =3D USER_CHILD_GET_CLASS(uc); + + if (ucc->get_child_name) { + return ucc->get_child_name(uc, parent); + } + + return NULL; +} + +bool uc_check_user_parent(Object *obj, Object *parent) +{ + UserChild *uc =3D USER_CHILD(obj); + UserChildClass *ucc =3D USER_CHILD_GET_CLASS(uc); + + if (ucc->check_parent) { + ucc->check_parent(uc, parent); + } + + return true; +} + +static const TypeInfo user_child_interface_info =3D { + .name =3D TYPE_USER_CHILD, + .parent =3D TYPE_INTERFACE, + .class_size =3D sizeof(UserChildClass), +}; + +static void user_child_register_types(void) +{ + type_register_static(&user_child_interface_info); +} + +type_init(user_child_register_types) --=20 2.34.1