From nobody Wed Nov 27 04:59:04 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=1701354806; cv=none; d=zohomail.com; s=zohoarc; b=Fw14gsFN6BQmKaA0Wc3bOLj3XBpcDzk7kjlgXtq7pBYjV9PNwc/DpFsbNkWsSLWPVk1F/70mfO6TGrjeICMrNTowB+/9pEly9O7lboMXfObUMLOXEtDUAvaes0D5XGVqHUvm2J8uIeFm8VBViOGS4y3rdaFJQ+Awa8P/u540aUw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1701354806; h=Content-Type: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=zAA6Wrn4DxKQJWM8/1wruACjatIykstf7VTwuaQnU/8=; b=V28kMt6zrP5iegwnmYTKBwZaUrrrKxYIJ58nCahi9gf1DCaMZDtqLSfaT7O9gm6q8VP6hxkX6ciBY4UqzrgZontNke2PAaoxb4QxJ5Ehle6RRILbJK4ZK1GM48R7ViPiRoOp5l4zH199K8EpGwS3Dg+WOqfEVC2R3OwaBhHM8Jc= 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 1701354806299468.7994475991974; Thu, 30 Nov 2023 06:33:26 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r8i5Y-000255-4P; Thu, 30 Nov 2023 09:32:24 -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 1r8i5V-0001vV-JX; Thu, 30 Nov 2023 09:32:21 -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 1r8i5T-00018C-2m; Thu, 30 Nov 2023 09:32:21 -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:48 -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:38 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701354739; x=1732890739; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0HgUkt24A8GDXQknSCYGY0tM/5gPDdFuKpTNl12j5yE=; b=ATYa529sz6DHIy+0chUCF3DcQdQ5ao/qjKYG9n7FgDoXWnXwbS/oSWXU 4ya5x/XjDxENInR29dipiz31rLWT+AAfWcbi3uawYAa8GN44+Ld51CE27 7RKBZcmzrPibkbe/sGSgeb6cqVxrnm3bgF8utQ04EDB2nIord+Hr2+QWb i0oUy4vdparRIaDZZJ4qEl3GarrTfdMnyZtHyZHxMpmPv8ukiSe0LfPgY WPGbywUXPIj579WWrPbKClt4FIprbrNH7/jGJ5esKgFXX/7r0yqdfVwQI +SXA+coVaKMf1I8tm6KmM2luiqaXBrsPu1VVsH43NKkce0gH9D2MqP/TN Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10910"; a="479531399" X-IronPort-AV: E=Sophos;i="6.04,239,1695711600"; d="scan'208";a="479531399" X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10910"; a="942729736" X-IronPort-AV: E=Sophos;i="6.04,239,1695711600"; d="scan'208";a="942729736" 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 08/41] hw/core/topo: Introduce CPU topology device abstraction Date: Thu, 30 Nov 2023 22:41:30 +0800 Message-Id: <20231130144203.2307629-9-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-Type: text/plain; charset="utf-8" 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: 1701354806614000001 From: Zhao Liu To create more flexible CPU topologies (both symmetric and heterogeneous) via the "-device" interface, it is necessary to convert the current CPU topology hierarchies into the special CPU topology devices. The CPU topology will be built as a tree, and the device with the CPU_TOPO_ROOT level is the only root of this CPU topology tree. The different levels of CPU topology devices are connected in the "-device" cli with the child<> property, which in turn will be set the Object.parent through the qdev interface. And ultimately at the realize(), CPU topology devices will be linked to their topological parent based on the Object.parent field, and then be inserted into the topology tree. As the first step, introduce the basic CPU topology device abstraction, as well as the topology tree and topology hierarchy construction based on the CPU topology devices. Signed-off-by: Zhao Liu --- MAINTAINERS | 2 + hw/core/cpu-topo.c | 201 +++++++++++++++++++++++++++++++++++++ hw/core/meson.build | 1 + include/hw/core/cpu-topo.h | 79 +++++++++++++++ 4 files changed, 283 insertions(+) create mode 100644 hw/core/cpu-topo.c create mode 100644 include/hw/core/cpu-topo.h diff --git a/MAINTAINERS b/MAINTAINERS index fdbabaa983cc..564cb776ae80 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1854,6 +1854,7 @@ R: Philippe Mathieu-Daud=C3=A9 R: Yanan Wang S: Supported F: hw/core/cpu.c +F: hw/core/cpu-topo.c F: hw/core/machine-qmp-cmds.c F: hw/core/machine.c F: hw/core/machine-smp.c @@ -1865,6 +1866,7 @@ F: qapi/machine-common.json F: qapi/machine-target.json F: include/hw/boards.h F: include/hw/core/cpu.h +F: include/hw/core/cpu-topo.h F: include/hw/cpu/cluster.h F: include/sysemu/numa.h F: tests/unit/test-smp-parse.c diff --git a/hw/core/cpu-topo.c b/hw/core/cpu-topo.c new file mode 100644 index 000000000000..4428b979a5dc --- /dev/null +++ b/hw/core/cpu-topo.c @@ -0,0 +1,201 @@ +/* + * General CPU topology device abstraction + * + * 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 "hw/core/cpu-topo.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" + +static const char *cpu_topo_level_to_string(CPUTopoLevel level) +{ + switch (level) { + case CPU_TOPO_UNKNOWN: + return "unknown"; + case CPU_TOPO_THREAD: + return "thread"; + case CPU_TOPO_CORE: + return "core"; + case CPU_TOPO_CLUSTER: + return "cluster"; + case CPU_TOPO_DIE: + return "die"; + case CPU_TOPO_SOCKET: + return "socket"; + case CPU_TOPO_BOOK: + return "book"; + case CPU_TOPO_DRAWER: + return "drawer"; + case CPU_TOPO_ROOT: + return "root"; + } + + return NULL; +} + +static void cpu_topo_build_hierarchy(CPUTopoState *topo, Error **errp) +{ + CPUTopoState *parent =3D topo->parent; + CPUTopoLevel level =3D CPU_TOPO_LEVEL(topo); + g_autofree char *name =3D NULL; + + if (!parent) { + return; + } + + if (parent->child_level =3D=3D CPU_TOPO_UNKNOWN) { + parent->child_level =3D level; + } else if (parent->child_level !=3D level) { + error_setg(errp, "cpu topo: the parent level %s asks for the " + "%s child, but current level is %s", + cpu_topo_level_to_string(CPU_TOPO_LEVEL(parent)), + cpu_topo_level_to_string(parent->child_level), + cpu_topo_level_to_string(level)); + return; + } + + if (parent->max_children && parent->max_children <=3D parent->num_chil= dren) { + error_setg(errp, "cpu topo: the parent limit the (%d) children, " + "currently it has %d children", + parent->max_children, + parent->num_children); + return; + } + + parent->num_children++; + QTAILQ_INSERT_TAIL(&parent->children, topo, sibling); +} + +static void cpu_topo_set_parent(CPUTopoState *topo, Error **errp) +{ + Object *obj =3D OBJECT(topo); + CPUTopoLevel level =3D CPU_TOPO_LEVEL(topo); + + if (!obj->parent) { + return; + } + + if (object_dynamic_cast(obj->parent, TYPE_CPU_TOPO)) { + CPUTopoState *parent =3D CPU_TOPO(obj->parent); + + if (level >=3D CPU_TOPO_LEVEL(parent)) { + error_setg(errp, "cpu topo: current level (%s) should be " + "lower than parent (%s) level", + object_get_typename(obj), + object_get_typename(OBJECT(parent))); + return; + } + topo->parent =3D parent; + } + + if (topo->parent) { + cpu_topo_build_hierarchy(topo, errp); + } +} + +static void cpu_topo_realize(DeviceState *dev, Error **errp) +{ + CPUTopoState *topo =3D CPU_TOPO(dev); + CPUTopoClass *tc =3D CPU_TOPO_GET_CLASS(topo); + + if (tc->level =3D=3D CPU_TOPO_UNKNOWN) { + error_setg(errp, "cpu topo: no level specified" + " type: %s", object_get_typename(OBJECT(dev))); + return; + } + + cpu_topo_set_parent(topo, errp); +} + +static void cpu_topo_destroy_hierarchy(CPUTopoState *topo) +{ + CPUTopoState *parent =3D topo->parent; + + if (!parent) { + return; + } + + QTAILQ_REMOVE(&parent->children, topo, sibling); + parent->num_children--; + + if (!parent->num_children) { + parent->child_level =3D CPU_TOPO_UNKNOWN; + } +} + +static void cpu_topo_unrealize(DeviceState *dev) +{ + CPUTopoState *topo =3D CPU_TOPO(dev); + + /* + * The specific unrealize method must consider the bottom-up, + * layer-by-layer unrealization implementation. + */ + g_assert(!topo->num_children); + + if (topo->parent) { + cpu_topo_destroy_hierarchy(topo); + } +} + +static void cpu_topo_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + CPUTopoClass *tc =3D CPU_TOPO_CLASS(oc); + + /* All topology devices belong to CPU property. */ + set_bit(DEVICE_CATEGORY_CPU, dc->categories); + dc->realize =3D cpu_topo_realize; + dc->unrealize =3D cpu_topo_unrealize; + + /* + * The general topo device is not hotpluggable by default. + * If any topo device needs hotplug support, this flag must be + * overridden under arch-specific topo device code. + */ + dc->hotpluggable =3D false; + + tc->level =3D CPU_TOPO_UNKNOWN; +} + +static void cpu_topo_instance_init(Object *obj) +{ + CPUTopoState *topo =3D CPU_TOPO(obj); + QTAILQ_INIT(&topo->children); + + topo->child_level =3D CPU_TOPO_UNKNOWN; +} + +static const TypeInfo cpu_topo_type_info =3D { + .name =3D TYPE_CPU_TOPO, + .parent =3D TYPE_DEVICE, + .abstract =3D true, + .class_size =3D sizeof(CPUTopoClass), + .class_init =3D cpu_topo_class_init, + .instance_size =3D sizeof(CPUTopoState), + .instance_init =3D cpu_topo_instance_init, +}; + +static void cpu_topo_register_types(void) +{ + type_register_static(&cpu_topo_type_info); +} + +type_init(cpu_topo_register_types) diff --git a/hw/core/meson.build b/hw/core/meson.build index 67dad04de559..501d2529697e 100644 --- a/hw/core/meson.build +++ b/hw/core/meson.build @@ -23,6 +23,7 @@ else endif =20 common_ss.add(files('cpu-common.c')) +common_ss.add(files('cpu-topo.c')) common_ss.add(files('machine-smp.c')) system_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c')) system_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: files('generic-loade= r.c')) diff --git a/include/hw/core/cpu-topo.h b/include/hw/core/cpu-topo.h new file mode 100644 index 000000000000..ebcbdd854da5 --- /dev/null +++ b/include/hw/core/cpu-topo.h @@ -0,0 +1,79 @@ +/* + * General CPU topology device abstraction + * + * 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 CPU_TOPO_H +#define CPU_TOPO_H + +#include "hw/qdev-core.h" +#include "qemu/queue.h" + +typedef enum CPUTopoLevel { + CPU_TOPO_UNKNOWN, + CPU_TOPO_THREAD, + CPU_TOPO_CORE, + CPU_TOPO_CLUSTER, + CPU_TOPO_DIE, + CPU_TOPO_SOCKET, + CPU_TOPO_BOOK, + CPU_TOPO_DRAWER, + CPU_TOPO_ROOT, +} CPUTopoLevel; + +#define TYPE_CPU_TOPO "cpu-topo" +OBJECT_DECLARE_TYPE(CPUTopoState, CPUTopoClass, CPU_TOPO) + +/** + * CPUTopoClass: + * @level: Topology level for this CPUTopoClass. + */ +struct CPUTopoClass { + /*< private >*/ + DeviceClass parent_class; + + /*< public >*/ + CPUTopoLevel level; +}; + +/** + * CPUTopoState: + * @num_children: Number of topology children under this topology device. + * @max_children: Maximum number of children allowed to be inserted under + * this topology device. + * @child_level: Topology level for children. + * @parent: Topology parent of this topology device. + * @children: Queue of topology children. + * @sibling: Queue node to be inserted in parent's topology queue. + */ +struct CPUTopoState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + int num_children; + int max_children; + CPUTopoLevel child_level; + struct CPUTopoState *parent; + QTAILQ_HEAD(, CPUTopoState) children; + QTAILQ_ENTRY(CPUTopoState) sibling; +}; + +#define CPU_TOPO_LEVEL(topo) (CPU_TOPO_GET_CLASS(topo)->level) + +#endif /* CPU_TOPO_H */ --=20 2.34.1