| /* |
| * SPDX-License-Identifier: BSD-3-Clause |
| * SPDX-FileCopyrightText: Copyright TF-RMM Contributors. |
| */ |
| |
| #ifndef GIC_H |
| #define GIC_H |
| |
| #include <stdbool.h> |
| #include <utils_def.h> |
| |
| /* The number of implemented List registers, minus one */ |
| #define ICH_VTR_EL2_LIST_REGS_SHIFT UL(0) |
| #define ICH_VTR_EL2_LIST_REGS_WIDTH UL(5) |
| #define ICH_VTR_EL2_LIST_REGS_MASK MASK(ICH_VTR_EL2_LIST_REGS) |
| |
| /* The number of virtual interrupt identifier bits supported */ |
| #define ICH_VTR_EL2_ID_BITS_SHIFT UL(23) |
| #define ICH_VTR_EL2_ID_BITS_WIDTH UL(3) |
| #define ICH_VTR_EL2_ID_BITS_MASK MASK(ICH_VTR_EL2_ID_BITS) |
| |
| /* The number of virtual preemption bits implemented, minus one */ |
| #define ICH_VTR_EL2_PRE_BITS_SHIFT UL(26) |
| #define ICH_VTR_EL2_PRE_BITS_WIDTH UL(3) |
| #define ICH_VTR_EL2_PRE_BITS_MASK MASK(ICH_VTR_EL2_PRE_BITS) |
| |
| /* The number of virtual priority bits implemented, minus one */ |
| #define ICH_VTR_EL2_PRI_BITS_SHIFT UL(29) |
| #define ICH_VTR_EL2_PRI_BITS_WIDTH UL(3) |
| #define ICH_VTR_EL2_PRI_BITS_MASK MASK(ICH_VTR_EL2_PRI_BITS) |
| |
| /* Global enable bit for the virtual CPU interface */ |
| #define ICH_HCR_EL2_EN_SHIFT UL(0) |
| #define ICH_HCR_EL2_EN_BIT INPLACE(ICH_HCR_EL2_EN, UL(1)) |
| |
| /* Underflow Interrupt Enable */ |
| #define ICH_HCR_EL2_UIE_SHIFT UL(1) |
| #define ICH_HCR_EL2_UIE_BIT INPLACE(ICH_HCR_EL2_UIE, UL(1)) |
| |
| /* List Register Entry Not Present Interrupt Enable */ |
| #define ICH_HCR_EL2_LRENPIE_SHIFT UL(2) |
| #define ICH_HCR_EL2_LRENPIE_BIT INPLACE(ICH_HCR_EL2_LRENPIE, UL(1)) |
| |
| /* No Pending Interrupt Enable */ |
| #define ICH_HCR_EL2_NPIE_SHIFT UL(3) |
| #define ICH_HCR_EL2_NPIE_BIT INPLACE(ICH_HCR_EL2_NPIE, UL(1)) |
| |
| /* VM Group 0 Enabled Interrupt Enable */ |
| #define ICH_HCR_EL2_VGRP0EIE_SHIFT UL(4) |
| #define ICH_HCR_EL2_VGRP0EIE_BIT INPLACE(ICH_HCR_EL2_VGRP0EIE, UL(1)) |
| |
| /* VM Group 0 Disabled Interrupt Enable */ |
| #define ICH_HCR_EL2_VGRP0DIE_SHIFT UL(5) |
| #define ICH_HCR_EL2_VGRP0DIE_BIT INPLACE(ICH_HCR_EL2_VGRP0DIE, UL(1)) |
| |
| /* VM Group 1 Enabled Interrupt Enable */ |
| #define ICH_HCR_EL2_VGRP1EIE_SHIFT UL(6) |
| #define ICH_HCR_EL2_VGRP1EIE_BIT INPLACE(ICH_HCR_EL2_VGRP1EIE, UL(1)) |
| |
| /* VM Group 1 Disabled Interrupt Enable */ |
| #define ICH_HCR_EL2_VGRP1DIE_SHIFT UL(7) |
| #define ICH_HCR_EL2_VGRP1DIE_BIT INPLACE(ICH_HCR_EL2_VGRP1DIE, UL(1)) |
| |
| /* |
| * When FEAT_GICv4p1 is implemented: |
| * Controls whether deactivation of virtual SGIs |
| * can increment ICH_HCR_EL2.EOIcount |
| */ |
| #define ICH_HCR_EL2_VSGIEEOICOUNT_SHIFT UL(8) |
| #define ICH_HCR_EL2_VSGIEEOICOUNT_BIT INPLACE(ICH_HCR_EL2_VSGIEEOICOUNT, UL(1)) |
| |
| /* |
| * Trap all EL1 accesses to System registers |
| * that are common to Group 0 and Group 1 to EL2 |
| */ |
| #define ICH_HCR_EL2_TC_SHIFT UL(10) |
| #define ICH_HCR_EL2_TC_BIT INPLACE(ICH_HCR_EL2_TC, UL(1)) |
| |
| /* |
| * Trap all EL1 accesses to ICC_* and ICV_* System registers |
| * for Group 0 interrupts to EL2 |
| */ |
| #define ICH_HCR_EL2_TALL0_SHIFT UL(11) |
| #define ICH_HCR_EL2_TALL0_BIT INPLACE(ICH_HCR_EL2_TALL0, UL(1)) |
| |
| /* |
| * Trap all EL1 accesses to ICC_* and ICV_* System registers |
| * for Group 1 interrupts to EL2 |
| */ |
| #define ICH_HCR_EL2_TALL1_SHIFT UL(12) |
| #define ICH_HCR_EL2_TALL1_BIT INPLACE(ICH_HCR_EL2_TALL1, UL(1)) |
| |
| /* Trap all locally generated SEIs */ |
| #define ICH_HCR_EL2_TSEI_SHIFT UL(13) |
| #define ICH_HCR_EL2_TSEI_BIT INPLACE(ICH_HCR_EL2_TSEI, UL(1)) |
| |
| /* |
| * When FEAT_GICv3_TDIR is implemented: |
| * Trap EL1 writes to ICC_DIR_EL1 and ICV_DIR_EL1 |
| */ |
| #define ICH_HCR_EL2_TDIR_SHIFT UL(14) |
| #define ICH_HCR_EL2_TDIR_BIT INPLACE(ICH_HCR_EL2_TDIR, UL(1)) |
| |
| /* |
| * When ICH_VTR_EL2.DVIM == 1: |
| * Directly-injected Virtual Interrupt Mask |
| */ |
| #define ICH_HCR_EL2_DVIM_SHIFT UL(15) |
| #define ICH_HCR_EL2_DVIM_BIT INPLACE(ICH_HCR_EL2_DVIM, UL(1)) |
| |
| #define ICH_HCR_EL2_EOI_COUNT_SHIFT UL(27) |
| #define ICH_HCR_EL2_EOI_COUNT_WIDTH UL(5) |
| #define ICH_HCR_EL2_EOI_COUNT_MASK MASK(ICH_HCR_EL2_EOI_COUNT) |
| |
| /* Virtual INTID of the interrupt */ |
| #define ICH_LR_VINTID_SHIFT UL(0) |
| #define ICH_LR_VINTID_WIDTH UL(32) |
| #define ICH_LR_VINTID_MASK MASK(ICH_LR_VINTID) |
| |
| /* |
| * Physical INTID, for hardware interrupts |
| * When ICH_LR<n>_EL2.HW is 0 (there is no corresponding physical interrupt), |
| * this field has the following meaning: |
| * Bits[44:42] : RES0. |
| * Bit[41] : EOI. If this bit is 1, then when the interrupt identified by |
| * vINTID is deactivated, a maintenance interrupt is asserted. |
| * Bits[40:32] : RES0 |
| */ |
| #define ICH_LR_PINTID_SHIFT UL(32) |
| #define ICH_LR_PINTID_WIDTH UL(13) |
| #define ICH_LR_PINTID_MASK MASK(ICH_LR_PINTID) |
| |
| #define ICH_LR_EOI_SHIFT UL(41) |
| #define ICH_LR_EOI_BIT INPLACE(ICH_LR_EOI, UL(1)) |
| |
| /* The priority of this interrupt */ |
| #define ICH_LR_PRIORITY_SHIFT UL(48) |
| #define ICH_LR_PRIORITY_WIDTH UL(8) |
| #define ICH_LR_PRIORITY_MASK MASK(ICH_LR_PRIORITY) |
| |
| /* The group for this virtual interrupt */ |
| #define ICH_LR_GROUP_SHIFT UL(60) |
| #define ICH_LR_GROUP_BIT INPLACE(ICH_LR_GROUP, UL(1)) |
| |
| /* |
| * Indicates whether this virtual interrupt |
| * maps directly to a hardware interrupt |
| */ |
| #define ICH_LR_HW_SHIFT UL(61) |
| #define ICH_LR_HW_BIT INPLACE(ICH_LR_HW, UL(1)) |
| |
| /* |
| * The state of the interrupt: |
| * 0b00 Invalid (Inactive) |
| * 0b01 Pending |
| * 0b10 Active |
| * 0b11 Pending and active |
| */ |
| #define ICH_LR_STATE_SHIFT UL(62) |
| #define ICH_LR_STATE_WIDTH UL(2) |
| #define ICH_LR_STATE_MASK MASK(ICH_LR_STATE) |
| |
| #define ICH_LR_STATE_INVALID INPLACE(ICH_LR_STATE, UL(0)) |
| #define ICH_LR_STATE_PENDING INPLACE(ICH_LR_STATE, UL(1)) |
| #define ICH_LR_STATE_ACTIVE INPLACE(ICH_LR_STATE, UL(2)) |
| #define ICH_LR_STATE_PENDING_ACTIVE INPLACE(ICH_LR_STATE, UL(3)) |
| |
| /* |
| * A `_ns` mask defines bits that can be set/cleared by the NS hypervisor. |
| */ |
| |
| #define ICH_HCR_EL2_NS_MASK \ |
| (ICH_HCR_EL2_UIE_BIT | \ |
| ICH_HCR_EL2_LRENPIE_BIT | \ |
| ICH_HCR_EL2_NPIE_BIT | \ |
| ICH_HCR_EL2_VGRP0EIE_BIT | \ |
| ICH_HCR_EL2_VGRP0DIE_BIT | \ |
| ICH_HCR_EL2_VGRP1EIE_BIT | \ |
| ICH_HCR_EL2_VGRP1DIE_BIT | \ |
| ICH_HCR_EL2_TDIR_BIT) |
| /* |
| * Maximum number of Interrupt Controller |
| * Hyp Active Priorities Group 0/1 Registers [0..3] |
| */ |
| #define ICH_MAX_APRS 4 |
| |
| /* Maximum number of Interrupt Controller List Registers */ |
| #define ICH_MAX_LRS 16 |
| |
| /******************************************************************************* |
| * GICv3 and 3.1 definitions |
| ******************************************************************************/ |
| #define MIN_SGI_ID U(0) |
| #define MIN_SEC_SGI_ID U(8) |
| |
| /* PPIs INTIDs 16-31 */ |
| #define MIN_PPI_ID U(16) |
| #define MAX_PPI_ID U(31) |
| |
| /* SPIs INTIDs 32-1019 */ |
| #define MIN_SPI_ID U(32) |
| #define MAX_SPI_ID U(1019) |
| |
| /* GICv3.1 extended PPIs INTIDs 1056-1119 */ |
| #define MIN_EPPI_ID U(1056) |
| #define MAX_EPPI_ID U(1119) |
| |
| /* GICv3.1 extended SPIs INTIDs 4096 - 5119 */ |
| #define MIN_ESPI_ID U(4096) |
| #define MAX_ESPI_ID U(5119) |
| |
| /* Constant to categorize LPI interrupt */ |
| #define MIN_LPI_ID U(8192) |
| |
| struct gic_cpu_state { |
| /* Interrupt Controller Hyp Active Priorities Group 0 Registers */ |
| unsigned long ich_ap0r_el2[ICH_MAX_APRS]; |
| /* Interrupt Controller Hyp Active Priorities Group 1 Registers */ |
| unsigned long ich_ap1r_el2[ICH_MAX_APRS]; |
| /* GICv3 Virtual Machine Control Register */ |
| unsigned long ich_vmcr_el2; /* RecRun out */ |
| /* Interrupt Controller Hyp Control Register */ |
| unsigned long ich_hcr_el2; /* RecRun in/out */ |
| |
| /* GICv3 List Registers */ |
| unsigned long ich_lr_el2[ICH_MAX_LRS]; /* RecRun in/out */ |
| /* GICv3 Maintenance Interrupt State Register */ |
| unsigned long ich_misr_el2; /* RecRun out */ |
| }; |
| |
| struct rmi_rec_entry; |
| struct rmi_rec_exit; |
| |
| void gic_get_virt_features(void); |
| void gic_cpu_state_init(struct gic_cpu_state *gicstate); |
| void gic_copy_state_from_ns(struct gic_cpu_state *gicstate, |
| struct rmi_rec_entry *rec_entry); |
| void gic_copy_state_to_ns(struct gic_cpu_state *gicstate, |
| struct rmi_rec_exit *rec_exit); |
| bool gic_validate_state(struct gic_cpu_state *gicstate); |
| void gic_restore_state(struct gic_cpu_state *gicstate); |
| void gic_save_state(struct gic_cpu_state *gicstate); |
| |
| #endif /* GIC_H */ |