qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Salil Mehta <salil.mehta@huawei.com>
To: <qemu-devel@nongnu.org>, <qemu-arm@nongnu.org>
Cc: peter.maydell@linaro.org, drjones@redhat.com,
	sudeep.holla@arm.com, gshan@redhat.com, mst@redhat.com,
	jiakernel2@gmail.com, maz@kernel.org, zhukeqian1@huawei.com,
	david@redhat.com, richard.henderson@linaro.org,
	linuxarm@huawei.com, eric.auger@redhat.com, james.morse@arm.com,
	catalin.marinas@arm.com, imammedo@redhat.com,
	Salil Mehta <salil.mehta@huawei.com>,
	pbonzini@redhat.com, mehta.salil.lnk@gmail.com,
	maran.wilson@oracle.com, will@kernel.org,
	wangxiongfeng2@huawei.com
Subject: [PATCH RFC 06/22] arm/cpuhp: Changes to pre-size GIC with possible vcpus @machine init
Date: Sat, 13 Jun 2020 22:36:13 +0100	[thread overview]
Message-ID: <20200613213629.21984-7-salil.mehta@huawei.com> (raw)
In-Reply-To: <20200613213629.21984-1-salil.mehta@huawei.com>

GIC needs to be pre-sized with possible vcpus at the initialization time. This
is necessary because Memory regions and resources associated with GICC/GICR
etc cannot be changed (add/del/modified) after VM has inited. Also, GIC_TYPER
needs to be initialized with mp_affinity and cpu interface number association.
This cannot be changed after GIC has initialized.

Once all the cpu interfaces of the GIC has been inited it needs to be ensured
that any updations to the GICC during reset only takes place for the present
vcpus and not the disabled ones. Therefore, proper checks are required at
various places.

Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
 hw/arm/virt.c              | 18 +++++++++---------
 hw/intc/arm_gicv3_common.c |  8 ++++++--
 hw/intc/arm_gicv3_cpuif.c  |  6 ++++++
 hw/intc/arm_gicv3_kvm.c    | 29 ++++++++++++++++++++++++++---
 include/hw/arm/virt.h      |  2 +-
 5 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 8040473d30..9e55b20685 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -628,19 +628,19 @@ static void create_v2m(VirtMachineState *vms)
 
 static void create_gic(VirtMachineState *vms)
 {
-    MachineState *ms = MACHINE(vms);
     /* We create a standalone GIC */
     SysBusDevice *gicbusdev;
     const char *gictype;
     int type = vms->gic_version, i;
-    unsigned int smp_cpus = ms->smp.cpus;
+    unsigned int max_cpus = vms->max_cpus;
+    unsigned int smp_cpus = vms->smp_cpus;
     uint32_t nb_redist_regions = 0;
 
     gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
 
     vms->gic = qdev_create(NULL, gictype);
     qdev_prop_set_uint32(vms->gic, "revision", type);
-    qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(vms->gic, "num-cpu", max_cpus);
     /* Note that the num-irq property counts both internal and external
      * interrupts; there are always 32 of the former (mandated by GIC spec).
      */
@@ -652,7 +652,7 @@ static void create_gic(VirtMachineState *vms)
     if (type == 3) {
         uint32_t redist0_capacity =
                     vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
-        uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
+        uint32_t redist0_count = MIN(max_cpus, redist0_capacity);
 
         nb_redist_regions = virt_gicv3_redist_region_count(vms);
 
@@ -665,7 +665,7 @@ static void create_gic(VirtMachineState *vms)
                     vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
 
             qdev_prop_set_uint32(vms->gic, "redist-region-count[1]",
-                MIN(smp_cpus - redist0_count, redist1_capacity));
+                MIN(max_cpus - redist0_count, redist1_capacity));
         }
     } else {
         if (!kvm_irqchip_in_kernel()) {
@@ -722,7 +722,7 @@ static void create_gic(VirtMachineState *vms)
         } else if (vms->virt) {
             qemu_irq irq = qdev_get_gpio_in(vms->gic,
                                             ppibase + ARCH_GIC_MAINT_IRQ);
-            sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
+            sysbus_connect_irq(gicbusdev, i + 4 * max_cpus, irq);
         }
 
         qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
@@ -730,11 +730,11 @@ static void create_gic(VirtMachineState *vms)
                                                      + VIRTUAL_PMU_IRQ));
 
         sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
