computing-offload/generic_vdpa/qemu/arm-virt-Add-CPU-topology-support.patch
jiangdongxu 79c4324644 add generic_vdpa basecode
Change-Id: I2d302dda68298877c65c99147f5bf22186a59aac
2024-09-19 17:19:46 +08:00

270 lines
10 KiB
Diff

From 5454c00908236dcabcbf9ae246ccb69e1fcea72e Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
Date: Mon, 6 Apr 2020 10:54:35 +0800
Subject: [PATCH] arm/virt: Add CPU topology support
The CPU topology specified by user (through -smp options) is used in
ACPI PPTT. Now we will use this information to locate which CPU to
plug or unplug.
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
hw/arm/virt.c | 87 ++++++++++++++++++++++++++++++++++++++-
include/hw/arm/topology.h | 68 ++++++++++++++++++++++++++++++
qapi/machine.json | 2 +
target/arm/cpu.c | 4 ++
target/arm/cpu.h | 4 ++
5 files changed, 163 insertions(+), 2 deletions(-)
create mode 100644 include/hw/arm/topology.h
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 11155fcb70..a12e718686 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -39,6 +39,7 @@
#include "hw/sysbus.h"
#include "hw/arm/boot.h"
#include "hw/arm/primecell.h"
+#include "hw/arm/topology.h"
#include "hw/arm/virt.h"
#include "hw/block/flash.h"
#include "hw/vfio/vfio-calxeda-xgmac.h"
@@ -2524,6 +2525,7 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
int n;
unsigned int max_cpus = ms->smp.max_cpus;
VirtMachineState *vms = VIRT_MACHINE(ms);
+ ARMCPUTopoInfo topo;
if (ms->possible_cpus) {
assert(ms->possible_cpus->len == max_cpus);
@@ -2535,10 +2537,19 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
ms->possible_cpus->len = max_cpus;
for (n = 0; n < ms->possible_cpus->len; n++) {
ms->possible_cpus->cpus[n].type = ms->cpu_type;
+ ms->possible_cpus->cpus[n].vcpus_count = 1;
ms->possible_cpus->cpus[n].arch_id =
virt_cpu_mp_affinity(vms, n);
+
+ topo_ids_from_idx(n, ms->smp.clusters, ms->smp.cores, ms->smp.threads, &topo);
+ ms->possible_cpus->cpus[n].props.has_socket_id = true;
+ ms->possible_cpus->cpus[n].props.socket_id = topo.pkg_id;
+ ms->possible_cpus->cpus[n].props.has_cluster_id = true;
+ ms->possible_cpus->cpus[n].props.cluster_id = topo.cluster_id;
+ ms->possible_cpus->cpus[n].props.has_core_id = true;
+ ms->possible_cpus->cpus[n].props.core_id = topo.core_id;
ms->possible_cpus->cpus[n].props.has_thread_id = true;
- ms->possible_cpus->cpus[n].props.thread_id = n;
+ ms->possible_cpus->cpus[n].props.thread_id = topo.smt_id;
}
return ms->possible_cpus;
}
@@ -2589,7 +2600,79 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- /* Currently nothing to do */
+ CPUState *cs = CPU(dev);
+ ARMCPUTopoInfo topo;
+ ARMCPU *cpu = ARM_CPU(dev);
+ MachineState *ms = MACHINE(hotplug_dev);
+ int smp_clusters = ms->smp.clusters;
+ int smp_cores = ms->smp.cores;
+ int smp_threads = ms->smp.threads;
+
+ /* if cpu idx is not set, set it based on socket/cluster/core/thread
+ * properties
+ */
+ if (cs->cpu_index == UNASSIGNED_CPU_INDEX) {
+ int max_socket = ms->smp.max_cpus / smp_threads / smp_cores / smp_clusters;
+ if (cpu->socket_id < 0 || cpu->socket_id >= max_socket) {
+ error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u",
+ cpu->socket_id, max_socket - 1);
+ return;
+ }
+ if (cpu->cluster_id < 0 || cpu->cluster_id >= smp_clusters) {
+ error_setg(errp, "Invalid CPU cluster-id: %u must be in range 0:%u",
+ cpu->cluster_id, smp_clusters - 1);
+ return;
+ }
+ if (cpu->core_id < 0 || cpu->core_id >= smp_cores) {
+ error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u",
+ cpu->core_id, smp_cores - 1);
+ return;
+ }
+ if (cpu->thread_id < 0 || cpu->thread_id >= smp_threads) {
+ error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u",
+ cpu->thread_id, smp_threads - 1);
+ return;
+ }
+
+ topo.pkg_id = cpu->socket_id;
+ topo.cluster_id = cpu->cluster_id;
+ topo.core_id = cpu->core_id;
+ topo.smt_id = cpu->thread_id;
+ cs->cpu_index = idx_from_topo_ids(smp_clusters, smp_cores, smp_threads, &topo);
+ }
+
+ /* if 'address' properties socket-id/cluster-id/core-id/thread-id are not
+ * set, set them so that machine_query_hotpluggable_cpus would show correct
+ * values
+ */
+ topo_ids_from_idx(cs->cpu_index, smp_clusters, smp_cores, smp_threads, &topo);
+ if (cpu->socket_id != -1 && cpu->socket_id != topo.pkg_id) {
+ error_setg(errp, "property socket-id: %u doesn't match set idx:"
+ " 0x%x (socket-id: %u)", cpu->socket_id, cs->cpu_index, topo.pkg_id);
+ return;
+ }
+ cpu->socket_id = topo.pkg_id;
+
+ if (cpu->cluster_id != -1 && cpu->cluster_id != topo.cluster_id) {
+ error_setg(errp, "property cluster-id: %u doesn't match set idx:"
+ " 0x%x (cluster-id: %u)", cpu->cluster_id, cs->cpu_index, topo.cluster_id);
+ return;
+ }
+ cpu->cluster_id = topo.cluster_id;
+
+ if (cpu->core_id != -1 && cpu->core_id != topo.core_id) {
+ error_setg(errp, "property core-id: %u doesn't match set idx:"
+ " 0x%x (core-id: %u)", cpu->core_id, cs->cpu_index, topo.core_id);
+ return;
+ }
+ cpu->core_id = topo.core_id;
+
+ if (cpu->thread_id != -1 && cpu->thread_id != topo.smt_id) {
+ error_setg(errp, "property thread-id: %u doesn't match set idx:"
+ " 0x%x (thread-id: %u)", cpu->thread_id, cs->cpu_index, topo.smt_id);
+ return;
+ }
+ cpu->thread_id = topo.smt_id;
}
static void virt_cpu_plug(HotplugHandler *hotplug_dev,
diff --git a/include/hw/arm/topology.h b/include/hw/arm/topology.h
new file mode 100644
index 0000000000..d0dad1a9a3
--- /dev/null
+++ b/include/hw/arm/topology.h
@@ -0,0 +1,68 @@
+/*
+ * ARM CPU topology data structures and functions
+ *
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO.,LTD.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_ARM_TOPOLOGY_H
+#define HW_ARM_TOPOLOGY_H
+
+typedef struct ARMCPUTopoInfo {
+ unsigned pkg_id;
+ unsigned cluster_id;
+ unsigned core_id;
+ unsigned smt_id;
+} ARMCPUTopoInfo;
+
+/* Calculate (contiguous) CPU index based on topology */
+static inline unsigned idx_from_topo_ids(unsigned nr_clusters,
+ unsigned nr_cores,
+ unsigned nr_threads,
+ const ARMCPUTopoInfo *topo)
+{
+ assert(nr_clusters > 0);
+ assert(nr_cores > 0);
+ assert(nr_threads > 0);
+ assert(topo != NULL);
+
+ return topo->pkg_id * nr_clusters * nr_cores * nr_threads +
+ topo->cluster_id * nr_cores +
+ topo->core_id * nr_threads +
+ topo->smt_id;
+}
+
+/* Calculate thread/core/cluster/package topology
+ * based on (contiguous) CPU index
+ */
+static inline void topo_ids_from_idx(unsigned cpu_index,
+ unsigned nr_clusters,
+ unsigned nr_cores,
+ unsigned nr_threads,
+ ARMCPUTopoInfo *topo)
+{
+ assert(nr_clusters > 0);
+ assert(nr_cores > 0);
+ assert(nr_threads > 0);
+ assert(topo != NULL);
+
+ topo->smt_id = cpu_index % nr_threads;
+ topo->core_id = cpu_index / nr_threads % nr_cores;
+ topo->cluster_id = cpu_index / nr_threads / nr_cores % nr_clusters;
+ topo->pkg_id = cpu_index / nr_threads / nr_cores / nr_clusters;
+}
+
+#endif /* HW_ARM_TOPOLOGY_H */
+
diff --git a/qapi/machine.json b/qapi/machine.json
index 8faa51074e..6822cafe2e 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -868,6 +868,7 @@
# @node-id: NUMA node ID the CPU belongs to
# @socket-id: socket number within node/board the CPU belongs to
# @die-id: die number within socket the CPU belongs to (since 4.1)
+# @cluster-id: cluster number within die the CPU belongs to (since 6.2)
# @core-id: core number within die the CPU belongs to
# @thread-id: thread number within core the CPU belongs to
#
@@ -883,6 +884,7 @@
'data': { '*node-id': 'int',
'*socket-id': 'int',
'*die-id': 'int',
+ '*cluster-id': 'int',
'*core-id': 'int',
'*thread-id': 'int'
}
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index f06ba29885..9fd8e57971 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2507,6 +2507,10 @@ static Property arm_cpu_properties[] = {
DEFINE_PROP_UINT64("mp-affinity", ARMCPU,
mp_affinity, ARM64_AFFINITY_INVALID),
DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
+ DEFINE_PROP_INT32("socket-id", ARMCPU, socket_id, -1),
+ DEFINE_PROP_INT32("cluster-id", ARMCPU, cluster_id, -1),
+ DEFINE_PROP_INT32("core-id", ARMCPU, core_id, -1),
+ DEFINE_PROP_INT32("thread-id", ARMCPU, thread_id, -1),
DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 947897d5ac..eb804dffaa 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1006,6 +1006,10 @@ struct ARMCPU {
QLIST_HEAD(, ARMELChangeHook) el_change_hooks;
int32_t node_id; /* NUMA node this CPU belongs to */
+ int32_t socket_id;
+ int32_t cluster_id;
+ int32_t core_id;
+ int32_t thread_id;
/* Used to synchronize KVM and QEMU in-kernel device levels */
uint8_t device_irq_level;
--
2.27.0