From patchwork Wed Oct 9 03:17:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Salil Mehta X-Patchwork-Id: 13827473 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 43CC2CF0435 for ; Wed, 9 Oct 2024 03:22:25 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1syNHJ-0007yg-JH; Tue, 08 Oct 2024 23:22:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1syNHH-0007q6-Cj; Tue, 08 Oct 2024 23:22:19 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1syNHF-0004ZZ-F7; Tue, 08 Oct 2024 23:22:19 -0400 Received: from mail.maildlp.com (unknown [172.18.186.216]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4XNdPJ2htdz6LDBV; Wed, 9 Oct 2024 11:17:56 +0800 (CST) Received: from frapeml500007.china.huawei.com (unknown [7.182.85.172]) by mail.maildlp.com (Postfix) with ESMTPS id 188F8140447; Wed, 9 Oct 2024 11:22:15 +0800 (CST) Received: from 00293818-MRGF.huawei.com (10.126.173.89) by frapeml500007.china.huawei.com (7.182.85.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Wed, 9 Oct 2024 05:21:55 +0200 To: , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC V4 08/33] arm/virt, gicv3: Introduce GICv3 CPU Interface *accessibility* flag and checks Date: Wed, 9 Oct 2024 04:17:50 +0100 Message-ID: <20241009031815.250096-9-salil.mehta@huawei.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241009031815.250096-1-salil.mehta@huawei.com> References: <20241009031815.250096-1-salil.mehta@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.126.173.89] X-ClientProxiedBy: dggems705-chm.china.huawei.com (10.3.19.182) To frapeml500007.china.huawei.com (7.182.85.172) Received-SPF: pass client-ip=185.176.79.56; envelope-from=salil.mehta@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Salil Mehta X-Patchwork-Original-From: Salil Mehta via From: Salil Mehta Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Introduce a `gicc_accessible` flag to indicate whether it is safe to access the GICv3 CPU interface. This flag will determine the availability of the GICv3 CPU interface based on whether the associated QOM vCPUs are enabled or disabled. Additionally, implement checks throughout the GICv3 codebase to ensure that any updates or accesses to GICC registers (e.g., `ICC_*_EL1`) occur only when the `gicc_accessible` flag is set. This ensures that operations such as KVM VGIC GICC register fetches or modifications are performed only for GICv3 CPU interfaces that are valid and associated with active QOM vCPUs. Co-developed-by: Keqian Zhu Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta --- hw/intc/arm_gicv3_common.c | 9 ++++++-- hw/intc/arm_gicv3_cpuif.c | 8 +++++++ hw/intc/arm_gicv3_kvm.c | 23 ++++++++++++++++++- include/hw/intc/arm_gicv3_common.h | 36 ++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c index bd50a1b079..4f230257ef 100644 --- a/hw/intc/arm_gicv3_common.c +++ b/hw/intc/arm_gicv3_common.c @@ -436,10 +436,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; - s->cpu[i].cpu = cpu; + /* + * Accordingly, set the QOM `GICv3CPUState` as either accessible or + * inaccessible based on the `CPUState` of the associated QOM vCPU. + */ + gicv3_set_cpustate(&s->cpu[i], cpu, qemu_enabled_cpu(cpu)); + 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 bdb13b00e9..151f957d42 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -1052,6 +1052,10 @@ void gicv3_cpuif_update(GICv3CPUState *cs) ARMCPU *cpu = ARM_CPU(cs->cpu); CPUARMState *env = &cpu->env; + if (!gicv3_cpu_accessible(cs)) { + return; + } + g_assert(bql_locked()); trace_gicv3_cpuif_update(gicv3_redist_affid(cs), cs->hppi.irq, @@ -2036,6 +2040,10 @@ static void icc_generate_sgi(CPUARMState *env, GICv3CPUState *cs, for (i = 0; i < s->num_cpu; i++) { GICv3CPUState *ocs = &s->cpu[i]; + if (!gicv3_cpu_accessible(ocs)) { + 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 9ea6b8e218..7e741ace50 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -24,6 +24,7 @@ #include "hw/intc/arm_gicv3_common.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,16 @@ static void kvm_arm_gicv3_put(GICv3State *s) GICv3CPUState *c = &s->cpu[ncpu]; int num_pri_bits; + /* + * We must ensure that we do not attempt to access or update KVM GICC + * registers if their corresponding QOM `GICv3CPUState` is marked as + * 'inaccessible', either because their corresponding QOM vCPU objects + * do not exist or are disabled due to hot-unplug action. + */ + if (!gicv3_cpu_accessible(c)) { + 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); @@ -616,6 +627,14 @@ static void kvm_arm_gicv3_get(GICv3State *s) GICv3CPUState *c = &s->cpu[ncpu]; int num_pri_bits; + /* + * don't attempt to access KVM VGIC for the disabled vCPUs where + * GICv3CPUState is inaccessible. + */ + if (!gicv3_cpu_accessible(c)) { + continue; + } + kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, false); kvm_gicc_access(s, ICC_CTLR_EL1, ncpu, &c->icc_ctlr_el1[GICV3_NS], false); @@ -815,7 +834,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); + if (gicv3_cpu_accessible(&s->cpu[i])) { + define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); + } } /* Try to create the device via the device control API */ diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index cd09bee3bc..73d9088768 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -190,6 +190,7 @@ struct GICv3CPUState { uint64_t icc_apr[3][4]; uint64_t icc_igrpen[3]; uint64_t icc_ctlr_el3; + bool gicc_accessible; /* Virtualization control interface */ uint64_t ich_apr[3][4]; /* ich_apr[GICV3_G1][x] never used */ @@ -353,4 +354,39 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler, */ const char *gicv3_class_name(void); +/** + * gicv3_cpu_accessible + * + * The `GICv3CPUState` can become inaccessible if the associated `CPUState` is + * either unavailable or in a disabled state. This state is independent of the + * KVM VGIC and is not compliant with ARM CPU architecture (i.e. there is no + * way we can explicitly enable/disable ARM GIC CPU interface). This change + * is specific to QOM only. + * + * Returns: True if accessible otherwise False + */ +static inline bool gicv3_cpu_accessible(GICv3CPUState *gicc) +{ + assert(gicc); + return gicc->gicc_accessible; +} + +/** + * gicv3_set_cpustate + * + * Sets `GICv3CPUState` and the associated `CPUState` as accessible and + * available for use + */ +static inline void gicv3_set_cpustate(GICv3CPUState *s, + CPUState *cpu, + bool gicc_accessible) +{ + if (gicc_accessible) { + s->cpu = cpu; + s->gicc_accessible = true; + } else { + s->cpu = NULL; + s->gicc_accessible = false; + } +} #endif