[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH RFC 17/22] arm/cpuhp: Changes to (un)wire GICC<->VCPU IRQs during
From: |
Salil Mehta |
Subject: |
[PATCH RFC 17/22] arm/cpuhp: Changes to (un)wire GICC<->VCPU IRQs during hot-(un)plug |
Date: |
Sat, 13 Jun 2020 22:36:24 +0100 |
Refactors the existing gic create code to extract common code to wire the
vcpu<->gic interrupts. This function could be used with cold-plug case and also
used when vcpu is hot-plugged. It also introduces a new function to unwire the
vcpu>->gic interrupts for the vcpu hot-unplug cases.
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
hw/arm/virt.c | 144 +++++++++++++++++++++++++++++------------
hw/core/qdev.c | 2 +-
include/hw/qdev-core.h | 2 +
3 files changed, 104 insertions(+), 44 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ac2941159a..f0295e940e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -615,6 +615,103 @@ static void create_v2m(VirtMachineState *vms)
fdt_add_v2m_gic_node(vms);
}
+static void unwire_gic_cpu_irqs(VirtMachineState *vms, CPUState *cs)
+{
+ unsigned int max_cpus = vms->max_cpus;
+ DeviceState *cpudev = DEVICE(cs);
+ DeviceState *gicdev = vms->gic;
+ int cpu = CPU(cs)->cpu_index;
+ int type = vms->gic_version;
+ int irq;
+
+ /* Mapping from the output timer irq lines from the CPU to the
+ * GIC PPI inputs we use for the virt board.
+ */
+ const int timer_irq[] = {
+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
+ };
+
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
+ qdev_disconnect_gpio_out_named(cpudev, NULL, irq);
+ }
+
+ if (type == 3) {
+ qdev_disconnect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
0);
+ } else if (vms->virt) {
+ qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ, cpu + 4
* max_cpus);
+ }
+
+ /*
+ * RFC: Question: This currently does not takes care of intimating the
devices
+ * which might be sitting on system bus. Do we need a
sysbus_disconnect_irq()
+ * which also does the job of notification beside disconnection?
+ */
+ qdev_disconnect_gpio_out_named(cpudev, "pmu-interrupt", 0);
+ qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ, cpu);
+ qdev_disconnect_gpio_out_named(gicdev,
+ SYSBUS_DEVICE_GPIO_IRQ, cpu + max_cpus);
+ qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ,
+ cpu + 2 * max_cpus);
+ qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ,
+ cpu + 3 * max_cpus);
+}
+
+static void wire_gic_cpu_irqs(VirtMachineState *vms, CPUState *cs)
+{
+ unsigned int max_cpus = vms->max_cpus;
+ DeviceState *cpudev = DEVICE(cs);
+ DeviceState *gicdev = vms->gic;
+ int cpu = CPU(cs)->cpu_index;
+ int type = vms->gic_version;
+ SysBusDevice *gicbusdev;
+ int ppibase;
+ int irq;
+
+ ppibase = NUM_IRQS + cpu * GIC_INTERNAL + GIC_NR_SGIS;
+
+ /* Mapping from the output timer irq lines from the CPU to the
+ * GIC PPI inputs we use for the virt board.
+ */
+ const int timer_irq[] = {
+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
+ };
+
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
+ qdev_connect_gpio_out(cpudev, irq,
+ qdev_get_gpio_in(gicdev,
+ ppibase + timer_irq[irq]));
+ }
+
+ gicbusdev = SYS_BUS_DEVICE(gicdev);
+ if (type == 3) {
+ qemu_irq irq = qdev_get_gpio_in(gicdev,
+ ppibase + ARCH_GIC_MAINT_IRQ);
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
+ 0, irq);
+ } else if (vms->virt) {
+ qemu_irq irq = qdev_get_gpio_in(gicdev,
+ ppibase + ARCH_GIC_MAINT_IRQ);
+ sysbus_connect_irq(gicbusdev, cpu + 4 * max_cpus, irq);
+ }
+
+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
+ qdev_get_gpio_in(gicdev,
+ ppibase + VIRTUAL_PMU_IRQ));
+ sysbus_connect_irq(gicbusdev, cpu, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
+ sysbus_connect_irq(gicbusdev, cpu + max_cpus,
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
+ sysbus_connect_irq(gicbusdev, cpu + 2 * max_cpus,
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
+ sysbus_connect_irq(gicbusdev, cpu + 3 * max_cpus,
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
+}
+
static void create_gic(VirtMachineState *vms)
{
/* We create a standalone GIC */
@@ -684,47 +781,7 @@ static void create_gic(VirtMachineState *vms)
* and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
*/
for (i = 0; i < smp_cpus; i++) {
- DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
- int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
- int irq;
- /* Mapping from the output timer irq lines from the CPU to the
- * GIC PPI inputs we use for the virt board.
- */
- const int timer_irq[] = {
- [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
- [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
- [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
- [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
- };
-
- for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
- qdev_connect_gpio_out(cpudev, irq,
- qdev_get_gpio_in(vms->gic,
- ppibase + timer_irq[irq]));
- }
-
- if (type == 3) {
- qemu_irq irq = qdev_get_gpio_in(vms->gic,
- ppibase + ARCH_GIC_MAINT_IRQ);
- qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
- 0, irq);
- } else if (vms->virt) {
- qemu_irq irq = qdev_get_gpio_in(vms->gic,
- ppibase + ARCH_GIC_MAINT_IRQ);
- sysbus_connect_irq(gicbusdev, i + 4 * max_cpus, irq);
- }
-
- qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
- qdev_get_gpio_in(vms->gic, ppibase
- + VIRTUAL_PMU_IRQ));
-
- sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev,
ARM_CPU_IRQ));
- sysbus_connect_irq(gicbusdev, i + max_cpus,
- qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
- sysbus_connect_irq(gicbusdev, i + 2 * max_cpus,
- qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
- sysbus_connect_irq(gicbusdev, i + 3 * max_cpus,
- qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
+ wire_gic_cpu_irqs(vms, qemu_get_cpu(i));
}
fdt_add_gic_node(vms);
@@ -2382,6 +2439,7 @@ static void virt_cpu_pre_plug(HotplugHandler
*hotplug_dev, DeviceState *dev,
static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
MachineState *ms = MACHINE(hotplug_dev);
ARMCPU *cpu = ARM_CPU(dev);
CPUState *cs = CPU(dev);
@@ -2392,7 +2450,7 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
DeviceState *dev,
cpu_slot->cpu = OBJECT(dev);
if (dev->hotplugged) {
- /* TODO: wire the gic-cpu irqs */
+ wire_gic_cpu_irqs(vms, cs);
/* TODO: update acpi hotplug state and send cpu hotplug event to guest
*/
/* TODO: register this cpu for reset & update F/W info for the next
boot */
}
@@ -2447,7 +2505,7 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev,
DeviceState *dev,
/* TODO: update the acpi cpu hotplug state for cpu hot-unplug */
- /* TODO: unwire the gic-cpu irqs here */
+ unwire_gic_cpu_irqs(vms, cs);
/* TODO: update the GIC about this hot unplug change */
/* TODO: unregister this cpu for reset & update F/W info for the next boot
*/
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 9e5538aeae..65b3ec7c8f 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -563,7 +563,7 @@ qemu_irq qdev_get_gpio_out_connector(DeviceState *dev,
const char *name, int n)
/* disconnect a GPIO output, returning the disconnected input (if any) */
-static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
+qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
const char *name, int n)
{
char *propname = g_strdup_printf("%s[%d]",
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index b870b27966..8434cc5a3e 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -355,6 +355,8 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const
char *name, int n,
qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int
n);
qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
const char *name, int n);
+qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
+ const char *name, int n);
BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
--
2.17.1
- Re: [PATCH RFC 07/22] arm/cpuhp: Init PMU at host for all possible vcpus, (continued)
- [PATCH RFC 08/22] arm/cpuhp: Enable ACPI support for vcpu hotplug, Salil Mehta, 2020/06/13
- [PATCH RFC 09/22] arm/cpuhp: Init GED framework with cpu hotplug events, Salil Mehta, 2020/06/13
- [PATCH RFC 10/22] arm/cpuhp: Update CPUs AML with cpu-(ctrl)dev change, Salil Mehta, 2020/06/13
- [PATCH RFC 11/22] arm/cpuhp: Update GED _EVT method AML with cpu scan, Salil Mehta, 2020/06/13
- [PATCH RFC 12/22] arm/cpuhp: MADT Tbl change to size the guest with possible vcpus, Salil Mehta, 2020/06/13
- [PATCH RFC 13/22] arm/cpuhp: Add ACPI _MAT entry for Processor object, Salil Mehta, 2020/06/13
- [PATCH RFC 14/22] arm/cpuhp: Release objects for *disabled* possible vcpus after init, Salil Mehta, 2020/06/13
- [PATCH RFC 15/22] arm/cpuhp: Update ACPI GED framework to support vcpu hotplug, Salil Mehta, 2020/06/13
- [PATCH RFC 16/22] arm/cpuhp: Add/update basic hot-(un)plug framework, Salil Mehta, 2020/06/13
- [PATCH RFC 17/22] arm/cpuhp: Changes to (un)wire GICC<->VCPU IRQs during hot-(un)plug,
Salil Mehta <=
- [PATCH RFC 18/22] arm/cpuhp: Changes to update GIC with vcpu hot-plug notification, Salil Mehta, 2020/06/13
- [PATCH RFC 19/22] arm/cpuhp: Changes required to (re)init the vcpu register info, Salil Mehta, 2020/06/13
- [PATCH RFC 20/22] arm/cpuhp: Update the guest(via GED) about cpu hot-(un)plug events, Salil Mehta, 2020/06/13
- [PATCH RFC 21/22] arm/cpuhp: Changes required for reset and to support next boot, Salil Mehta, 2020/06/13
- [PATCH RFC 22/22] arm/cpuhp: Add support of *unrealize* ARMCPU during vcpu hot-unplug, Salil Mehta, 2020/06/13
- Re: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch, no-reply, 2020/06/13
- Re: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch, no-reply, 2020/06/13
- Re: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch, Marc Zyngier, 2020/06/14
- Re: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch, Andrew Jones, 2020/06/23