From nobody Thu Nov 14 18:11:41 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1712478234; cv=none; d=zohomail.com; s=zohoarc; b=biv9L+BeOKYBpu13gn+HwDXjGwc5jAJNUD2Ygj0PW8kk7Cp6r/z17El5AlnJKImN2RHKIk0QELgwwpmA6M5z3EmwrfNAEyGz2Pt7IezmXgN8fUosArOKy2ql4DJA4fidDaOx1/0fHOogAZkKy+GJMlHCNkboP7YnQEpMkoDmW64= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1712478234; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=th89uhOPGlQo25ab5yGEAGxL63ZU2H4yQbBJyaCwByI=; b=FyXibGmgosKK5+mZZjvrlvnfTaIj4YX+Zjelqy3wcDkL4s/f/sqifMaFAyiW5J4M4OQjdP86tqsWg+Jf3UqvLhYK9ix3TdcxAU4YaSlOI+MCnu88VcSACIFbQs4YS+fvXZremGANK8nwcQ72ZV5mZZttkhVsfjkNcgN/GaF44B0= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1712478234196695.3077261731529; Sun, 7 Apr 2024 01:23:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rtNlL-0004XW-Qv; Sun, 07 Apr 2024 04:20:27 -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 1rtNlA-0004Kl-HH; Sun, 07 Apr 2024 04:20:19 -0400 Received: from szxga07-in.huawei.com ([45.249.212.35]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rtNl2-0002Gp-W7; Sun, 07 Apr 2024 04:20:15 -0400 Received: from mail.maildlp.com (unknown [172.19.88.234]) by szxga07-in.huawei.com (SkyGuard) with ESMTP id 4VC4p348jyz1RBZN; Sun, 7 Apr 2024 16:17:15 +0800 (CST) Received: from kwepemi500008.china.huawei.com (unknown [7.221.188.139]) by mail.maildlp.com (Postfix) with ESMTPS id 152BE140119; Sun, 7 Apr 2024 16:20:05 +0800 (CST) Received: from huawei.com (10.67.174.55) by kwepemi500008.china.huawei.com (7.221.188.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.35; Sun, 7 Apr 2024 16:20:04 +0800 To: , , , , , , , CC: Subject: [PATCH v13 19/24] hw/intc/arm_gicv3: Handle icv_nmiar1_read() for icc_nmiar1_read() Date: Sun, 7 Apr 2024 08:17:28 +0000 Message-ID: <20240407081733.3231820-20-ruanjinjie@huawei.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240407081733.3231820-1-ruanjinjie@huawei.com> References: <20240407081733.3231820-1-ruanjinjie@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.67.174.55] X-ClientProxiedBy: dggems704-chm.china.huawei.com (10.3.19.181) To kwepemi500008.china.huawei.com (7.221.188.139) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=45.249.212.35; envelope-from=ruanjinjie@huawei.com; helo=szxga07-in.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_H4=0.001, RCVD_IN_MSPIKE_WL=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: Jinjie Ruan From: Jinjie Ruan via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1712478236464100003 Content-Type: text/plain; charset="utf-8" Implement icv_nmiar1_read() for icc_nmiar1_read(), so add definition for ICH_LR_EL2.NMI and ICH_AP1R_EL2.NMI bit. If FEAT_GICv3_NMI is supported, ich_ap_write() should consider ICV_AP1R_EL1= .NMI bit. In icv_activate_irq() and icv_eoir_write(), the ICV_AP1R_EL1.NMI bit should be set or clear according to the Non-maskable property. And the RPR priority should also update the NMI bit according to the APR priority NMI b= it. By the way, add gicv3_icv_nmiar1_read trace event. If the hpp irq is a NMI, the icv iar read should return 1022 and trap for NMI again Signed-off-by: Jinjie Ruan Reviewed-by: Richard Henderson Reviewed-by: Peter Maydell --- v13: - Enforce RES0 bit in NMI field when FEAT_GICv3_NMI is not implemented for ICH_LR_EL2. - Add Reviewed-by. v12: - When NMI is 1, the virtual interrupt's priority is 0x0. - Make the thisnmi logic more concisely in hppvi_index(). - Use is_nmi to simplify the code and check is_nmi before comparing vpmr. - Remove redundant nmi_support check in ich_highest_active_virt_prio(), hppvi_index(), icv_hppi_can_preempt(), icv_rpr_read() and icv_activate_ir= q(). - Also check sctlrx.NMI in icv_iar_read(). - Check icv_hppi_can_preempt() for icv_nmiar1_read(). - Check ICH_LR_EL2.NMI after check icv_hppi_can_preempt() as icv_iar_read() do it in icv_nmiar1_read(). - Fix the comment style in icv_nmiar1_read(). - Correct thisnmi to bool in icv_eoir_write(). - Check thisnmi and nmi both true instead of identical in icv_eoir_write(). v11: - Deal with NMI in the callers instead of ich_highest_active_virt_prio(). - Set either NMI or a group-priority bit, not both. - Only set AP NMI bits in the 0 reg. - Handle NMI in hppvi_index(), icv_hppi_can_preempt() and icv_eoir_write(). v10: - Rename ICH_AP1R_EL2_NMI to ICV_AP1R_EL1_NMI. - Add ICV_RPR_EL1_NMI definition. - Set ICV_RPR_EL1.NMI according to the ICV_AP1R_EL1.NMI in ich_highest_active_virt_prio(). v9: - Correct the INTID_NMI logic. v8: - Fix an unexpected interrupt bug when sending VNMI by running qemu VM. v7: - Add Reviewed-by. v6: - Implement icv_nmiar1_read(). --- hw/intc/arm_gicv3_cpuif.c | 105 +++++++++++++++++++++++++++++++++----- hw/intc/gicv3_internal.h | 4 ++ hw/intc/trace-events | 1 + 3 files changed, 98 insertions(+), 12 deletions(-) diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index a5a1ef93ca..dff88c4283 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -157,6 +157,10 @@ static int ich_highest_active_virt_prio(GICv3CPUState = *cs) int i; int aprmax =3D ich_num_aprs(cs); =20 + if (cs->ich_apr[GICV3_G1NS][0] & ICV_AP1R_EL1_NMI) { + return 0x0; + } + for (i =3D 0; i < aprmax; i++) { uint32_t apr =3D cs->ich_apr[GICV3_G0][i] | cs->ich_apr[GICV3_G1NS][i]; @@ -191,6 +195,7 @@ static int hppvi_index(GICv3CPUState *cs) * correct behaviour. */ int prio =3D 0xff; + bool nmi =3D false; =20 if (!(cs->ich_vmcr_el2 & (ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1))) { /* Both groups disabled, definitely nothing to do */ @@ -199,6 +204,7 @@ static int hppvi_index(GICv3CPUState *cs) =20 for (i =3D 0; i < cs->num_list_regs; i++) { uint64_t lr =3D cs->ich_lr_el2[i]; + bool thisnmi; int thisprio; =20 if (ich_lr_state(lr) !=3D ICH_LR_EL2_STATE_PENDING) { @@ -217,10 +223,12 @@ static int hppvi_index(GICv3CPUState *cs) } } =20 + thisnmi =3D lr & ICH_LR_EL2_NMI; thisprio =3D ich_lr_prio(lr); =20 - if (thisprio < prio) { + if ((thisprio < prio) || ((thisprio =3D=3D prio) && (thisnmi & (!n= mi)))) { prio =3D thisprio; + nmi =3D thisnmi; idx =3D i; } } @@ -289,6 +297,7 @@ static bool icv_hppi_can_preempt(GICv3CPUState *cs, uin= t64_t lr) * equivalent of these checks. */ int grp; + bool is_nmi; uint32_t mask, prio, rprio, vpmr; =20 if (!(cs->ich_hcr_el2 & ICH_HCR_EL2_EN)) { @@ -301,10 +310,11 @@ static bool icv_hppi_can_preempt(GICv3CPUState *cs, u= int64_t lr) */ =20 prio =3D ich_lr_prio(lr); + is_nmi =3D lr & ICH_LR_EL2_NMI; vpmr =3D extract64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VPMR_SHIFT, ICH_VMCR_EL2_VPMR_LENGTH); =20 - if (prio >=3D vpmr) { + if (!is_nmi && prio >=3D vpmr) { /* Priority mask masks this interrupt */ return false; } @@ -326,6 +336,11 @@ static bool icv_hppi_can_preempt(GICv3CPUState *cs, ui= nt64_t lr) return true; } =20 + if ((prio & mask) =3D=3D (rprio & mask) && is_nmi && + !(cs->ich_apr[GICV3_G1NS][0] & ICV_AP1R_EL1_NMI)) { + return true; + } + return false; } =20 @@ -550,7 +565,11 @@ static void icv_ap_write(CPUARMState *env, const ARMCP= RegInfo *ri, =20 trace_gicv3_icv_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), v= alue); =20 - cs->ich_apr[grp][regno] =3D value & 0xFFFFFFFFU; + if (cs->gic->nmi_support) { + cs->ich_apr[grp][regno] =3D value & (0xFFFFFFFFU | ICV_AP1R_EL1_NM= I); + } else { + cs->ich_apr[grp][regno] =3D value & 0xFFFFFFFFU; + } =20 gicv3_cpuif_virt_irq_fiq_update(cs); return; @@ -697,7 +716,11 @@ static void icv_ctlr_write(CPUARMState *env, const ARM= CPRegInfo *ri, static uint64_t icv_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri) { GICv3CPUState *cs =3D icc_cs_from_env(env); - int prio =3D ich_highest_active_virt_prio(cs); + uint64_t prio =3D ich_highest_active_virt_prio(cs); + + if (cs->ich_apr[GICV3_G1NS][0] & ICV_AP1R_EL1_NMI) { + prio |=3D ICV_RPR_EL1_NMI; + } =20 trace_gicv3_icv_rpr_read(gicv3_redist_affid(cs), prio); return prio; @@ -736,13 +759,19 @@ static void icv_activate_irq(GICv3CPUState *cs, int i= dx, int grp) */ uint32_t mask =3D icv_gprio_mask(cs, grp); int prio =3D ich_lr_prio(cs->ich_lr_el2[idx]) & mask; + bool nmi =3D cs->ich_lr_el2[idx] & ICH_LR_EL2_NMI; int aprbit =3D prio >> (8 - cs->vprebits); int regno =3D aprbit / 32; int regbit =3D aprbit % 32; =20 cs->ich_lr_el2[idx] &=3D ~ICH_LR_EL2_STATE_PENDING_BIT; cs->ich_lr_el2[idx] |=3D ICH_LR_EL2_STATE_ACTIVE_BIT; - cs->ich_apr[grp][regno] |=3D (1 << regbit); + + if (nmi) { + cs->ich_apr[grp][regno] |=3D ICV_AP1R_EL1_NMI; + } else { + cs->ich_apr[grp][regno] |=3D (1 << regbit); + } } =20 static void icv_activate_vlpi(GICv3CPUState *cs) @@ -763,6 +792,7 @@ static uint64_t icv_iar_read(CPUARMState *env, const AR= MCPRegInfo *ri) int grp =3D ri->crm =3D=3D 8 ? GICV3_G0 : GICV3_G1NS; int idx =3D hppvi_index(cs); uint64_t intid =3D INTID_SPURIOUS; + int el =3D arm_current_el(env); =20 if (idx =3D=3D HPPVI_INDEX_VLPI) { if (cs->hppvlpi.grp =3D=3D grp && icv_hppvlpi_can_preempt(cs)) { @@ -772,11 +802,16 @@ static uint64_t icv_iar_read(CPUARMState *env, const = ARMCPRegInfo *ri) } else if (idx >=3D 0) { uint64_t lr =3D cs->ich_lr_el2[idx]; int thisgrp =3D (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0; + bool nmi =3D env->cp15.sctlr_el[el] & SCTLR_NMI && lr & ICH_LR_EL2= _NMI; =20 if (thisgrp =3D=3D grp && icv_hppi_can_preempt(cs, lr)) { intid =3D ich_lr_vintid(lr); if (!gicv3_intid_is_special(intid)) { - icv_activate_irq(cs, idx, grp); + if (!nmi) { + icv_activate_irq(cs, idx, grp); + } else { + intid =3D INTID_NMI; + } } else { /* Interrupt goes from Pending to Invalid */ cs->ich_lr_el2[idx] &=3D ~ICH_LR_EL2_STATE_PENDING_BIT; @@ -797,8 +832,37 @@ static uint64_t icv_iar_read(CPUARMState *env, const A= RMCPRegInfo *ri) =20 static uint64_t icv_nmiar1_read(CPUARMState *env, const ARMCPRegInfo *ri) { - /* todo */ + GICv3CPUState *cs =3D icc_cs_from_env(env); + int idx =3D hppvi_index(cs); uint64_t intid =3D INTID_SPURIOUS; + + if (idx >=3D 0 && idx !=3D HPPVI_INDEX_VLPI) { + uint64_t lr =3D cs->ich_lr_el2[idx]; + int thisgrp =3D (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0; + + if ((thisgrp =3D=3D GICV3_G1NS) && icv_hppi_can_preempt(cs, lr)) { + intid =3D ich_lr_vintid(lr); + if (!gicv3_intid_is_special(intid)) { + if (lr & ICH_LR_EL2_NMI) { + icv_activate_irq(cs, idx, GICV3_G1NS); + } else { + intid =3D INTID_SPURIOUS; + } + } else { + /* Interrupt goes from Pending to Invalid */ + cs->ich_lr_el2[idx] &=3D ~ICH_LR_EL2_STATE_PENDING_BIT; + /* + * We will now return the (bogus) ID from the list registe= r, + * as per the pseudocode. + */ + } + } + } + + trace_gicv3_icv_nmiar1_read(gicv3_redist_affid(cs), intid); + + gicv3_cpuif_virt_update(cs); + return intid; } =20 @@ -1423,7 +1487,7 @@ static void icv_increment_eoicount(GICv3CPUState *cs) ICH_HCR_EL2_EOICOUNT_LENGTH, eoicount + 1); } =20 -static int icv_drop_prio(GICv3CPUState *cs) +static int icv_drop_prio(GICv3CPUState *cs, bool *nmi) { /* Drop the priority of the currently active virtual interrupt * (favouring group 0 if there is a set active bit at @@ -1445,6 +1509,12 @@ static int icv_drop_prio(GICv3CPUState *cs) continue; } =20 + if (i =3D=3D 0 && cs->gic->nmi_support && (*papr1 & ICV_AP1R_EL1_N= MI)) { + *papr1 &=3D (~ICV_AP1R_EL1_NMI); + *nmi =3D true; + return 0xff; + } + /* We can't just use the bit-twiddling hack icc_drop_prio() does * because we need to return the bit number we cleared so * it can be compared against the list register's priority field. @@ -1504,6 +1574,7 @@ static void icv_eoir_write(CPUARMState *env, const AR= MCPRegInfo *ri, int irq =3D value & 0xffffff; int grp =3D ri->crm =3D=3D 8 ? GICV3_G0 : GICV3_G1NS; int idx, dropprio; + bool nmi =3D false; =20 trace_gicv3_icv_eoir_write(ri->crm =3D=3D 8 ? 0 : 1, gicv3_redist_affid(cs), value); @@ -1516,8 +1587,8 @@ static void icv_eoir_write(CPUARMState *env, const AR= MCPRegInfo *ri, * error checks" (because that lets us avoid scanning the AP * registers twice). */ - dropprio =3D icv_drop_prio(cs); - if (dropprio =3D=3D 0xff) { + dropprio =3D icv_drop_prio(cs, &nmi); + if (dropprio =3D=3D 0xff && !nmi) { /* No active interrupt. It is CONSTRAINED UNPREDICTABLE * whether the list registers are checked in this * situation; we choose not to. @@ -1539,8 +1610,9 @@ static void icv_eoir_write(CPUARMState *env, const AR= MCPRegInfo *ri, uint64_t lr =3D cs->ich_lr_el2[idx]; int thisgrp =3D (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0; int lr_gprio =3D ich_lr_prio(lr) & icv_gprio_mask(cs, grp); + bool thisnmi =3D lr & ICH_LR_EL2_NMI; =20 - if (thisgrp =3D=3D grp && lr_gprio =3D=3D dropprio) { + if (thisgrp =3D=3D grp && (lr_gprio =3D=3D dropprio || (thisnmi & = nmi))) { if (!icv_eoi_split(env, cs) || irq >=3D GICV3_LPI_INTID_START)= { /* * Priority drop and deactivate not split: deactivate irq = now. @@ -2626,7 +2698,11 @@ static void ich_ap_write(CPUARMState *env, const ARM= CPRegInfo *ri, =20 trace_gicv3_ich_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), v= alue); =20 - cs->ich_apr[grp][regno] =3D value & 0xFFFFFFFFU; + if (cs->gic->nmi_support) { + cs->ich_apr[grp][regno] =3D value & (0xFFFFFFFFU | ICV_AP1R_EL1_NM= I); + } else { + cs->ich_apr[grp][regno] =3D value & 0xFFFFFFFFU; + } gicv3_cpuif_virt_irq_fiq_update(cs); } =20 @@ -2743,6 +2819,11 @@ static void ich_lr_write(CPUARMState *env, const ARM= CPRegInfo *ri, 8 - cs->vpribits, 0); } =20 + /* Enforce RES0 bit in NMI field when FEAT_GICv3_NMI is not implemente= d */ + if (!cs->gic->nmi_support) { + value &=3D ~ICH_LR_EL2_NMI; + } + cs->ich_lr_el2[regno] =3D value; gicv3_cpuif_virt_update(cs); } diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 81200eb90e..bc9f518fe8 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -246,6 +246,7 @@ FIELD(GICR_VPENDBASER, VALID, 63, 1) #define ICH_LR_EL2_PRIORITY_SHIFT 48 #define ICH_LR_EL2_PRIORITY_LENGTH 8 #define ICH_LR_EL2_PRIORITY_MASK (0xffULL << ICH_LR_EL2_PRIORITY_SHIFT) +#define ICH_LR_EL2_NMI (1ULL << 59) #define ICH_LR_EL2_GROUP (1ULL << 60) #define ICH_LR_EL2_HW (1ULL << 61) #define ICH_LR_EL2_STATE_SHIFT 62 @@ -277,6 +278,9 @@ FIELD(GICR_VPENDBASER, VALID, 63, 1) #define ICH_VTR_EL2_PREBITS_SHIFT 26 #define ICH_VTR_EL2_PRIBITS_SHIFT 29 =20 +#define ICV_AP1R_EL1_NMI (1ULL << 63) +#define ICV_RPR_EL1_NMI (1ULL << 63) + /* ITS Registers */ =20 FIELD(GITS_BASER, SIZE, 0, 8) diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 94030550d5..47340b5bc1 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -152,6 +152,7 @@ gicv3_icv_rpr_read(uint32_t cpu, uint64_t val) "GICv3 I= CV_RPR read cpu 0x%x valu gicv3_icv_hppir_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_HPPIR= %d read cpu 0x%x value 0x%" PRIx64 gicv3_icv_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICV_DIR write cpu 0= x%x value 0x%" PRIx64 gicv3_icv_iar_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IAR%d r= ead cpu 0x%x value 0x%" PRIx64 +gicv3_icv_nmiar1_read(uint32_t cpu, uint64_t val) "GICv3 ICV_NMIAR1 read c= pu 0x%x value 0x%" PRIx64 gicv3_icv_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_EOIR%= d write cpu 0x%x value 0x%" PRIx64 gicv3_cpuif_virt_update(uint32_t cpuid, int idx, int hppvlpi, int grp, int= prio) "GICv3 CPU i/f 0x%x virt HPPI update LR index %d HPPVLPI %d grp %d p= rio %d" gicv3_cpuif_virt_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel) "GIC= v3 CPU i/f 0x%x virt HPPI update: setting FIQ %d IRQ %d" --=20 2.34.1