From: Ruslan Ruslichenko <[email protected]> Add support for grouping CPUs into clusters during FDT machine instantiation.
The clusters are automatically created if CPU parent is not already an existing cluster. Signed-off-by: Ruslan Ruslichenko <[email protected]> --- hw/core/fdt_generic.c | 77 +++++++++++++++++++++++++++++++++++ include/hw/core/fdt_generic.h | 13 ++++++ 2 files changed, 90 insertions(+) diff --git a/hw/core/fdt_generic.c b/hw/core/fdt_generic.c index b3ef0b7d0a..3c28f42491 100644 --- a/hw/core/fdt_generic.c +++ b/hw/core/fdt_generic.c @@ -31,6 +31,7 @@ #include "migration/vmstate.h" #include "qemu/coroutine.h" #include "qemu/log.h" +#include "hw/cpu/cluster.h" #include "system/reset.h" #ifndef FDT_GENERIC_ERR_DEBUG @@ -175,6 +176,75 @@ int fdt_init_has_opaque(FDTMachineInfo *fdti, char *node_path) return 0; } +static int get_next_cpu_cluster_id(void) +{ + static int i; + + return i++; +} + +void fdt_init_register_user_cpu_cluster(FDTMachineInfo *fdti, Object *cluster) +{ + int i = get_next_cpu_cluster_id(); + DeviceState *dev = DEVICE(cluster); + FDTCPUCluster *cl; + + qdev_prop_set_uint32(dev, "cluster-id", i); + + cl = g_new0(FDTCPUCluster, 1); + cl->cpu_cluster = cluster; + cl->next = fdti->clusters; + cl->user = true; + + fdti->clusters = cl; + + DB_PRINT(0, "%s: Registered user-defined cpu cluster with id %d\n", + object_get_canonical_path(cluster), i); +} + +static void *fdt_init_add_cpu_cluster(FDTMachineInfo *fdti, char *compat) +{ + FDTCPUCluster *cl = g_malloc0(sizeof(*cl)); + int i = get_next_cpu_cluster_id(); + char *name = g_strdup_printf("cluster%d", i); + Object *obj; + + obj = object_new(TYPE_CPU_CLUSTER); + object_property_add_child(object_get_root(), name, OBJECT(obj)); + qdev_prop_set_uint32(DEVICE(obj), "cluster-id", i); + + cl->cpu_type = g_strdup(compat); + cl->cpu_cluster = obj; + cl->next = fdti->clusters; + + fdti->clusters = cl; + + g_free(name); + + return obj; +} + +void *fdt_init_get_cpu_cluster(FDTMachineInfo *fdti, Object *parent, + char *compat) +{ + FDTCPUCluster *cl = fdti->clusters; + + if (object_dynamic_cast(parent, TYPE_CPU_CLUSTER)) { + /* The direct parent of this CPU is a CPU cluster. Use it. */ + return parent; + } + + while (cl) { + if (!cl->user && !strcmp(compat, cl->cpu_type)) { + return cl->cpu_cluster; + } + cl = cl->next; + } + + /* No cluster found so create and return a new one */ + return fdt_init_add_cpu_cluster(fdti, compat); +} + void *fdt_init_get_opaque(FDTMachineInfo *fdti, char *node_path) { FDTDevOpaque *dp; @@ -199,8 +269,15 @@ FDTMachineInfo *fdt_init_new_fdti(void *fdt) void fdt_init_destroy_fdti(FDTMachineInfo *fdti) { + FDTCPUCluster *cl = fdti->clusters; FDTDevOpaque *dp; + while (cl) { + FDTCPUCluster *tmp = cl; + cl = cl->next; + g_free(tmp->cpu_type); + g_free(tmp); + } for (dp = fdti->dev_opaques; dp->node_path; dp++) { g_free(dp->node_path); } diff --git a/include/hw/core/fdt_generic.h b/include/hw/core/fdt_generic.h index a21e3c2440..46b7dc084b 100644 --- a/include/hw/core/fdt_generic.h +++ b/include/hw/core/fdt_generic.h @@ -17,6 +17,13 @@ typedef struct FDTDevOpaque { void *opaque; } FDTDevOpaque; +typedef struct FDTCPUCluster { + char *cpu_type; + void *cpu_cluster; + void *next; + bool user; +} FDTCPUCluster; + typedef struct FDTMachineInfo { /* the fdt blob */ void *fdt; @@ -26,6 +33,8 @@ typedef struct FDTMachineInfo { FDTDevOpaque *dev_opaques; /* recheck coroutine queue */ CoQueue *cq; + /* list of all CPU clusters */ + FDTCPUCluster *clusters; } FDTMachineInfo; /* @@ -73,6 +82,10 @@ void fdt_init_set_opaque(FDTMachineInfo *fdti, char *node_path, void *opaque); int fdt_init_has_opaque(FDTMachineInfo *fdti, char *node_path); void *fdt_init_get_opaque(FDTMachineInfo *fdti, char *node_path); +void *fdt_init_get_cpu_cluster(FDTMachineInfo *fdti, Object *parent, + char *compat); +void fdt_init_register_user_cpu_cluster(FDTMachineInfo *fdti, Object *cluster); + /* statically register a FDTInitFn as being associate with a compatibility */ #define fdt_register_compatibility_opaque(function, compat, n, opaque) \ -- 2.43.0
