Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Shanker Donthineni and committed by
Marc Zyngier
eda0d04a c0ca7262

+55 -9
+5
arch/arm/include/asm/arch_gicv3.h
··· 196 196 isb(); 197 197 } 198 198 199 + static inline u32 gic_read_ctlr(void) 200 + { 201 + return read_sysreg(ICC_CTLR); 202 + } 203 + 199 204 static inline void gic_write_grpen1(u32 val) 200 205 { 201 206 write_sysreg(val, ICC_IGRPEN1);
+5
arch/arm64/include/asm/arch_gicv3.h
··· 87 87 isb(); 88 88 } 89 89 90 + static inline u32 gic_read_ctlr(void) 91 + { 92 + return read_sysreg_s(SYS_ICC_CTLR_EL1); 93 + } 94 + 90 95 static inline void gic_write_grpen1(u32 val) 91 96 { 92 97 write_sysreg_s(val, SYS_ICC_IGRPEN1_EL1);
+41 -9
drivers/irqchip/irq-gic-v3.c
··· 55 55 struct irq_domain *domain; 56 56 u64 redist_stride; 57 57 u32 nr_redist_regions; 58 + bool has_rss; 58 59 unsigned int irq_nr; 59 60 struct partition_desc *ppi_descs[16]; 60 61 }; ··· 64 63 static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; 65 64 66 65 static struct gic_kvm_info gic_v3_kvm_info; 66 + static DEFINE_PER_CPU(bool, has_rss); 67 67 68 + #define MPIDR_RS(mpidr) (((mpidr) & 0xF0UL) >> 4) 68 69 #define gic_data_rdist() (this_cpu_ptr(gic_data.rdists.rdist)) 69 70 #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) 70 71 #define gic_data_rdist_sgi_base() (gic_data_rdist_rd_base() + SZ_64K) ··· 529 526 530 527 static void gic_cpu_sys_reg_init(void) 531 528 { 529 + int i, cpu = smp_processor_id(); 530 + u64 mpidr = cpu_logical_map(cpu); 531 + u64 need_rss = MPIDR_RS(mpidr); 532 + 532 533 /* 533 534 * Need to check that the SRE bit has actually been set. If 534 535 * not, it means that SRE is disabled at EL2. We're going to ··· 564 557 565 558 /* ... and let's hit the road... */ 566 559 gic_write_grpen1(1); 560 + 561 + /* Keep the RSS capability status in per_cpu variable */ 562 + per_cpu(has_rss, cpu) = !!(gic_read_ctlr() & ICC_CTLR_EL1_RSS); 563 + 564 + /* Check all the CPUs have capable of sending SGIs to other CPUs */ 565 + for_each_online_cpu(i) { 566 + bool have_rss = per_cpu(has_rss, i) && per_cpu(has_rss, cpu); 567 + 568 + need_rss |= MPIDR_RS(cpu_logical_map(i)); 569 + if (need_rss && (!have_rss)) 570 + pr_crit("CPU%d (%lx) can't SGI CPU%d (%lx), no RSS\n", 571 + cpu, (unsigned long)mpidr, 572 + i, (unsigned long)cpu_logical_map(i)); 573 + } 574 + 575 + /** 576 + * GIC spec says, when ICC_CTLR_EL1.RSS==1 and GICD_TYPER.RSS==0, 577 + * writing ICC_ASGI1R_EL1 register with RS != 0 is a CONSTRAINED 578 + * UNPREDICTABLE choice of : 579 + * - The write is ignored. 580 + * - The RS field is treated as 0. 581 + */ 582 + if (need_rss && (!gic_data.has_rss)) 583 + pr_crit_once("RSS is required but GICD doesn't support it\n"); 567 584 } 568 585 569 586 static int gic_dist_supports_lpis(void) ··· 622 591 623 592 #ifdef CONFIG_SMP 624 593 594 + #define MPIDR_TO_SGI_RS(mpidr) (MPIDR_RS(mpidr) << ICC_SGI1R_RS_SHIFT) 595 + #define MPIDR_TO_SGI_CLUSTER_ID(mpidr) ((mpidr) & ~0xFUL) 596 + 625 597 static int gic_starting_cpu(unsigned int cpu) 626 598 { 627 599 gic_cpu_init(); ··· 639 605 u16 tlist = 0; 640 606 641 607 while (cpu < nr_cpu_ids) { 642 - /* 643 - * If we ever get a cluster of more than 16 CPUs, just 644 - * scream and skip that CPU. 645 - */ 646 - if (WARN_ON((mpidr & 0xff) >= 16)) 647 - goto out; 648 - 649 608 tlist |= 1 << (mpidr & 0xf); 650 609 651 610 next_cpu = cpumask_next(cpu, mask); ··· 648 621 649 622 mpidr = cpu_logical_map(cpu); 650 623 651 - if (cluster_id != (mpidr & ~0xffUL)) { 624 + if (cluster_id != MPIDR_TO_SGI_CLUSTER_ID(mpidr)) { 652 625 cpu--; 653 626 goto out; 654 627 } ··· 670 643 MPIDR_TO_SGI_AFFINITY(cluster_id, 2) | 671 644 irq << ICC_SGI1R_SGI_ID_SHIFT | 672 645 MPIDR_TO_SGI_AFFINITY(cluster_id, 1) | 646 + MPIDR_TO_SGI_RS(cluster_id) | 673 647 tlist << ICC_SGI1R_TARGET_LIST_SHIFT); 674 648 675 649 pr_debug("CPU%d: ICC_SGI1R_EL1 %llx\n", smp_processor_id(), val); ··· 691 663 smp_wmb(); 692 664 693 665 for_each_cpu(cpu, mask) { 694 - unsigned long cluster_id = cpu_logical_map(cpu) & ~0xffUL; 666 + u64 cluster_id = MPIDR_TO_SGI_CLUSTER_ID(cpu_logical_map(cpu)); 695 667 u16 tlist; 696 668 697 669 tlist = gic_compute_target_list(&cpu, mask, cluster_id); ··· 1034 1006 err = -ENOMEM; 1035 1007 goto out_free; 1036 1008 } 1009 + 1010 + gic_data.has_rss = !!(typer & GICD_TYPER_RSS); 1011 + pr_info("Distributor has %sRange Selector support\n", 1012 + gic_data.has_rss ? "" : "no "); 1037 1013 1038 1014 set_handle_irq(gic_handle_irq); 1039 1015
+4
include/linux/irqchip/arm-gic-v3.h
··· 68 68 #define GICD_CTLR_ENABLE_SS_G1 (1U << 1) 69 69 #define GICD_CTLR_ENABLE_SS_G0 (1U << 0) 70 70 71 + #define GICD_TYPER_RSS (1U << 26) 71 72 #define GICD_TYPER_LPIS (1U << 17) 72 73 #define GICD_TYPER_MBIS (1U << 16) 73 74 ··· 460 459 #define ICC_CTLR_EL1_SEIS_MASK (0x1 << ICC_CTLR_EL1_SEIS_SHIFT) 461 460 #define ICC_CTLR_EL1_A3V_SHIFT 15 462 461 #define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT) 462 + #define ICC_CTLR_EL1_RSS (0x1 << 18) 463 463 #define ICC_PMR_EL1_SHIFT 0 464 464 #define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT) 465 465 #define ICC_BPR0_EL1_SHIFT 0 ··· 549 547 #define ICC_SGI1R_AFFINITY_2_SHIFT 32 550 548 #define ICC_SGI1R_AFFINITY_2_MASK (0xffULL << ICC_SGI1R_AFFINITY_2_SHIFT) 551 549 #define ICC_SGI1R_IRQ_ROUTING_MODE_BIT 40 550 + #define ICC_SGI1R_RS_SHIFT 44 551 + #define ICC_SGI1R_RS_MASK (0xfULL << ICC_SGI1R_RS_SHIFT) 552 552 #define ICC_SGI1R_AFFINITY_3_SHIFT 48 553 553 #define ICC_SGI1R_AFFINITY_3_MASK (0xffULL << ICC_SGI1R_AFFINITY_3_SHIFT) 554 554