From nobody Tue Nov 4 23:55:37 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1531589414116248.25377975864308; Sat, 14 Jul 2018 10:30:14 -0700 (PDT) Received: from localhost ([::1]:42139 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1feON3-0007xk-4W for importer@patchew.org; Sat, 14 Jul 2018 13:30:13 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38430) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1feO9u-0005nJ-Cg for qemu-devel@nongnu.org; Sat, 14 Jul 2018 13:16:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1feO9p-0004ZW-9z for qemu-devel@nongnu.org; Sat, 14 Jul 2018 13:16:36 -0400 Received: from greensocs.com ([193.104.36.180]:57315) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1feO9j-0004QV-FW; Sat, 14 Jul 2018 13:16:27 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id 2AA7A388FC7; Sat, 14 Jul 2018 19:16:25 +0200 (CEST) Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id WHKlFjokaTHh; Sat, 14 Jul 2018 19:16:24 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id 08A60C7AF9; Sat, 14 Jul 2018 19:16:23 +0200 (CEST) Received: from localhost.localdomain (unknown [105.98.38.216]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: luc.michel@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id 380EDC7ADD; Sat, 14 Jul 2018 19:16:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1531588585; bh=mj0E0fGdjtwxaKm72+hIt1Ta3Is13HKiu08Sv8mBdX0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=aSonkLPVvhfmmIBhIXUpyupL7iuOWNPWMQL1hSpJmVjnRF7p0UKqUYDiavr21R0AL kOGOgG23RU5x5UzU0K5wYY6mGe1iYmtgmPqUU6AHWxw6C/m/u4AgExxdS6Sad2Ggbn dRZ5CfpEGfN2xtEaW+xvZt3G9bdhAbmgqRPYSWn4= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=WvmDr/4f; dkim=pass (1024-bit key) header.d=greensocs.com header.b=pSkVRANX DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1531588584; bh=mj0E0fGdjtwxaKm72+hIt1Ta3Is13HKiu08Sv8mBdX0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=WvmDr/4fEr6lsWQqhg2MOF8TJT0fYDvOpSlWDkp68FzREaueWDq4AUIaiFPHBjArN w+uprJjQ7KJxH0DUdOCiO6Y8l20fBvCOA3AAWXSlbdXQqrT6qwbmAVMmdaAGliaeo2 N26n637EGR36l3p+j/4NgLC1Vr1VocdKs6E+X9/8= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1531588583; bh=mj0E0fGdjtwxaKm72+hIt1Ta3Is13HKiu08Sv8mBdX0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=pSkVRANXxPgN9r4RnsN8S9z4Z+vikdbIHM5/4gRFdMYA/ihdX1HpX0a+YR63Hzm05 E0qxMEMnieOFI7dUkWC+XUmwwTJqocSyPAb30FPNueHVKw8JriUC987dJkNdNM5RLU /5arTWWfALcfdMvS/Xbtr/mWggfkQYYGo17C8skI= From: Luc Michel To: qemu-devel@nongnu.org Date: Sat, 14 Jul 2018 19:15:50 +0200 Message-Id: <20180714171601.5734-10-luc.michel@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180714171601.5734-1-luc.michel@greensocs.com> References: <20180714171601.5734-1-luc.michel@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 09/20] intc/arm_gic: Add virtualization enabled IRQ helper functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , mark.burton@greensocs.com, saipava@xilinx.com, edgari@xilinx.com, qemu-arm@nongnu.org, Jan Kiszka , Luc Michel Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (found 3 invalid signatures) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add some helper functions to gic_internal.h to get or change the state of an IRQ. When the current CPU is not a vCPU, the call is forwarded to the GIC distributor. Otherwise, it acts on the list register matching the IRQ in the current CPU virtual interface. gic_clear_active can have a side effect on the distributor, even in the vCPU case, when the correponding LR has the HW field set. Use those functions in the CPU interface code path to prepare for the vCPU interface implementation. Signed-off-by: Luc Michel Reviewed-by: Peter Maydell --- hw/intc/arm_gic.c | 32 +++++++--------- hw/intc/gic_internal.h | 83 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 18 deletions(-) diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 53cc257ed8..ad241d12c2 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -222,7 +222,8 @@ static uint16_t gic_get_current_pending_irq(GICState *s= , int cpu, uint16_t pending_irq =3D s->current_pending[cpu]; =20 if (pending_irq < GIC_MAXIRQ && gic_has_groups(s)) { - int group =3D GIC_DIST_TEST_GROUP(pending_irq, (1 << cpu)); + int group =3D gic_test_group(s, pending_irq, cpu); + /* On a GIC without the security extensions, reading this register * behaves in the same way as a secure access to a GIC with them. */ @@ -253,7 +254,7 @@ static int gic_get_group_priority(GICState *s, int cpu,= int irq) =20 if (gic_has_groups(s) && !(s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) && - GIC_DIST_TEST_GROUP(irq, (1 << cpu))) { + gic_test_group(s, irq, cpu)) { bpr =3D s->abpr[cpu] - 1; assert(bpr >=3D 0); } else { @@ -266,7 +267,7 @@ static int gic_get_group_priority(GICState *s, int cpu,= int irq) */ mask =3D ~0U << ((bpr & 7) + 1); =20 - return GIC_DIST_GET_PRIORITY(irq, cpu) & mask; + return gic_get_priority(s, irq, cpu) & mask; } =20 static void gic_activate_irq(GICState *s, int cpu, int irq) @@ -279,14 +280,14 @@ static void gic_activate_irq(GICState *s, int cpu, in= t irq) int regno =3D preemption_level / 32; int bitno =3D preemption_level % 32; =20 - if (gic_has_groups(s) && GIC_DIST_TEST_GROUP(irq, (1 << cpu))) { + if (gic_has_groups(s) && gic_test_group(s, irq, cpu)) { s->nsapr[regno][cpu] |=3D (1 << bitno); } else { s->apr[regno][cpu] |=3D (1 << bitno); } =20 s->running_priority[cpu] =3D prio; - GIC_DIST_SET_ACTIVE(irq, 1 << cpu); + gic_set_active(s, irq, cpu); } =20 static int gic_get_prio_from_apr_bits(GICState *s, int cpu) @@ -355,7 +356,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemT= xAttrs attrs) return irq; } =20 - if (GIC_DIST_GET_PRIORITY(irq, cpu) >=3D s->running_priority[cpu]) { + if (gic_get_priority(s, irq, cpu) >=3D s->running_priority[cpu]) { DPRINTF("ACK, pending interrupt (%d) has insufficient priority\n",= irq); return 1023; } @@ -364,8 +365,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemT= xAttrs attrs) /* Clear pending flags for both level and edge triggered interrupt= s. * Level triggered IRQs will be reasserted once they become inacti= ve. */ - GIC_DIST_CLEAR_PENDING(irq, GIC_DIST_TEST_MODEL(irq) ? ALL_CPU_MASK - : cm); + gic_clear_pending(s, irq, cpu); ret =3D irq; } else { if (irq < GIC_NR_SGIS) { @@ -377,9 +377,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemT= xAttrs attrs) src =3D ctz32(s->sgi_pending[irq][cpu]); s->sgi_pending[irq][cpu] &=3D ~(1 << src); if (s->sgi_pending[irq][cpu] =3D=3D 0) { - GIC_DIST_CLEAR_PENDING(irq, - GIC_DIST_TEST_MODEL(irq) ? ALL_CPU_= MASK - : cm); + gic_clear_pending(s, irq, cpu); } ret =3D irq | ((src & 0x7) << 10); } else { @@ -387,8 +385,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemT= xAttrs attrs) * interrupts. (level triggered interrupts with an active line * remain pending, see gic_test_pending) */ - GIC_DIST_CLEAR_PENDING(irq, GIC_DIST_TEST_MODEL(irq) ? ALL_CPU= _MASK - : cm); + gic_clear_pending(s, irq, cpu); ret =3D irq; } } @@ -544,8 +541,7 @@ static bool gic_eoi_split(GICState *s, int cpu, MemTxAt= trs attrs) =20 static void gic_deactivate_irq(GICState *s, int cpu, int irq, MemTxAttrs a= ttrs) { - int cm =3D 1 << cpu; - int group =3D gic_has_groups(s) && GIC_DIST_TEST_GROUP(irq, cm); + int group =3D gic_has_groups(s) && gic_test_group(s, irq, cpu); =20 if (!gic_eoi_split(s, cpu, attrs)) { /* This is UNPREDICTABLE; we choose to ignore it */ @@ -559,7 +555,7 @@ static void gic_deactivate_irq(GICState *s, int cpu, in= t irq, MemTxAttrs attrs) return; } =20 - GIC_DIST_CLEAR_ACTIVE(irq, cm); + gic_clear_active(s, irq, cpu); } =20 static void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs att= rs) @@ -594,7 +590,7 @@ static void gic_complete_irq(GICState *s, int cpu, int = irq, MemTxAttrs attrs) } } =20 - group =3D gic_has_groups(s) && GIC_DIST_TEST_GROUP(irq, cm); + group =3D gic_has_groups(s) && gic_test_group(s, irq, cpu); =20 if (gic_cpu_ns_access(s, cpu, attrs) && !group) { DPRINTF("Non-secure EOI for Group0 interrupt %d ignored\n", irq); @@ -610,7 +606,7 @@ static void gic_complete_irq(GICState *s, int cpu, int = irq, MemTxAttrs attrs) =20 /* In GICv2 the guest can choose to split priority-drop and deactivate= */ if (!gic_eoi_split(s, cpu, attrs)) { - GIC_DIST_CLEAR_ACTIVE(irq, cm); + gic_clear_active(s, irq, cpu); } gic_update(s); } diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h index 56e203aeb9..d772d621fd 100644 --- a/hw/intc/gic_internal.h +++ b/hw/intc/gic_internal.h @@ -143,6 +143,13 @@ REG32(GICH_LR63, 0x1fc) #define GICH_LR_GROUP(entry) (FIELD_EX32(entry, GICH_LR0, Grp1)) #define GICH_LR_HW(entry) (FIELD_EX32(entry, GICH_LR0, HW)) =20 +#define GICH_LR_CLEAR_PENDING(entry) \ + ((entry) &=3D ~(GICH_LR_STATE_PENDING << R_GICH_LR0_State_SHIFT)) +#define GICH_LR_SET_ACTIVE(entry) \ + ((entry) |=3D (GICH_LR_STATE_ACTIVE << R_GICH_LR0_State_SHIFT)) +#define GICH_LR_CLEAR_ACTIVE(entry) \ + ((entry) &=3D ~(GICH_LR_STATE_ACTIVE << R_GICH_LR0_State_SHIFT)) + /* Valid bits for GICC_CTLR for GICv1, v1 with security extensions, * GICv2 and GICv2 with security extensions: */ @@ -239,4 +246,80 @@ static inline uint32_t *gic_get_lr_entry(GICState *s, = int irq, int vcpu) return NULL; } =20 +static inline bool gic_test_group(GICState *s, int irq, int cpu) +{ + if (gic_is_vcpu(cpu)) { + uint32_t *entry =3D gic_get_lr_entry(s, irq, cpu); + return GICH_LR_GROUP(*entry); + } else { + return GIC_DIST_TEST_GROUP(irq, 1 << cpu); + } +} + +static inline void gic_clear_pending(GICState *s, int irq, int cpu) +{ + if (gic_is_vcpu(cpu)) { + uint32_t *entry =3D gic_get_lr_entry(s, irq, cpu); + GICH_LR_CLEAR_PENDING(*entry); + } else { + /* Clear pending state for both level and edge triggered + * interrupts. (level triggered interrupts with an active line + * remain pending, see gic_test_pending) + */ + GIC_DIST_CLEAR_PENDING(irq, GIC_DIST_TEST_MODEL(irq) ? ALL_CPU_MASK + : (1 << cpu)); + } +} + +static inline void gic_set_active(GICState *s, int irq, int cpu) +{ + if (gic_is_vcpu(cpu)) { + uint32_t *entry =3D gic_get_lr_entry(s, irq, cpu); + GICH_LR_SET_ACTIVE(*entry); + } else { + GIC_DIST_SET_ACTIVE(irq, 1 << cpu); + } +} + +static inline void gic_clear_active(GICState *s, int irq, int cpu) +{ + if (gic_is_vcpu(cpu)) { + uint32_t *entry =3D gic_get_lr_entry(s, irq, cpu); + GICH_LR_CLEAR_ACTIVE(*entry); + + if (GICH_LR_HW(*entry)) { + /* Hardware interrupt. We must forward the deactivation reques= t to + * the distributor. + */ + int phys_irq =3D GICH_LR_PHYS_ID(*entry); + int rcpu =3D gic_get_vcpu_real_id(cpu); + + if (phys_irq < GIC_NR_SGIS || phys_irq >=3D GIC_MAXIRQ) { + /* UNPREDICTABLE behaviour, we choose to ignore the reques= t */ + return; + } + + /* This is equivalent to a NS write to DIR on the physical CPU + * interface. Hence group0 interrupt deactivation is ignored if + * the GIC is secure. + */ + if (!s->security_extn || GIC_DIST_TEST_GROUP(phys_irq, 1 << rc= pu)) { + GIC_DIST_CLEAR_ACTIVE(phys_irq, 1 << rcpu); + } + } + } else { + GIC_DIST_CLEAR_ACTIVE(irq, 1 << cpu); + } +} + +static inline int gic_get_priority(GICState *s, int irq, int cpu) +{ + if (gic_is_vcpu(cpu)) { + uint32_t *entry =3D gic_get_lr_entry(s, irq, cpu); + return GICH_LR_PRIORITY(*entry); + } else { + return GIC_DIST_GET_PRIORITY(irq, cpu); + } +} + #endif /* QEMU_ARM_GIC_INTERNAL_H */ --=20 2.18.0