diff options
-rw-r--r-- | Documentation/arm64/booting.txt | 5 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 66 |
2 files changed, 64 insertions, 7 deletions
diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt index 8df9f4658d6f..fbab7e21d116 100644 --- a/Documentation/arm64/booting.txt +++ b/Documentation/arm64/booting.txt | |||
@@ -188,6 +188,11 @@ Before jumping into the kernel, the following conditions must be met: | |||
188 | the kernel image will be entered must be initialised by software at a | 188 | the kernel image will be entered must be initialised by software at a |
189 | higher exception level to prevent execution in an UNKNOWN state. | 189 | higher exception level to prevent execution in an UNKNOWN state. |
190 | 190 | ||
191 | - SCR_EL3.FIQ must have the same value across all CPUs the kernel is | ||
192 | executing on. | ||
193 | - The value of SCR_EL3.FIQ must be the same as the one present at boot | ||
194 | time whenever the kernel is executing. | ||
195 | |||
191 | For systems with a GICv3 interrupt controller to be used in v3 mode: | 196 | For systems with a GICv3 interrupt controller to be used in v3 mode: |
192 | - If EL3 is present: | 197 | - If EL3 is present: |
193 | ICC_SRE_EL3.Enable (bit 3) must be initialiased to 0b1. | 198 | ICC_SRE_EL3.Enable (bit 3) must be initialiased to 0b1. |
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 5a703ae09ce5..eb9d9486f90b 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
@@ -66,6 +66,31 @@ struct gic_chip_data { | |||
66 | static struct gic_chip_data gic_data __read_mostly; | 66 | static struct gic_chip_data gic_data __read_mostly; |
67 | static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key); | 67 | static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key); |
68 | 68 | ||
69 | /* | ||
70 | * The behaviours of RPR and PMR registers differ depending on the value of | ||
71 | * SCR_EL3.FIQ, and the behaviour of non-secure priority registers of the | ||
72 | * distributor and redistributors depends on whether security is enabled in the | ||
73 | * GIC. | ||
74 | * | ||
75 | * When security is enabled, non-secure priority values from the (re)distributor | ||
76 | * are presented to the GIC CPUIF as follow: | ||
77 | * (GIC_(R)DIST_PRI[irq] >> 1) | 0x80; | ||
78 | * | ||
79 | * If SCR_EL3.FIQ == 1, the values writen to/read from PMR and RPR at non-secure | ||
80 | * EL1 are subject to a similar operation thus matching the priorities presented | ||
81 | * from the (re)distributor when security is enabled. | ||
82 | * | ||
83 | * see GICv3/GICv4 Architecture Specification (IHI0069D): | ||
84 | * - section 4.8.1 Non-secure accesses to register fields for Secure interrupt | ||
85 | * priorities. | ||
86 | * - Figure 4-7 Secure read of the priority field for a Non-secure Group 1 | ||
87 | * interrupt. | ||
88 | * | ||
89 | * For now, we only support pseudo-NMIs if we have non-secure view of | ||
90 | * priorities. | ||
91 | */ | ||
92 | static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis); | ||
93 | |||
69 | static struct gic_kvm_info gic_v3_kvm_info; | 94 | static struct gic_kvm_info gic_v3_kvm_info; |
70 | static DEFINE_PER_CPU(bool, has_rss); | 95 | static DEFINE_PER_CPU(bool, has_rss); |
71 | 96 | ||
@@ -232,6 +257,12 @@ static void gic_unmask_irq(struct irq_data *d) | |||
232 | gic_poke_irq(d, GICD_ISENABLER); | 257 | gic_poke_irq(d, GICD_ISENABLER); |
233 | } | 258 | } |
234 | 259 | ||
260 | static inline bool gic_supports_nmi(void) | ||
261 | { | ||
262 | return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && | ||
263 | static_branch_likely(&supports_pseudo_nmis); | ||
264 | } | ||
265 | |||
235 | static int gic_irq_set_irqchip_state(struct irq_data *d, | 266 | static int gic_irq_set_irqchip_state(struct irq_data *d, |
236 | enum irqchip_irq_state which, bool val) | 267 | enum irqchip_irq_state which, bool val) |
237 | { | 268 | { |
@@ -573,6 +604,12 @@ static void gic_update_vlpi_properties(void) | |||
573 | !gic_data.rdists.has_direct_lpi ? "no " : ""); | 604 | !gic_data.rdists.has_direct_lpi ? "no " : ""); |
574 | } | 605 | } |
575 | 606 | ||
607 | /* Check whether it's single security state view */ | ||
608 | static inline bool gic_dist_security_disabled(void) | ||
609 | { | ||
610 | return readl_relaxed(gic_data.dist_base + GICD_CTLR) & GICD_CTLR_DS; | ||
611 | } | ||
612 | |||
576 | static void gic_cpu_sys_reg_init(void) | 613 | static void gic_cpu_sys_reg_init(void) |
577 | { | 614 | { |
578 | int i, cpu = smp_processor_id(); | 615 | int i, cpu = smp_processor_id(); |
@@ -596,8 +633,17 @@ static void gic_cpu_sys_reg_init(void) | |||
596 | group0 = gic_has_group0(); | 633 | group0 = gic_has_group0(); |
597 | 634 | ||
598 | /* Set priority mask register */ | 635 | /* Set priority mask register */ |
599 | if (!gic_prio_masking_enabled()) | 636 | if (!gic_prio_masking_enabled()) { |
600 | write_gicreg(DEFAULT_PMR_VALUE, ICC_PMR_EL1); | 637 | write_gicreg(DEFAULT_PMR_VALUE, ICC_PMR_EL1); |
638 | } else { | ||
639 | /* | ||
640 | * Mismatch configuration with boot CPU, the system is likely | ||
641 | * to die as interrupt masking will not work properly on all | ||
642 | * CPUs | ||
643 | */ | ||
644 | WARN_ON(gic_supports_nmi() && group0 && | ||
645 | !gic_dist_security_disabled()); | ||
646 | } | ||
601 | 647 | ||
602 | /* | 648 | /* |
603 | * Some firmwares hand over to the kernel with the BPR changed from | 649 | * Some firmwares hand over to the kernel with the BPR changed from |
@@ -852,12 +898,6 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, | |||
852 | #endif | 898 | #endif |
853 | 899 | ||
854 | #ifdef CONFIG_CPU_PM | 900 | #ifdef CONFIG_CPU_PM |
855 | /* Check whether it's single security state view */ | ||
856 | static bool gic_dist_security_disabled(void) | ||
857 | { | ||
858 | return readl_relaxed(gic_data.dist_base + GICD_CTLR) & GICD_CTLR_DS; | ||
859 | } | ||
860 | |||
861 | static int gic_cpu_pm_notifier(struct notifier_block *self, | 901 | static int gic_cpu_pm_notifier(struct notifier_block *self, |
862 | unsigned long cmd, void *v) | 902 | unsigned long cmd, void *v) |
863 | { | 903 | { |
@@ -1110,6 +1150,11 @@ static bool gic_enable_quirk_msm8996(void *data) | |||
1110 | return true; | 1150 | return true; |
1111 | } | 1151 | } |
1112 | 1152 | ||
1153 | static void gic_enable_nmi_support(void) | ||
1154 | { | ||
1155 | static_branch_enable(&supports_pseudo_nmis); | ||
1156 | } | ||
1157 | |||
1113 | static int __init gic_init_bases(void __iomem *dist_base, | 1158 | static int __init gic_init_bases(void __iomem *dist_base, |
1114 | struct redist_region *rdist_regs, | 1159 | struct redist_region *rdist_regs, |
1115 | u32 nr_redist_regions, | 1160 | u32 nr_redist_regions, |
@@ -1179,6 +1224,13 @@ static int __init gic_init_bases(void __iomem *dist_base, | |||
1179 | its_cpu_init(); | 1224 | its_cpu_init(); |
1180 | } | 1225 | } |
1181 | 1226 | ||
1227 | if (gic_prio_masking_enabled()) { | ||
1228 | if (!gic_has_group0() || gic_dist_security_disabled()) | ||
1229 | gic_enable_nmi_support(); | ||
1230 | else | ||
1231 | pr_warn("SCR_EL3.FIQ is cleared, cannot enable use of pseudo-NMIs\n"); | ||
1232 | } | ||
1233 | |||
1182 | return 0; | 1234 | return 0; |
1183 | 1235 | ||
1184 | out_free: | 1236 | out_free: |