aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShanker Donthineni <shankerd@codeaurora.org>2017-10-06 11:24:00 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2017-10-19 06:22:34 -0400
commiteda0d04acc5e317da675ee93a3f09e7c2e2fa592 (patch)
treead6f831dd6a027d3813e44655568d90453e42f18
parentc0ca7262088ebab67452a39f27979d3faa4762f0 (diff)
irqchip/gic-v3: Add support for Range Selector (RS) feature
A new feature Range Selector (RS) has been added to GIC specification in order to support more than 16 CPUs at affinity level 0. New fields are introduced in SGI system registers (ICC_SGI0R_EL1, ICC_SGI1R_EL1 and ICC_ASGI1R_EL1) to relax an artificial limit of 16 at level 0. - A new RSS field in ICC_CTLR_EL3, ICC_CTLR_EL1 and ICV_CTLR_EL1: [18] - Range Selector Support (RSS) 0b0 = Targeted SGIs with affinity level 0 values of 0-15 are supported. 0b1 = Targeted SGIs with affinity level 0 values of 0-255 are supported. - A new RS field in ICC_SGI0R_EL1, ICC_SGI1R_EL1 and ICC_ASGI1R_EL1: [47:44] - RangeSelector (RS) which group of 16 TargetList[n] field TargetList[n] represents aff0 value ((RS*16)+n) When ICC_CTLR_EL3.RSS==0 or ICC_CTLR_EL1.RSS==0, RS is RES0. - A new RSS field in GICD_TYPER: [26] - Range Selector Support (RSS) 0b0 = Targeted SGIs with affinity level 0 values of 0-15 are supported. 0b1 = Targeted SGIs with affinity level 0 values of 0-255 are supported. Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--arch/arm/include/asm/arch_gicv3.h5
-rw-r--r--arch/arm64/include/asm/arch_gicv3.h5
-rw-r--r--drivers/irqchip/irq-gic-v3.c50
-rw-r--r--include/linux/irqchip/arm-gic-v3.h4
4 files changed, 55 insertions, 9 deletions
diff --git a/arch/arm/include/asm/arch_gicv3.h b/arch/arm/include/asm/arch_gicv3.h
index eee269321923..1070044f5c3f 100644
--- a/arch/arm/include/asm/arch_gicv3.h
+++ b/arch/arm/include/asm/arch_gicv3.h
@@ -196,6 +196,11 @@ static inline void gic_write_ctlr(u32 val)
196 isb(); 196 isb();
197} 197}
198 198
199static inline u32 gic_read_ctlr(void)
200{
201 return read_sysreg(ICC_CTLR);
202}
203
199static inline void gic_write_grpen1(u32 val) 204static inline void gic_write_grpen1(u32 val)
200{ 205{
201 write_sysreg(val, ICC_IGRPEN1); 206 write_sysreg(val, ICC_IGRPEN1);
diff --git a/arch/arm64/include/asm/arch_gicv3.h b/arch/arm64/include/asm/arch_gicv3.h
index b7e3f74822da..9becba9ab392 100644
--- a/arch/arm64/include/asm/arch_gicv3.h
+++ b/arch/arm64/include/asm/arch_gicv3.h
@@ -87,6 +87,11 @@ static inline void gic_write_ctlr(u32 val)
87 isb(); 87 isb();
88} 88}
89 89
90static inline u32 gic_read_ctlr(void)
91{
92 return read_sysreg_s(SYS_ICC_CTLR_EL1);
93}
94
90static inline void gic_write_grpen1(u32 val) 95static inline void gic_write_grpen1(u32 val)
91{ 96{
92 write_sysreg_s(val, SYS_ICC_IGRPEN1_EL1); 97 write_sysreg_s(val, SYS_ICC_IGRPEN1_EL1);
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index b5df99c6f680..b54b55597ffb 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -55,6 +55,7 @@ struct gic_chip_data {
55 struct irq_domain *domain; 55 struct irq_domain *domain;
56 u64 redist_stride; 56 u64 redist_stride;
57 u32 nr_redist_regions; 57 u32 nr_redist_regions;
58 bool has_rss;
58 unsigned int irq_nr; 59 unsigned int irq_nr;
59 struct partition_desc *ppi_descs[16]; 60 struct partition_desc *ppi_descs[16];
60}; 61};
@@ -63,7 +64,9 @@ static struct gic_chip_data gic_data __read_mostly;
63static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; 64static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE;
64 65
65static struct gic_kvm_info gic_v3_kvm_info; 66static struct gic_kvm_info gic_v3_kvm_info;
67static DEFINE_PER_CPU(bool, has_rss);
66 68
69#define MPIDR_RS(mpidr) (((mpidr) & 0xF0UL) >> 4)
67#define gic_data_rdist() (this_cpu_ptr(gic_data.rdists.rdist)) 70#define gic_data_rdist() (this_cpu_ptr(gic_data.rdists.rdist))
68#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) 71#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base)
69#define gic_data_rdist_sgi_base() (gic_data_rdist_rd_base() + SZ_64K) 72#define gic_data_rdist_sgi_base() (gic_data_rdist_rd_base() + SZ_64K)
@@ -526,6 +529,10 @@ static void gic_update_vlpi_properties(void)
526 529
527static void gic_cpu_sys_reg_init(void) 530static void gic_cpu_sys_reg_init(void)
528{ 531{
532 int i, cpu = smp_processor_id();
533 u64 mpidr = cpu_logical_map(cpu);
534 u64 need_rss = MPIDR_RS(mpidr);
535
529 /* 536 /*
530 * Need to check that the SRE bit has actually been set. If 537 * Need to check that the SRE bit has actually been set. If
531 * not, it means that SRE is disabled at EL2. We're going to 538 * not, it means that SRE is disabled at EL2. We're going to
@@ -557,6 +564,30 @@ static void gic_cpu_sys_reg_init(void)
557 564
558 /* ... and let's hit the road... */ 565 /* ... and let's hit the road... */
559 gic_write_grpen1(1); 566 gic_write_grpen1(1);
567
568 /* Keep the RSS capability status in per_cpu variable */
569 per_cpu(has_rss, cpu) = !!(gic_read_ctlr() & ICC_CTLR_EL1_RSS);
570
571 /* Check all the CPUs have capable of sending SGIs to other CPUs */
572 for_each_online_cpu(i) {
573 bool have_rss = per_cpu(has_rss, i) && per_cpu(has_rss, cpu);
574
575 need_rss |= MPIDR_RS(cpu_logical_map(i));
576 if (need_rss && (!have_rss))
577 pr_crit("CPU%d (%lx) can't SGI CPU%d (%lx), no RSS\n",
578 cpu, (unsigned long)mpidr,
579 i, (unsigned long)cpu_logical_map(i));
580 }
581
582 /**
583 * GIC spec says, when ICC_CTLR_EL1.RSS==1 and GICD_TYPER.RSS==0,
584 * writing ICC_ASGI1R_EL1 register with RS != 0 is a CONSTRAINED
585 * UNPREDICTABLE choice of :
586 * - The write is ignored.
587 * - The RS field is treated as 0.
588 */
589 if (need_rss && (!gic_data.has_rss))
590 pr_crit_once("RSS is required but GICD doesn't support it\n");
560} 591}
561 592
562static int gic_dist_supports_lpis(void) 593static int gic_dist_supports_lpis(void)
@@ -591,6 +622,9 @@ static void gic_cpu_init(void)
591 622
592#ifdef CONFIG_SMP 623#ifdef CONFIG_SMP
593 624
625#define MPIDR_TO_SGI_RS(mpidr) (MPIDR_RS(mpidr) << ICC_SGI1R_RS_SHIFT)
626#define MPIDR_TO_SGI_CLUSTER_ID(mpidr) ((mpidr) & ~0xFUL)
627
594static int gic_starting_cpu(unsigned int cpu) 628static int gic_starting_cpu(unsigned int cpu)
595{ 629{
596 gic_cpu_init(); 630 gic_cpu_init();
@@ -605,13 +639,6 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
605 u16 tlist = 0; 639 u16 tlist = 0;
606 640
607 while (cpu < nr_cpu_ids) { 641 while (cpu < nr_cpu_ids) {
608 /*
609 * If we ever get a cluster of more than 16 CPUs, just
610 * scream and skip that CPU.
611 */
612 if (WARN_ON((mpidr & 0xff) >= 16))
613 goto out;
614
615 tlist |= 1 << (mpidr & 0xf); 642 tlist |= 1 << (mpidr & 0xf);
616 643
617 next_cpu = cpumask_next(cpu, mask); 644 next_cpu = cpumask_next(cpu, mask);
@@ -621,7 +648,7 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
621 648
622 mpidr = cpu_logical_map(cpu); 649 mpidr = cpu_logical_map(cpu);
623 650
624 if (cluster_id != (mpidr & ~0xffUL)) { 651 if (cluster_id != MPIDR_TO_SGI_CLUSTER_ID(mpidr)) {
625 cpu--; 652 cpu--;
626 goto out; 653 goto out;
627 } 654 }
@@ -643,6 +670,7 @@ static void gic_send_sgi(u64 cluster_id, u16 tlist, unsigned int irq)
643 MPIDR_TO_SGI_AFFINITY(cluster_id, 2) | 670 MPIDR_TO_SGI_AFFINITY(cluster_id, 2) |
644 irq << ICC_SGI1R_SGI_ID_SHIFT | 671 irq << ICC_SGI1R_SGI_ID_SHIFT |
645 MPIDR_TO_SGI_AFFINITY(cluster_id, 1) | 672 MPIDR_TO_SGI_AFFINITY(cluster_id, 1) |
673 MPIDR_TO_SGI_RS(cluster_id) |
646 tlist << ICC_SGI1R_TARGET_LIST_SHIFT); 674 tlist << ICC_SGI1R_TARGET_LIST_SHIFT);
647 675
648 pr_debug("CPU%d: ICC_SGI1R_EL1 %llx\n", smp_processor_id(), val); 676 pr_debug("CPU%d: ICC_SGI1R_EL1 %llx\n", smp_processor_id(), val);
@@ -663,7 +691,7 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
663 smp_wmb(); 691 smp_wmb();
664 692
665 for_each_cpu(cpu, mask) { 693 for_each_cpu(cpu, mask) {
666 unsigned long cluster_id = cpu_logical_map(cpu) & ~0xffUL; 694 u64 cluster_id = MPIDR_TO_SGI_CLUSTER_ID(cpu_logical_map(cpu));
667 u16 tlist; 695 u16 tlist;
668 696
669 tlist = gic_compute_target_list(&cpu, mask, cluster_id); 697 tlist = gic_compute_target_list(&cpu, mask, cluster_id);
@@ -1007,6 +1035,10 @@ static int __init gic_init_bases(void __iomem *dist_base,
1007 goto out_free; 1035 goto out_free;
1008 } 1036 }
1009 1037
1038 gic_data.has_rss = !!(typer & GICD_TYPER_RSS);
1039 pr_info("Distributor has %sRange Selector support\n",
1040 gic_data.has_rss ? "" : "no ");
1041
1010 set_handle_irq(gic_handle_irq); 1042 set_handle_irq(gic_handle_irq);
1011 1043
1012 gic_update_vlpi_properties(); 1044 gic_update_vlpi_properties();
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 1ea576c8126f..b8b59989bd73 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -68,6 +68,7 @@
68#define GICD_CTLR_ENABLE_SS_G1 (1U << 1) 68#define GICD_CTLR_ENABLE_SS_G1 (1U << 1)
69#define GICD_CTLR_ENABLE_SS_G0 (1U << 0) 69#define GICD_CTLR_ENABLE_SS_G0 (1U << 0)
70 70
71#define GICD_TYPER_RSS (1U << 26)
71#define GICD_TYPER_LPIS (1U << 17) 72#define GICD_TYPER_LPIS (1U << 17)
72#define GICD_TYPER_MBIS (1U << 16) 73#define GICD_TYPER_MBIS (1U << 16)
73 74
@@ -459,6 +460,7 @@
459#define ICC_CTLR_EL1_SEIS_MASK (0x1 << ICC_CTLR_EL1_SEIS_SHIFT) 460#define ICC_CTLR_EL1_SEIS_MASK (0x1 << ICC_CTLR_EL1_SEIS_SHIFT)
460#define ICC_CTLR_EL1_A3V_SHIFT 15 461#define ICC_CTLR_EL1_A3V_SHIFT 15
461#define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT) 462#define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT)
463#define ICC_CTLR_EL1_RSS (0x1 << 18)
462#define ICC_PMR_EL1_SHIFT 0 464#define ICC_PMR_EL1_SHIFT 0
463#define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT) 465#define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT)
464#define ICC_BPR0_EL1_SHIFT 0 466#define ICC_BPR0_EL1_SHIFT 0
@@ -547,6 +549,8 @@
547#define ICC_SGI1R_AFFINITY_2_SHIFT 32 549#define ICC_SGI1R_AFFINITY_2_SHIFT 32
548#define ICC_SGI1R_AFFINITY_2_MASK (0xffULL << ICC_SGI1R_AFFINITY_2_SHIFT) 550#define ICC_SGI1R_AFFINITY_2_MASK (0xffULL << ICC_SGI1R_AFFINITY_2_SHIFT)
549#define ICC_SGI1R_IRQ_ROUTING_MODE_BIT 40 551#define ICC_SGI1R_IRQ_ROUTING_MODE_BIT 40
552#define ICC_SGI1R_RS_SHIFT 44
553#define ICC_SGI1R_RS_MASK (0xfULL << ICC_SGI1R_RS_SHIFT)
550#define ICC_SGI1R_AFFINITY_3_SHIFT 48 554#define ICC_SGI1R_AFFINITY_3_SHIFT 48
551#define ICC_SGI1R_AFFINITY_3_MASK (0xffULL << ICC_SGI1R_AFFINITY_3_SHIFT) 555#define ICC_SGI1R_AFFINITY_3_MASK (0xffULL << ICC_SGI1R_AFFINITY_3_SHIFT)
552 556