[tip: irq/urgent] irqchip/gic-v5: Preserve ICC_CR0_EL1 state

From: tip-bot2 for Sascha Bischoff

Date: Mon Sep 07 2026 - 15:50:27 EST


The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: 1017911fcc03584b6854b1b8f0aafeb25f5a8d25
Gitweb: https://git.kernel.org/tip/1017911fcc03584b6854b1b8f0aafeb25f5a8d25
Author: Sascha Bischoff <Sascha.Bischoff@xxxxxxx>
AuthorDate: Mon, 07 Sep 2026 16:49:50
Committer: Thomas Gleixner <tglx@xxxxxxxxxx>
CommitterDate: Mon, 07 Sep 2026 21:44:17 +02:00

irqchip/gic-v5: Preserve ICC_CR0_EL1 state

In addition to EN, ICC_CR0_EL1 contains other fields, such as LINK and
LINK_IDLE. The driver only needs to modify EN, and must preserve the
values of all other fields when enabling or disabling the CPU
interface.

Define the missing LINK and LINK_IDLE fields, and use read-modify-write
accesses to update EN without affecting the rest of ICC_CR0_EL1.

Fixes: 7ec80fb3f025 ("irqchip/gic-v5: Add GICv5 PPI support")
Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Signed-off-by: Sascha Bischoff <sascha.bischoff@xxxxxxx>
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxx>
Reviewed-by: Marc Zyngier <maz@xxxxxxxxxx>
Link: https://patch.msgid.link/20260907164945.714545-1-sascha.bischoff@xxxxxxx
Closes: https://lore.kernel.org/r/20260807121703.D4B7A1F00A3A@xxxxxxxxxxxxxxx
---
arch/arm64/tools/sysreg | 4 +++-
drivers/irqchip/irq-gic-v5.c | 6 ++++--
2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 94bf065..e2d37ee 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -3761,7 +3761,9 @@ Sysreg ICC_CR0_EL1 3 1 12 0 1
Res0 63:39
Field 38 PID
Field 37:32 IPPT
-Res0 31:1
+Res0 31:3
+Field 2 LINK_IDLE
+Field 1 LINK
Field 0 EN
EndSysreg

diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c
index ac2d423..5f2551c 100644
--- a/drivers/irqchip/irq-gic-v5.c
+++ b/drivers/irqchip/irq-gic-v5.c
@@ -974,7 +974,8 @@ static void gicv5_cpu_disable_interrupts(void)
{
u64 cr0;

- cr0 = FIELD_PREP(ICC_CR0_EL1_EN, 0);
+ cr0 = read_sysreg_s(SYS_ICC_CR0_EL1);
+ cr0 &= ~ICC_CR0_EL1_EN_MASK;
write_sysreg_s(cr0, SYS_ICC_CR0_EL1);
isb();
}
@@ -991,7 +992,8 @@ static void gicv5_cpu_enable_interrupts(void)
pcr = FIELD_PREP(ICC_PCR_EL1_PRIORITY, GICV5_IRQ_PRI_MI);
write_sysreg_s(pcr, SYS_ICC_PCR_EL1);

- cr0 = FIELD_PREP(ICC_CR0_EL1_EN, 1);
+ cr0 = read_sysreg_s(SYS_ICC_CR0_EL1);
+ cr0 |= ICC_CR0_EL1_EN_MASK;
write_sysreg_s(cr0, SYS_ICC_CR0_EL1);
}