On Fri, 20 Oct 2023 at 17:36, Philippe Mathieu-Daudé <philmd@xxxxxxxxxx> wrote:
Heterogeneous machines have different type of CPU.
qemu_get_cpu() returning unfiltered CPUs doesn't make
sense anymore. Add a 'type' argument to filter CPU by
QOM type.
I'm not sure "filter by CPU type" is ever really the
correct answer to this problem, though.
Picking out a handful of arm-related parts to this patchset
as examples of different situations where we're currently
using qemu_get_cpu():
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 474cfdc87c..1c1585f3e1 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -212,7 +212,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
for (i = 0; i < smp_cpus; i++) {
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore);
- DeviceState *d = DEVICE(qemu_get_cpu(i));
+ DeviceState *d = DEVICE(qemu_get_cpu(i, NULL));
irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
sysbus_connect_irq(sbd, i, irq);
This is an Arm SoC object. What it wants is not "the i'th Arm
CPU in the whole system", but "the i'th CPU in this SoC object".
Conveniently, it has easy access to that: s->cpu[i].
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
index e7c3d99224..0a698171ab 100644
--- a/hw/arm/pxa2xx_gpio.c
+++ b/hw/arm/pxa2xx_gpio.c
@@ -303,7 +303,7 @@ static void pxa2xx_gpio_realize(DeviceState *dev, Error **errp)
{
PXA2xxGPIOInfo *s = PXA2XX_GPIO(dev);
- s->cpu = ARM_CPU(qemu_get_cpu(s->ncpu));
+ s->cpu = ARM_CPU(qemu_get_cpu(s->ncpu, NULL));
qdev_init_gpio_in(dev, pxa2xx_gpio_set, s->lines);
qdev_init_gpio_out(dev, s->handler, s->lines);
This is grabbing a private pointer to the CPU object[*], which
we can do more cleanly by setting a link property, and getting
the board code to pass a pointer to the CPU.
[*] it then uses that pointer to mess with the internals of
the CPU to implement wake-up-on-GPIO in a completely horrible
way, but let's assume we don't want to try to clean that up now...
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 3c7dfcd6dc..3571d5038f 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -275,7 +275,7 @@ static void create_fdt(SBSAMachineState *sms)
for (cpu = sms->smp_cpus - 1; cpu >= 0; cpu--) {
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
- ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
+ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu, NULL));
CPUState *cs = CPU(armcpu);
uint64_t mpidr = sbsa_ref_cpu_mp_affinity(sms, cpu);
This is in a board model. By definition the board model for a
non-heterogenous board knows it isn't in a heterogenous system
model, and it doesn't need to say "specifically the first Arm CPU".
So I think we should be able to leave it alone...
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index bfd8aa5644..8c9098d5d3 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -65,7 +65,7 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
/* Make the GIC's TZ support match the CPUs. We assume that
* either all the CPUs have TZ, or none do.
*/
- cpuobj = OBJECT(qemu_get_cpu(0));
+ cpuobj = OBJECT(qemu_get_cpu(0, NULL));
has_el3 = object_property_find(cpuobj, "has_el3") &&
object_property_get_bool(cpuobj, "has_el3", &error_abort);
qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
@@ -90,7 +90,7 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
* appropriate GIC PPI inputs
*/
for (i = 0; i < s->num_cpu; i++) {
- DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
+ DeviceState *cpudev = DEVICE(qemu_get_cpu(i, NULL));
int ppibase = s->num_irq - 32 + i * 32;
int irq;
/* Mapping from the output timer irq lines from the CPU to the
This is another case where what we want is "the Nth CPU
associated with this peripheral block", not the Nth CPU of
some particular architecture. (It's not as easy to figure
out where we would get that from as it is in the fsl-imx7
case, though -- perhaps we would need to tweak the API
these objects have somehow to pass in pointers to the CPUs?)
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 2ebf880ead..cdf21dfc11 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -392,7 +392,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
s->cpu = g_new0(GICv3CPUState, s->num_cpu);
for (i = 0; i < s->num_cpu; i++) {
- CPUState *cpu = qemu_get_cpu(i);
+ CPUState *cpu = qemu_get_cpu(i, NULL);
uint64_t cpu_affid;
s->cpu[i].cpu = cpu;
These gicv3 uses of qemu_get_cpu() are because instead of doing
the theoretical Right Thing and having the GIC object have to
be told which CPUs it is responsible for, we took a shortcut
and said "there's only one GIC, and it's connected to all the CPUs".
The fix is, again, not filtering by CPU type, but having the
board and SoC models do the work to explicitly represent
"this GIC object is attached to these CPU objects" (via link
properties or otherwise).
So overall there are some places where figuring out the right
replacement for qemu_get_cpu() is tricky, and some places where
it's probably fairly straightforward but just an annoying
amount of extra code to write, and some places where we don't
care because we know the board model is not heterogenous.
But I don't think "filter by CPU architecture type" is usually
going to be what we want.