1af325e87SSascha Bischoff // SPDX-License-Identifier: GPL-2.0-only 2af325e87SSascha Bischoff /* 3af325e87SSascha Bischoff * Copyright (C) 2025, 2026 - Arm Ltd 4af325e87SSascha Bischoff */ 5af325e87SSascha Bischoff 6af325e87SSascha Bischoff #include <linux/irqchip/arm-gic-v5.h> 7af325e87SSascha Bischoff 8af325e87SSascha Bischoff #include <asm/kvm_hyp.h> 9af325e87SSascha Bischoff 10af325e87SSascha Bischoff void __vgic_v5_save_apr(struct vgic_v5_cpu_if *cpu_if) 11af325e87SSascha Bischoff { 12af325e87SSascha Bischoff cpu_if->vgic_apr = read_sysreg_s(SYS_ICH_APR_EL2); 13af325e87SSascha Bischoff } 14af325e87SSascha Bischoff 15af325e87SSascha Bischoff static void __vgic_v5_compat_mode_disable(void) 16af325e87SSascha Bischoff { 17af325e87SSascha Bischoff sysreg_clear_set_s(SYS_ICH_VCTLR_EL2, ICH_VCTLR_EL2_V3, 0); 18af325e87SSascha Bischoff isb(); 19af325e87SSascha Bischoff } 20af325e87SSascha Bischoff 21af325e87SSascha Bischoff void __vgic_v5_restore_vmcr_apr(struct vgic_v5_cpu_if *cpu_if) 22af325e87SSascha Bischoff { 23af325e87SSascha Bischoff __vgic_v5_compat_mode_disable(); 24af325e87SSascha Bischoff 25af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_vmcr, SYS_ICH_VMCR_EL2); 26af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_apr, SYS_ICH_APR_EL2); 27af325e87SSascha Bischoff } 28af325e87SSascha Bischoff 29af325e87SSascha Bischoff void __vgic_v5_save_ppi_state(struct vgic_v5_cpu_if *cpu_if) 30af325e87SSascha Bischoff { 31af325e87SSascha Bischoff /* 32af325e87SSascha Bischoff * The following code assumes that the bitmap storage that we have for 33af325e87SSascha Bischoff * PPIs is either 64 (architected PPIs, only) or 128 bits (architected & 34af325e87SSascha Bischoff * impdef PPIs). 35af325e87SSascha Bischoff */ 36af325e87SSascha Bischoff BUILD_BUG_ON(VGIC_V5_NR_PRIVATE_IRQS % 64); 37af325e87SSascha Bischoff 38af325e87SSascha Bischoff bitmap_write(host_data_ptr(vgic_v5_ppi_state)->activer_exit, 39af325e87SSascha Bischoff read_sysreg_s(SYS_ICH_PPI_ACTIVER0_EL2), 0, 64); 40*9c1ac77dSSascha Bischoff bitmap_write(host_data_ptr(vgic_v5_ppi_state)->pendr, 41af325e87SSascha Bischoff read_sysreg_s(SYS_ICH_PPI_PENDR0_EL2), 0, 64); 42af325e87SSascha Bischoff 43af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[0] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR0_EL2); 44af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[1] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR1_EL2); 45af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[2] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR2_EL2); 46af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[3] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR3_EL2); 47af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[4] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR4_EL2); 48af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[5] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR5_EL2); 49af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[6] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR6_EL2); 50af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[7] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR7_EL2); 51af325e87SSascha Bischoff 52af325e87SSascha Bischoff if (VGIC_V5_NR_PRIVATE_IRQS == 128) { 53af325e87SSascha Bischoff bitmap_write(host_data_ptr(vgic_v5_ppi_state)->activer_exit, 54af325e87SSascha Bischoff read_sysreg_s(SYS_ICH_PPI_ACTIVER1_EL2), 64, 64); 55*9c1ac77dSSascha Bischoff bitmap_write(host_data_ptr(vgic_v5_ppi_state)->pendr, 56af325e87SSascha Bischoff read_sysreg_s(SYS_ICH_PPI_PENDR1_EL2), 64, 64); 57af325e87SSascha Bischoff 58af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[8] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR8_EL2); 59af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[9] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR9_EL2); 60af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[10] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR10_EL2); 61af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[11] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR11_EL2); 62af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[12] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR12_EL2); 63af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[13] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR13_EL2); 64af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[14] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR14_EL2); 65af325e87SSascha Bischoff cpu_if->vgic_ppi_priorityr[15] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR15_EL2); 66af325e87SSascha Bischoff } 67af325e87SSascha Bischoff 68af325e87SSascha Bischoff /* Now that we are done, disable DVI */ 69af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_DVIR0_EL2); 70af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_DVIR1_EL2); 71af325e87SSascha Bischoff } 72af325e87SSascha Bischoff 73af325e87SSascha Bischoff void __vgic_v5_restore_ppi_state(struct vgic_v5_cpu_if *cpu_if) 74af325e87SSascha Bischoff { 75af325e87SSascha Bischoff DECLARE_BITMAP(pendr, VGIC_V5_NR_PRIVATE_IRQS); 76af325e87SSascha Bischoff 77af325e87SSascha Bischoff /* We assume 64 or 128 PPIs - see above comment */ 78af325e87SSascha Bischoff BUILD_BUG_ON(VGIC_V5_NR_PRIVATE_IRQS % 64); 79af325e87SSascha Bischoff 80af325e87SSascha Bischoff /* Enable DVI so that the guest's interrupt config takes over */ 81af325e87SSascha Bischoff write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_dvir, 0, 64), 82af325e87SSascha Bischoff SYS_ICH_PPI_DVIR0_EL2); 83af325e87SSascha Bischoff 84af325e87SSascha Bischoff write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_activer, 0, 64), 85af325e87SSascha Bischoff SYS_ICH_PPI_ACTIVER0_EL2); 86af325e87SSascha Bischoff write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_enabler, 0, 64), 87af325e87SSascha Bischoff SYS_ICH_PPI_ENABLER0_EL2); 88af325e87SSascha Bischoff 89af325e87SSascha Bischoff /* Update the pending state of the NON-DVI'd PPIs, only */ 90*9c1ac77dSSascha Bischoff bitmap_andnot(pendr, host_data_ptr(vgic_v5_ppi_state)->pendr, 91af325e87SSascha Bischoff cpu_if->vgic_ppi_dvir, VGIC_V5_NR_PRIVATE_IRQS); 92af325e87SSascha Bischoff write_sysreg_s(bitmap_read(pendr, 0, 64), SYS_ICH_PPI_PENDR0_EL2); 93af325e87SSascha Bischoff 94af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[0], 95af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR0_EL2); 96af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[1], 97af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR1_EL2); 98af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[2], 99af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR2_EL2); 100af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[3], 101af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR3_EL2); 102af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[4], 103af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR4_EL2); 104af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[5], 105af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR5_EL2); 106af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[6], 107af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR6_EL2); 108af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[7], 109af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR7_EL2); 110af325e87SSascha Bischoff 111af325e87SSascha Bischoff if (VGIC_V5_NR_PRIVATE_IRQS == 128) { 112af325e87SSascha Bischoff /* Enable DVI so that the guest's interrupt config takes over */ 113af325e87SSascha Bischoff write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_dvir, 64, 64), 114af325e87SSascha Bischoff SYS_ICH_PPI_DVIR1_EL2); 115af325e87SSascha Bischoff 116af325e87SSascha Bischoff write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_activer, 64, 64), 117af325e87SSascha Bischoff SYS_ICH_PPI_ACTIVER1_EL2); 118af325e87SSascha Bischoff write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_enabler, 64, 64), 119af325e87SSascha Bischoff SYS_ICH_PPI_ENABLER1_EL2); 120af325e87SSascha Bischoff write_sysreg_s(bitmap_read(pendr, 64, 64), 121af325e87SSascha Bischoff SYS_ICH_PPI_PENDR1_EL2); 122af325e87SSascha Bischoff 123af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[8], 124af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR8_EL2); 125af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[9], 126af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR9_EL2); 127af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[10], 128af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR10_EL2); 129af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[11], 130af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR11_EL2); 131af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[12], 132af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR12_EL2); 133af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[13], 134af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR13_EL2); 135af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[14], 136af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR14_EL2); 137af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_ppi_priorityr[15], 138af325e87SSascha Bischoff SYS_ICH_PPI_PRIORITYR15_EL2); 139af325e87SSascha Bischoff } else { 140af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_DVIR1_EL2); 141af325e87SSascha Bischoff 142af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_ACTIVER1_EL2); 143af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_ENABLER1_EL2); 144af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_PENDR1_EL2); 145af325e87SSascha Bischoff 146af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR8_EL2); 147af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR9_EL2); 148af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR10_EL2); 149af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR11_EL2); 150af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR12_EL2); 151af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR13_EL2); 152af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR14_EL2); 153af325e87SSascha Bischoff write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR15_EL2); 154af325e87SSascha Bischoff } 155af325e87SSascha Bischoff } 156af325e87SSascha Bischoff 157af325e87SSascha Bischoff void __vgic_v5_save_state(struct vgic_v5_cpu_if *cpu_if) 158af325e87SSascha Bischoff { 159af325e87SSascha Bischoff cpu_if->vgic_vmcr = read_sysreg_s(SYS_ICH_VMCR_EL2); 160af325e87SSascha Bischoff cpu_if->vgic_icsr = read_sysreg_s(SYS_ICC_ICSR_EL1); 161af325e87SSascha Bischoff } 162af325e87SSascha Bischoff 163af325e87SSascha Bischoff void __vgic_v5_restore_state(struct vgic_v5_cpu_if *cpu_if) 164af325e87SSascha Bischoff { 165af325e87SSascha Bischoff write_sysreg_s(cpu_if->vgic_icsr, SYS_ICC_ICSR_EL1); 166af325e87SSascha Bischoff } 167