-        sysbus_connect_irq(gicbusdev, i + smp_cpus,
+        sysbus_connect_irq(gicbusdev, i + max_cpus,
                            qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
-        sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus,
+        sysbus_connect_irq(gicbusdev, i + 2 * max_cpus,
                            qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
-        sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
+        sysbus_connect_irq(gicbusdev, i + 3 * max_cpus,
                            qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
     }
 
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 58ef65f589..bfa514444a 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -348,11 +348,15 @@ 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_possible_cpu(i);
         uint64_t cpu_affid;
         int last;
 
-        s->cpu[i].cpu = cpu;
+        if (qemu_present_cpu(cpu))
+            s->cpu[i].cpu = cpu;
+        else
+            s->cpu[i].cpu = NULL;
+
         s->cpu[i].gic = s;
         /* Store GICv3CPUState in CPUARMState gicv3state pointer */
         gicv3_set_gicv3state(cpu, &s->cpu[i]);
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 08e000e33c..90d8b0118e 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -779,6 +779,9 @@ void gicv3_cpuif_update(GICv3CPUState *cs)
     ARMCPU *cpu = ARM_CPU(cs->cpu);
     CPUARMState *env = &cpu->env;
 
+    if (!qemu_present_cpu(cs->cpu))
+        return;
+
     g_assert(qemu_mutex_iothread_locked());
 
     trace_gicv3_cpuif_update(gicv3_redist_affid(cs), cs->hppi.irq,
@@ -1654,6 +1657,9 @@ static void icc_generate_sgi(CPUARMState *env, GICv3CPUState *cs,
     for (i = 0; i < s->num_cpu; i++) {
         GICv3CPUState *ocs = &s->cpu[i];
 
+        if (!qemu_present_cpu(ocs->cpu))
+            continue;
+
         if (irm) {
             /* IRM == 1 : route to all CPUs except self */
             if (cs == ocs) {
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index ca43bf87ca..7fe000e53c 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -25,6 +25,7 @@
 #include "hw/sysbus.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "sysemu/cpus.h"
 #include "sysemu/kvm.h"
 #include "sysemu/runstate.h"
 #include "kvm_arm.h"
@@ -458,6 +459,17 @@ static void kvm_arm_gicv3_put(GICv3State *s)
         GICv3CPUState *c = &s->cpu[ncpu];
         int num_pri_bits;
 
+        /*
+         * To support hotplug of vcpus we need to make sure all gic cpuif/GICC
+         * are initialized at machvirt init time. Once the init is done we
+         * release the ARMCPU object for disabled vcpus but this leg could hit
+         * during reset of GICC later as well i.e. after init has happened and
+         * all of the cases we want to make sure we dont acess the GICC for
+         * the disabled VCPUs.
+         */
+        if (!qemu_present_cpu(c->cpu))
+            continue;
+
         kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, true);
         kvm_gicc_access(s, ICC_CTLR_EL1, ncpu,
                         &c->icc_ctlr_el1[GICV3_NS], true);
@@ -677,10 +689,21 @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
         return;
     }
 
+    /*
+     * This shall be called even when vcpu is being hotplugged and other vcpus
+     * might be running. Host kernel KVM code to handle device access of IOCTLs
+     * KVM_{GET|SET}_DEVICE_ATTR might fail due to inability to grab vcpu locks
+     * for all the vcpus. Hence, we need to pause all vcpus to facilitate
+     * locking within host.
+     */
+    if (!qemu_present_cpu(c->cpu))
+        pause_all_vcpus();
     /* Initialize to actual HW supported configuration */
     kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
                       KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer),
                       &c->icc_ctlr_el1[GICV3_NS], false, &error_abort);
+    if (!qemu_present_cpu(c->cpu))
+        resume_all_vcpus();
 
     c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
 }
@@ -788,9 +811,9 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
     }
 
     for (i = 0; i < s->num_cpu; i++) {
-        ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
-
-        define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
+        CPUState *cs = qemu_get_cpu(i);
+        if (qemu_present_cpu(cs))
+            define_arm_cp_regs(ARM_CPU(cs), gicv3_cpuif_reginfo);
     }
 
     /* Try to create the device via the device control API */
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 5b8ba64ec2..38a9cad168 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -178,7 +178,7 @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
 
     assert(vms->gic_version == VIRT_GIC_VERSION_3);
 
-    return vms->smp_cpus > redist0_capacity ? 2 : 1;
+    return vms->max_cpus > redist0_capacity ? 2 : 1;
 }
 
 #endif /* QEMU_ARM_VIRT_H */
-- 
2.17.1




  parent reply	other threads:[~2020-06-13 21:49 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-13 21:36 [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 01/22] arm/cpuhp: Add QMP vcpu params validation support Salil Mehta
2020-06-23  8:46   ` Andrew Jones
2020-06-23  9:40     ` Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 02/22] arm/cpuhp: Add new ARMCPU core-id property Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 03/22] arm/cpuhp: Add common cpu utility for possible vcpus Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 04/22] arm/cpuhp: Machine init time change common to vcpu {cold|hot}-plug Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 05/22] arm/cpuhp: Pre-create disabled possible vcpus @machine init Salil Mehta
2020-06-13 21:36 ` Salil Mehta [this message]
2020-06-13 21:36 ` [PATCH RFC 07/22] arm/cpuhp: Init PMU at host for all possible vcpus Salil Mehta
2020-06-23  9:00   ` Andrew Jones
2020-06-23  9:52     ` Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 08/22] arm/cpuhp: Enable ACPI support for vcpu hotplug Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 09/22] arm/cpuhp: Init GED framework with cpu hotplug events Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 10/22] arm/cpuhp: Update CPUs AML with cpu-(ctrl)dev change Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 11/22] arm/cpuhp: Update GED _EVT method AML with cpu scan Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 12/22] arm/cpuhp: MADT Tbl change to size the guest with possible vcpus Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 13/22] arm/cpuhp: Add ACPI _MAT entry for Processor object Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 14/22] arm/cpuhp: Release objects for *disabled* possible vcpus after init Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 15/22] arm/cpuhp: Update ACPI GED framework to support vcpu hotplug Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 16/22] arm/cpuhp: Add/update basic hot-(un)plug framework Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 17/22] arm/cpuhp: Changes to (un)wire GICC<->VCPU IRQs during hot-(un)plug Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 18/22] arm/cpuhp: Changes to update GIC with vcpu hot-plug notification Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 19/22] arm/cpuhp: Changes required to (re)init the vcpu register info Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 20/22] arm/cpuhp: Update the guest(via GED) about cpu hot-(un)plug events Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 21/22] arm/cpuhp: Changes required for reset and to support next boot Salil Mehta
2020-06-13 21:36 ` [PATCH RFC 22/22] arm/cpuhp: Add support of *unrealize* ARMCPU during vcpu hot-unplug Salil Mehta
2020-06-13 22:24 ` [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch no-reply
2020-06-13 22:26 ` no-reply
2020-06-14 11:54 ` Marc Zyngier
2020-06-15 10:19   ` Salil Mehta
2020-06-23  9:12 ` Andrew Jones
2020-06-23  9:56   ` Salil Mehta

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200613213629.21984-7-salil.mehta@huawei.com \
    --to=salil.mehta@huawei.com \
    --cc=catalin.marinas@arm.com \
    --cc=david@redhat.com \
    --cc=drjones@redhat.com \
    --cc=eric.auger@redhat.com \
    --cc=gshan@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=james.morse@arm.com \
    --cc=jiakernel2@gmail.com \
    --cc=linuxarm@huawei.com \
    --cc=maran.wilson@oracle.com \
    --cc=maz@kernel.org \
    --cc=mehta.salil.lnk@gmail.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=sudeep.holla@arm.com \
    --cc=wangxiongfeng2@huawei.com \
    --cc=will@kernel.org \
    --cc=zhukeqian1@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).