cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

irq-hip04.c (10438B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * HiSilicon HiP04 INTC
      4 *
      5 * Copyright (C) 2002-2014 ARM Limited.
      6 * Copyright (c) 2013-2014 HiSilicon Ltd.
      7 * Copyright (c) 2013-2014 Linaro Ltd.
      8 *
      9 * Interrupt architecture for the HIP04 INTC:
     10 *
     11 * o There is one Interrupt Distributor, which receives interrupts
     12 *   from system devices and sends them to the Interrupt Controllers.
     13 *
     14 * o There is one CPU Interface per CPU, which sends interrupts sent
     15 *   by the Distributor, and interrupts generated locally, to the
     16 *   associated CPU. The base address of the CPU interface is usually
     17 *   aliased so that the same address points to different chips depending
     18 *   on the CPU it is accessed from.
     19 *
     20 * Note that IRQs 0-31 are special - they are local to each CPU.
     21 * As such, the enable set/clear, pending set/clear and active bit
     22 * registers are banked per-cpu for these sources.
     23 */
     24
     25#include <linux/init.h>
     26#include <linux/kernel.h>
     27#include <linux/err.h>
     28#include <linux/module.h>
     29#include <linux/list.h>
     30#include <linux/smp.h>
     31#include <linux/cpu.h>
     32#include <linux/cpu_pm.h>
     33#include <linux/cpumask.h>
     34#include <linux/io.h>
     35#include <linux/of.h>
     36#include <linux/of_address.h>
     37#include <linux/of_irq.h>
     38#include <linux/irqdomain.h>
     39#include <linux/interrupt.h>
     40#include <linux/slab.h>
     41#include <linux/irqchip.h>
     42#include <linux/irqchip/arm-gic.h>
     43
     44#include <asm/irq.h>
     45#include <asm/exception.h>
     46#include <asm/smp_plat.h>
     47
     48#include "irq-gic-common.h"
     49
     50#define HIP04_MAX_IRQS		510
     51
     52struct hip04_irq_data {
     53	void __iomem *dist_base;
     54	void __iomem *cpu_base;
     55	struct irq_domain *domain;
     56	unsigned int nr_irqs;
     57};
     58
     59static DEFINE_RAW_SPINLOCK(irq_controller_lock);
     60
     61/*
     62 * The GIC mapping of CPU interfaces does not necessarily match
     63 * the logical CPU numbering.  Let's use a mapping as returned
     64 * by the GIC itself.
     65 */
     66#define NR_HIP04_CPU_IF 16
     67static u16 hip04_cpu_map[NR_HIP04_CPU_IF] __read_mostly;
     68
     69static struct hip04_irq_data hip04_data __read_mostly;
     70
     71static inline void __iomem *hip04_dist_base(struct irq_data *d)
     72{
     73	struct hip04_irq_data *hip04_data = irq_data_get_irq_chip_data(d);
     74	return hip04_data->dist_base;
     75}
     76
     77static inline void __iomem *hip04_cpu_base(struct irq_data *d)
     78{
     79	struct hip04_irq_data *hip04_data = irq_data_get_irq_chip_data(d);
     80	return hip04_data->cpu_base;
     81}
     82
     83static inline unsigned int hip04_irq(struct irq_data *d)
     84{
     85	return d->hwirq;
     86}
     87
     88/*
     89 * Routines to acknowledge, disable and enable interrupts
     90 */
     91static void hip04_mask_irq(struct irq_data *d)
     92{
     93	u32 mask = 1 << (hip04_irq(d) % 32);
     94
     95	raw_spin_lock(&irq_controller_lock);
     96	writel_relaxed(mask, hip04_dist_base(d) + GIC_DIST_ENABLE_CLEAR +
     97		       (hip04_irq(d) / 32) * 4);
     98	raw_spin_unlock(&irq_controller_lock);
     99}
    100
    101static void hip04_unmask_irq(struct irq_data *d)
    102{
    103	u32 mask = 1 << (hip04_irq(d) % 32);
    104
    105	raw_spin_lock(&irq_controller_lock);
    106	writel_relaxed(mask, hip04_dist_base(d) + GIC_DIST_ENABLE_SET +
    107		       (hip04_irq(d) / 32) * 4);
    108	raw_spin_unlock(&irq_controller_lock);
    109}
    110
    111static void hip04_eoi_irq(struct irq_data *d)
    112{
    113	writel_relaxed(hip04_irq(d), hip04_cpu_base(d) + GIC_CPU_EOI);
    114}
    115
    116static int hip04_irq_set_type(struct irq_data *d, unsigned int type)
    117{
    118	void __iomem *base = hip04_dist_base(d);
    119	unsigned int irq = hip04_irq(d);
    120	int ret;
    121
    122	/* Interrupt configuration for SGIs can't be changed */
    123	if (irq < 16)
    124		return -EINVAL;
    125
    126	/* SPIs have restrictions on the supported types */
    127	if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
    128			 type != IRQ_TYPE_EDGE_RISING)
    129		return -EINVAL;
    130
    131	raw_spin_lock(&irq_controller_lock);
    132
    133	ret = gic_configure_irq(irq, type, base + GIC_DIST_CONFIG, NULL);
    134	if (ret && irq < 32) {
    135		/* Misconfigured PPIs are usually not fatal */
    136		pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
    137		ret = 0;
    138	}
    139
    140	raw_spin_unlock(&irq_controller_lock);
    141
    142	return ret;
    143}
    144
    145#ifdef CONFIG_SMP
    146static int hip04_irq_set_affinity(struct irq_data *d,
    147				  const struct cpumask *mask_val,
    148				  bool force)
    149{
    150	void __iomem *reg;
    151	unsigned int cpu, shift = (hip04_irq(d) % 2) * 16;
    152	u32 val, mask, bit;
    153
    154	if (!force)
    155		cpu = cpumask_any_and(mask_val, cpu_online_mask);
    156	else
    157		cpu = cpumask_first(mask_val);
    158
    159	if (cpu >= NR_HIP04_CPU_IF || cpu >= nr_cpu_ids)
    160		return -EINVAL;
    161
    162	raw_spin_lock(&irq_controller_lock);
    163	reg = hip04_dist_base(d) + GIC_DIST_TARGET + ((hip04_irq(d) * 2) & ~3);
    164	mask = 0xffff << shift;
    165	bit = hip04_cpu_map[cpu] << shift;
    166	val = readl_relaxed(reg) & ~mask;
    167	writel_relaxed(val | bit, reg);
    168	raw_spin_unlock(&irq_controller_lock);
    169
    170	irq_data_update_effective_affinity(d, cpumask_of(cpu));
    171
    172	return IRQ_SET_MASK_OK;
    173}
    174
    175static void hip04_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)
    176{
    177	int cpu;
    178	unsigned long flags, map = 0;
    179
    180	raw_spin_lock_irqsave(&irq_controller_lock, flags);
    181
    182	/* Convert our logical CPU mask into a physical one. */
    183	for_each_cpu(cpu, mask)
    184		map |= hip04_cpu_map[cpu];
    185
    186	/*
    187	 * Ensure that stores to Normal memory are visible to the
    188	 * other CPUs before they observe us issuing the IPI.
    189	 */
    190	dmb(ishst);
    191
    192	/* this always happens on GIC0 */
    193	writel_relaxed(map << 8 | d->hwirq, hip04_data.dist_base + GIC_DIST_SOFTINT);
    194
    195	raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
    196}
    197#endif
    198
    199static void __exception_irq_entry hip04_handle_irq(struct pt_regs *regs)
    200{
    201	u32 irqstat, irqnr;
    202	void __iomem *cpu_base = hip04_data.cpu_base;
    203
    204	do {
    205		irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
    206		irqnr = irqstat & GICC_IAR_INT_ID_MASK;
    207
    208		if (irqnr <= HIP04_MAX_IRQS)
    209			generic_handle_domain_irq(hip04_data.domain, irqnr);
    210	} while (irqnr > HIP04_MAX_IRQS);
    211}
    212
    213static struct irq_chip hip04_irq_chip = {
    214	.name			= "HIP04 INTC",
    215	.irq_mask		= hip04_mask_irq,
    216	.irq_unmask		= hip04_unmask_irq,
    217	.irq_eoi		= hip04_eoi_irq,
    218	.irq_set_type		= hip04_irq_set_type,
    219#ifdef CONFIG_SMP
    220	.irq_set_affinity	= hip04_irq_set_affinity,
    221	.ipi_send_mask		= hip04_ipi_send_mask,
    222#endif
    223	.flags			= IRQCHIP_SET_TYPE_MASKED |
    224				  IRQCHIP_SKIP_SET_WAKE |
    225				  IRQCHIP_MASK_ON_SUSPEND,
    226};
    227
    228static u16 hip04_get_cpumask(struct hip04_irq_data *intc)
    229{
    230	void __iomem *base = intc->dist_base;
    231	u32 mask, i;
    232
    233	for (i = mask = 0; i < 32; i += 2) {
    234		mask = readl_relaxed(base + GIC_DIST_TARGET + i * 2);
    235		mask |= mask >> 16;
    236		if (mask)
    237			break;
    238	}
    239
    240	if (!mask)
    241		pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");
    242
    243	return mask;
    244}
    245
    246static void __init hip04_irq_dist_init(struct hip04_irq_data *intc)
    247{
    248	unsigned int i;
    249	u32 cpumask;
    250	unsigned int nr_irqs = intc->nr_irqs;
    251	void __iomem *base = intc->dist_base;
    252
    253	writel_relaxed(0, base + GIC_DIST_CTRL);
    254
    255	/*
    256	 * Set all global interrupts to this CPU only.
    257	 */
    258	cpumask = hip04_get_cpumask(intc);
    259	cpumask |= cpumask << 16;
    260	for (i = 32; i < nr_irqs; i += 2)
    261		writel_relaxed(cpumask, base + GIC_DIST_TARGET + ((i * 2) & ~3));
    262
    263	gic_dist_config(base, nr_irqs, NULL);
    264
    265	writel_relaxed(1, base + GIC_DIST_CTRL);
    266}
    267
    268static void hip04_irq_cpu_init(struct hip04_irq_data *intc)
    269{
    270	void __iomem *dist_base = intc->dist_base;
    271	void __iomem *base = intc->cpu_base;
    272	unsigned int cpu_mask, cpu = smp_processor_id();
    273	int i;
    274
    275	/*
    276	 * Get what the GIC says our CPU mask is.
    277	 */
    278	BUG_ON(cpu >= NR_HIP04_CPU_IF);
    279	cpu_mask = hip04_get_cpumask(intc);
    280	hip04_cpu_map[cpu] = cpu_mask;
    281
    282	/*
    283	 * Clear our mask from the other map entries in case they're
    284	 * still undefined.
    285	 */
    286	for (i = 0; i < NR_HIP04_CPU_IF; i++)
    287		if (i != cpu)
    288			hip04_cpu_map[i] &= ~cpu_mask;
    289
    290	gic_cpu_config(dist_base, 32, NULL);
    291
    292	writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
    293	writel_relaxed(1, base + GIC_CPU_CTRL);
    294}
    295
    296static int hip04_irq_domain_map(struct irq_domain *d, unsigned int irq,
    297				irq_hw_number_t hw)
    298{
    299	if (hw < 32) {
    300		irq_set_percpu_devid(irq);
    301		irq_set_chip_and_handler(irq, &hip04_irq_chip,
    302					 handle_percpu_devid_irq);
    303	} else {
    304		irq_set_chip_and_handler(irq, &hip04_irq_chip,
    305					 handle_fasteoi_irq);
    306		irq_set_probe(irq);
    307		irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
    308	}
    309	irq_set_chip_data(irq, d->host_data);
    310	return 0;
    311}
    312
    313static int hip04_irq_domain_xlate(struct irq_domain *d,
    314				  struct device_node *controller,
    315				  const u32 *intspec, unsigned int intsize,
    316				  unsigned long *out_hwirq,
    317				  unsigned int *out_type)
    318{
    319	if (irq_domain_get_of_node(d) != controller)
    320		return -EINVAL;
    321	if (intsize == 1 && intspec[0] < 16) {
    322		*out_hwirq = intspec[0];
    323		*out_type = IRQ_TYPE_EDGE_RISING;
    324		return 0;
    325	}
    326	if (intsize < 3)
    327		return -EINVAL;
    328
    329	/* Get the interrupt number and add 16 to skip over SGIs */
    330	*out_hwirq = intspec[1] + 16;
    331
    332	/* For SPIs, we need to add 16 more to get the irq ID number */
    333	if (!intspec[0])
    334		*out_hwirq += 16;
    335
    336	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
    337
    338	return 0;
    339}
    340
    341static int hip04_irq_starting_cpu(unsigned int cpu)
    342{
    343	hip04_irq_cpu_init(&hip04_data);
    344	return 0;
    345}
    346
    347static const struct irq_domain_ops hip04_irq_domain_ops = {
    348	.map	= hip04_irq_domain_map,
    349	.xlate	= hip04_irq_domain_xlate,
    350};
    351
    352static int __init
    353hip04_of_init(struct device_node *node, struct device_node *parent)
    354{
    355	int nr_irqs, irq_base, i;
    356
    357	if (WARN_ON(!node))
    358		return -ENODEV;
    359
    360	hip04_data.dist_base = of_iomap(node, 0);
    361	WARN(!hip04_data.dist_base, "fail to map hip04 intc dist registers\n");
    362
    363	hip04_data.cpu_base = of_iomap(node, 1);
    364	WARN(!hip04_data.cpu_base, "unable to map hip04 intc cpu registers\n");
    365
    366	/*
    367	 * Initialize the CPU interface map to all CPUs.
    368	 * It will be refined as each CPU probes its ID.
    369	 */
    370	for (i = 0; i < NR_HIP04_CPU_IF; i++)
    371		hip04_cpu_map[i] = 0xffff;
    372
    373	/*
    374	 * Find out how many interrupts are supported.
    375	 * The HIP04 INTC only supports up to 510 interrupt sources.
    376	 */
    377	nr_irqs = readl_relaxed(hip04_data.dist_base + GIC_DIST_CTR) & 0x1f;
    378	nr_irqs = (nr_irqs + 1) * 32;
    379	if (nr_irqs > HIP04_MAX_IRQS)
    380		nr_irqs = HIP04_MAX_IRQS;
    381	hip04_data.nr_irqs = nr_irqs;
    382
    383	irq_base = irq_alloc_descs(-1, 0, nr_irqs, numa_node_id());
    384	if (irq_base < 0) {
    385		pr_err("failed to allocate IRQ numbers\n");
    386		return -EINVAL;
    387	}
    388
    389	hip04_data.domain = irq_domain_add_legacy(node, nr_irqs, irq_base,
    390						  0,
    391						  &hip04_irq_domain_ops,
    392						  &hip04_data);
    393	if (WARN_ON(!hip04_data.domain))
    394		return -EINVAL;
    395
    396#ifdef CONFIG_SMP
    397	set_smp_ipi_range(irq_base, 16);
    398#endif
    399	set_handle_irq(hip04_handle_irq);
    400
    401	hip04_irq_dist_init(&hip04_data);
    402	cpuhp_setup_state(CPUHP_AP_IRQ_HIP04_STARTING, "irqchip/hip04:starting",
    403			  hip04_irq_starting_cpu, NULL);
    404	return 0;
    405}
    406IRQCHIP_DECLARE(hip04_intc, "hisilicon,hip04-intc", hip04_of_init);