qemu/hw-arm-virt-Simplify-by-moving-the-gic-in-the-machin.patch
Keqian Zhu 1c823f0431 arm/virt: Add ACPI CPU hotplug support
This series is an attempt to provide CPU hotplug support on ARM
virt platform. This is based on ACPI GED device.

We should enable ACPI support, and use vGICv3 and 64bit CPU to
support CPU hotplug.

Under KVM accel, the KVM vCPUs is pre-created. Besides, vGIC IRIs
is pre-created too. However, QEMU vCPU objects are defer-created.

Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
2020-06-01 09:13:39 +00:00

403 lines
15 KiB
Diff

From 5d1be90750551f1debf5767d7a6e2b9c50054c05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
Date: Mon, 9 Dec 2019 10:03:06 +0100
Subject: [PATCH] hw/arm/virt: Simplify by moving the gic in the machine state
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Make the gic a field in the machine state, and instead of filling
an array of qemu_irq and passing it around, directly call
qdev_get_gpio_in() on the gic field.
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20191209090306.20433-1-philmd@redhat.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/arm/virt.c | 109 +++++++++++++++++++++---------------------
include/hw/arm/virt.h | 1 +
2 files changed, 55 insertions(+), 55 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 18321e522b..8638aeedb7 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -634,7 +634,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
}
}
-static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic)
+static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
{
DeviceState *dev;
MachineState *ms = MACHINE(vms);
@@ -650,14 +650,14 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic)
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base);
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq));
qdev_init_nofail(dev);
return dev;
}
-static void create_its(VirtMachineState *vms, DeviceState *gicdev)
+static void create_its(VirtMachineState *vms)
{
const char *itsclass = its_class_name();
DeviceState *dev;
@@ -669,7 +669,7 @@ static void create_its(VirtMachineState *vms, DeviceState *gicdev)
dev = qdev_create(NULL, itsclass);
- object_property_set_link(OBJECT(dev), OBJECT(gicdev), "parent-gicv3",
+ object_property_set_link(OBJECT(dev), OBJECT(vms->gic), "parent-gicv3",
&error_abort);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_ITS].base);
@@ -677,7 +677,7 @@ static void create_its(VirtMachineState *vms, DeviceState *gicdev)
fdt_add_its_gic_node(vms);
}
-static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
+static void create_v2m(VirtMachineState *vms)
{
int i;
int irq = vms->irqmap[VIRT_GIC_V2M];
@@ -690,17 +690,17 @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
qdev_init_nofail(dev);
for (i = 0; i < NUM_GICV2M_SPIS; i++) {
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
+ qdev_get_gpio_in(vms->gic, irq + i));
}
fdt_add_v2m_gic_node(vms);
}
-static void create_gic(VirtMachineState *vms, qemu_irq *pic)
+static void create_gic(VirtMachineState *vms)
{
MachineState *ms = MACHINE(vms);
/* We create a standalone GIC */
- DeviceState *gicdev;
SysBusDevice *gicbusdev;
const char *gictype;
int type = vms->gic_version, i;
@@ -709,15 +709,15 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
- gicdev = qdev_create(NULL, gictype);
- qdev_prop_set_uint32(gicdev, "revision", type);
- qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus);
+ vms->gic = qdev_create(NULL, gictype);
+ qdev_prop_set_uint32(vms->gic, "revision", type);
+ qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
/* Note that the num-irq property counts both internal and external
* interrupts; there are always 32 of the former (mandated by GIC spec).
*/
- qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32);
+ qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32);
if (!kvm_irqchip_in_kernel()) {
- qdev_prop_set_bit(gicdev, "has-security-extensions", vms->secure);
+ qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
}
if (type == 3) {
@@ -727,25 +727,25 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
nb_redist_regions = virt_gicv3_redist_region_count(vms);
- qdev_prop_set_uint32(gicdev, "len-redist-region-count",
+ qdev_prop_set_uint32(vms->gic, "len-redist-region-count",
nb_redist_regions);
- qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count);
+ qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", redist0_count);
if (nb_redist_regions == 2) {
uint32_t redist1_capacity =
vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
- qdev_prop_set_uint32(gicdev, "redist-region-count[1]",
+ qdev_prop_set_uint32(vms->gic, "redist-region-count[1]",
MIN(smp_cpus - redist0_count, redist1_capacity));
}
} else {
if (!kvm_irqchip_in_kernel()) {
- qdev_prop_set_bit(gicdev, "has-virtualization-extensions",
+ qdev_prop_set_bit(vms->gic, "has-virtualization-extensions",
vms->virt);
}
}
- qdev_init_nofail(gicdev);
- gicbusdev = SYS_BUS_DEVICE(gicdev);
+ qdev_init_nofail(vms->gic);
+ gicbusdev = SYS_BUS_DEVICE(vms->gic);
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
if (type == 3) {
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
@@ -781,23 +781,23 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
qdev_connect_gpio_out(cpudev, irq,
- qdev_get_gpio_in(gicdev,
+ qdev_get_gpio_in(vms->gic,
ppibase + timer_irq[irq]));
}
if (type == 3) {
- qemu_irq irq = qdev_get_gpio_in(gicdev,
+ 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(gicdev,
+ qemu_irq irq = qdev_get_gpio_in(vms->gic,
ppibase + ARCH_GIC_MAINT_IRQ);
sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
}
qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
- qdev_get_gpio_in(gicdev, ppibase
+ qdev_get_gpio_in(vms->gic, ppibase
+ VIRTUAL_PMU_IRQ));
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
@@ -809,20 +809,16 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
}
- for (i = 0; i < NUM_IRQS; i++) {
- pic[i] = qdev_get_gpio_in(gicdev, i);
- }
-
fdt_add_gic_node(vms);
if (type == 3 && vms->its) {
- create_its(vms, gicdev);
+ create_its(vms);
} else if (type == 2) {
- create_v2m(vms, pic);
+ create_v2m(vms);
}
}
-static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart,
+static void create_uart(const VirtMachineState *vms, int uart,
MemoryRegion *mem, Chardev *chr)
{
char *nodename;
@@ -838,7 +834,7 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart,
qdev_init_nofail(dev);
memory_region_add_subregion(mem, base,
sysbus_mmio_get_region(s, 0));
- sysbus_connect_irq(s, 0, pic[irq]);
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
nodename = g_strdup_printf("/pl011@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename);
@@ -880,7 +876,7 @@ static void create_cpufreq(const VirtMachineState *vms, MemoryRegion *mem)
memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
}
-static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
+static void create_rtc(const VirtMachineState *vms)
{
char *nodename;
hwaddr base = vms->memmap[VIRT_RTC].base;
@@ -888,7 +884,7 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
int irq = vms->irqmap[VIRT_RTC];
const char compat[] = "arm,pl031\0arm,primecell";
- sysbus_create_simple("pl031", base, pic[irq]);
+ sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq));
nodename = g_strdup_printf("/pl031@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename);
@@ -916,7 +912,7 @@ static void virt_powerdown_req(Notifier *n, void *opaque)
}
}
-static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
+static void create_gpio(const VirtMachineState *vms)
{
char *nodename;
DeviceState *pl061_dev;
@@ -925,7 +921,8 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
int irq = vms->irqmap[VIRT_GPIO];
const char compat[] = "arm,pl061\0arm,primecell";
- pl061_dev = sysbus_create_simple("pl061", base, pic[irq]);
+ pl061_dev = sysbus_create_simple("pl061", base,
+ qdev_get_gpio_in(vms->gic, irq));
uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt);
nodename = g_strdup_printf("/pl061@%" PRIx64, base);
@@ -959,7 +956,7 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
g_free(nodename);
}
-static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic)
+static void create_virtio_devices(const VirtMachineState *vms)
{
int i;
hwaddr size = vms->memmap[VIRT_MMIO].size;
@@ -995,7 +992,8 @@ static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic)
int irq = vms->irqmap[VIRT_MMIO] + i;
hwaddr base = vms->memmap[VIRT_MMIO].base + i * size;
- sysbus_create_simple("virtio-mmio", base, pic[irq]);
+ sysbus_create_simple("virtio-mmio", base,
+ qdev_get_gpio_in(vms->gic, irq));
}
/* We add dtb nodes in reverse order so that they appear in the finished
@@ -1244,7 +1242,7 @@ static void create_pcie_irq_map(const VirtMachineState *vms,
0x7 /* PCI irq */);
}
-static void create_smmu(const VirtMachineState *vms, qemu_irq *pic,
+static void create_smmu(const VirtMachineState *vms,
PCIBus *bus)
{
char *node;
@@ -1267,7 +1265,8 @@ static void create_smmu(const VirtMachineState *vms, qemu_irq *pic,
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
for (i = 0; i < NUM_SMMU_IRQS; i++) {
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
+ qdev_get_gpio_in(vms->gic, irq + i));
}
node = g_strdup_printf("/smmuv3@%" PRIx64, base);
@@ -1294,7 +1293,7 @@ static void create_smmu(const VirtMachineState *vms, qemu_irq *pic,
g_free(node);
}
-static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
+static void create_pcie(VirtMachineState *vms)
{
hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size;
@@ -1354,7 +1353,8 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
for (i = 0; i < GPEX_NUM_IRQS; i++) {
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
+ qdev_get_gpio_in(vms->gic, irq + i));
gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
}
@@ -1414,7 +1414,7 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
if (vms->iommu) {
vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt);
- create_smmu(vms, pic, pci->bus);
+ create_smmu(vms, pci->bus);
qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map",
0x0, vms->iommu_phandle, 0x0, 0x10000);
@@ -1423,7 +1423,7 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
g_free(nodename);
}
-static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic)
+static void create_platform_bus(VirtMachineState *vms)
{
DeviceState *dev;
SysBusDevice *s;
@@ -1439,8 +1439,8 @@ static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic)
s = SYS_BUS_DEVICE(dev);
for (i = 0; i < PLATFORM_BUS_NUM_IRQS; i++) {
- int irqn = vms->irqmap[VIRT_PLATFORM_BUS] + i;
- sysbus_connect_irq(s, i, pic[irqn]);
+ int irq = vms->irqmap[VIRT_PLATFORM_BUS] + i;
+ sysbus_connect_irq(s, i, qdev_get_gpio_in(vms->gic, irq));
}
memory_region_add_subregion(sysmem,
@@ -1621,7 +1621,6 @@ static void machvirt_init(MachineState *machine)
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine);
MachineClass *mc = MACHINE_GET_CLASS(machine);
const CPUArchIdList *possible_cpus;
- qemu_irq pic[NUM_IRQS];
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *secure_sysmem = NULL;
int n, virt_max_cpus;
@@ -1829,29 +1828,29 @@ static void machvirt_init(MachineState *machine)
virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
- create_gic(vms, pic);
+ create_gic(vms);
fdt_add_pmu_nodes(vms);
- create_uart(vms, pic, VIRT_UART, sysmem, serial_hd(0));
+ create_uart(vms, VIRT_UART, sysmem, serial_hd(0));
create_cpufreq(vms, sysmem);
if (vms->secure) {
create_secure_ram(vms, secure_sysmem);
- create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
+ create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
}
vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64);
- create_rtc(vms, pic);
+ create_rtc(vms);
- create_pcie(vms, pic);
+ create_pcie(vms);
if (has_ged && aarch64 && firmware_loaded && acpi_enabled) {
- vms->acpi_dev = create_acpi_ged(vms, pic);
+ vms->acpi_dev = create_acpi_ged(vms);
} else {
- create_gpio(vms, pic);
+ create_gpio(vms);
}
/* connect powerdown request */
@@ -1862,12 +1861,12 @@ static void machvirt_init(MachineState *machine)
* (which will be automatically plugged in to the transports). If
* no backend is created the transport will just sit harmlessly idle.
*/
- create_virtio_devices(vms, pic);
+ create_virtio_devices(vms);
vms->fw_cfg = create_fw_cfg(vms, &address_space_memory);
rom_set_fw(vms->fw_cfg);
- create_platform_bus(vms, pic);
+ create_platform_bus(vms);
vms->bootinfo.ram_size = machine->ram_size;
vms->bootinfo.kernel_filename = machine->kernel_filename;
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index dcceb9c615..3dfefca93b 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -138,6 +138,7 @@ typedef struct {
uint32_t iommu_phandle;
int psci_conduit;
hwaddr highest_gpa;
+ DeviceState *gic;
DeviceState *acpi_dev;
Notifier powerdown_notifier;
} VirtMachineState;
--
2.19.1