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

interrupt.c (9935B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Cell Internal Interrupt Controller
      4 *
      5 * Copyright (C) 2006 Benjamin Herrenschmidt (benh@kernel.crashing.org)
      6 *                    IBM, Corp.
      7 *
      8 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
      9 *
     10 * Author: Arnd Bergmann <arndb@de.ibm.com>
     11 *
     12 * TODO:
     13 * - Fix various assumptions related to HW CPU numbers vs. linux CPU numbers
     14 *   vs node numbers in the setup code
     15 * - Implement proper handling of maxcpus=1/2 (that is, routing of irqs from
     16 *   a non-active node to the active node)
     17 */
     18
     19#include <linux/interrupt.h>
     20#include <linux/irq.h>
     21#include <linux/irqdomain.h>
     22#include <linux/export.h>
     23#include <linux/percpu.h>
     24#include <linux/types.h>
     25#include <linux/ioport.h>
     26#include <linux/kernel_stat.h>
     27#include <linux/pgtable.h>
     28#include <linux/of_address.h>
     29
     30#include <asm/io.h>
     31#include <asm/ptrace.h>
     32#include <asm/machdep.h>
     33#include <asm/cell-regs.h>
     34
     35#include "interrupt.h"
     36
     37struct iic {
     38	struct cbe_iic_thread_regs __iomem *regs;
     39	u8 target_id;
     40	u8 eoi_stack[16];
     41	int eoi_ptr;
     42	struct device_node *node;
     43};
     44
     45static DEFINE_PER_CPU(struct iic, cpu_iic);
     46#define IIC_NODE_COUNT	2
     47static struct irq_domain *iic_host;
     48
     49/* Convert between "pending" bits and hw irq number */
     50static irq_hw_number_t iic_pending_to_hwnum(struct cbe_iic_pending_bits bits)
     51{
     52	unsigned char unit = bits.source & 0xf;
     53	unsigned char node = bits.source >> 4;
     54	unsigned char class = bits.class & 3;
     55
     56	/* Decode IPIs */
     57	if (bits.flags & CBE_IIC_IRQ_IPI)
     58		return IIC_IRQ_TYPE_IPI | (bits.prio >> 4);
     59	else
     60		return (node << IIC_IRQ_NODE_SHIFT) | (class << 4) | unit;
     61}
     62
     63static void iic_mask(struct irq_data *d)
     64{
     65}
     66
     67static void iic_unmask(struct irq_data *d)
     68{
     69}
     70
     71static void iic_eoi(struct irq_data *d)
     72{
     73	struct iic *iic = this_cpu_ptr(&cpu_iic);
     74	out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]);
     75	BUG_ON(iic->eoi_ptr < 0);
     76}
     77
     78static struct irq_chip iic_chip = {
     79	.name = "CELL-IIC",
     80	.irq_mask = iic_mask,
     81	.irq_unmask = iic_unmask,
     82	.irq_eoi = iic_eoi,
     83};
     84
     85
     86static void iic_ioexc_eoi(struct irq_data *d)
     87{
     88}
     89
     90static void iic_ioexc_cascade(struct irq_desc *desc)
     91{
     92	struct irq_chip *chip = irq_desc_get_chip(desc);
     93	struct cbe_iic_regs __iomem *node_iic =
     94		(void __iomem *)irq_desc_get_handler_data(desc);
     95	unsigned int irq = irq_desc_get_irq(desc);
     96	unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
     97	unsigned long bits, ack;
     98	int cascade;
     99
    100	for (;;) {
    101		bits = in_be64(&node_iic->iic_is);
    102		if (bits == 0)
    103			break;
    104		/* pre-ack edge interrupts */
    105		ack = bits & IIC_ISR_EDGE_MASK;
    106		if (ack)
    107			out_be64(&node_iic->iic_is, ack);
    108		/* handle them */
    109		for (cascade = 63; cascade >= 0; cascade--)
    110			if (bits & (0x8000000000000000UL >> cascade))
    111				generic_handle_domain_irq(iic_host,
    112							  base | cascade);
    113		/* post-ack level interrupts */
    114		ack = bits & ~IIC_ISR_EDGE_MASK;
    115		if (ack)
    116			out_be64(&node_iic->iic_is, ack);
    117	}
    118	chip->irq_eoi(&desc->irq_data);
    119}
    120
    121
    122static struct irq_chip iic_ioexc_chip = {
    123	.name = "CELL-IOEX",
    124	.irq_mask = iic_mask,
    125	.irq_unmask = iic_unmask,
    126	.irq_eoi = iic_ioexc_eoi,
    127};
    128
    129/* Get an IRQ number from the pending state register of the IIC */
    130static unsigned int iic_get_irq(void)
    131{
    132	struct cbe_iic_pending_bits pending;
    133	struct iic *iic;
    134	unsigned int virq;
    135
    136	iic = this_cpu_ptr(&cpu_iic);
    137	*(unsigned long *) &pending =
    138		in_be64((u64 __iomem *) &iic->regs->pending_destr);
    139	if (!(pending.flags & CBE_IIC_IRQ_VALID))
    140		return 0;
    141	virq = irq_linear_revmap(iic_host, iic_pending_to_hwnum(pending));
    142	if (!virq)
    143		return 0;
    144	iic->eoi_stack[++iic->eoi_ptr] = pending.prio;
    145	BUG_ON(iic->eoi_ptr > 15);
    146	return virq;
    147}
    148
    149void iic_setup_cpu(void)
    150{
    151	out_be64(&this_cpu_ptr(&cpu_iic)->regs->prio, 0xff);
    152}
    153
    154u8 iic_get_target_id(int cpu)
    155{
    156	return per_cpu(cpu_iic, cpu).target_id;
    157}
    158
    159EXPORT_SYMBOL_GPL(iic_get_target_id);
    160
    161#ifdef CONFIG_SMP
    162
    163/* Use the highest interrupt priorities for IPI */
    164static inline int iic_msg_to_irq(int msg)
    165{
    166	return IIC_IRQ_TYPE_IPI + 0xf - msg;
    167}
    168
    169void iic_message_pass(int cpu, int msg)
    170{
    171	out_be64(&per_cpu(cpu_iic, cpu).regs->generate, (0xf - msg) << 4);
    172}
    173
    174static void iic_request_ipi(int msg)
    175{
    176	int virq;
    177
    178	virq = irq_create_mapping(iic_host, iic_msg_to_irq(msg));
    179	if (!virq) {
    180		printk(KERN_ERR
    181		       "iic: failed to map IPI %s\n", smp_ipi_name[msg]);
    182		return;
    183	}
    184
    185	/*
    186	 * If smp_request_message_ipi encounters an error it will notify
    187	 * the error.  If a message is not needed it will return non-zero.
    188	 */
    189	if (smp_request_message_ipi(virq, msg))
    190		irq_dispose_mapping(virq);
    191}
    192
    193void iic_request_IPIs(void)
    194{
    195	iic_request_ipi(PPC_MSG_CALL_FUNCTION);
    196	iic_request_ipi(PPC_MSG_RESCHEDULE);
    197	iic_request_ipi(PPC_MSG_TICK_BROADCAST);
    198	iic_request_ipi(PPC_MSG_NMI_IPI);
    199}
    200
    201#endif /* CONFIG_SMP */
    202
    203
    204static int iic_host_match(struct irq_domain *h, struct device_node *node,
    205			  enum irq_domain_bus_token bus_token)
    206{
    207	return of_device_is_compatible(node,
    208				    "IBM,CBEA-Internal-Interrupt-Controller");
    209}
    210
    211static int iic_host_map(struct irq_domain *h, unsigned int virq,
    212			irq_hw_number_t hw)
    213{
    214	switch (hw & IIC_IRQ_TYPE_MASK) {
    215	case IIC_IRQ_TYPE_IPI:
    216		irq_set_chip_and_handler(virq, &iic_chip, handle_percpu_irq);
    217		break;
    218	case IIC_IRQ_TYPE_IOEXC:
    219		irq_set_chip_and_handler(virq, &iic_ioexc_chip,
    220					 handle_edge_eoi_irq);
    221		break;
    222	default:
    223		irq_set_chip_and_handler(virq, &iic_chip, handle_edge_eoi_irq);
    224	}
    225	return 0;
    226}
    227
    228static int iic_host_xlate(struct irq_domain *h, struct device_node *ct,
    229			   const u32 *intspec, unsigned int intsize,
    230			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
    231
    232{
    233	unsigned int node, ext, unit, class;
    234	const u32 *val;
    235
    236	if (!of_device_is_compatible(ct,
    237				     "IBM,CBEA-Internal-Interrupt-Controller"))
    238		return -ENODEV;
    239	if (intsize != 1)
    240		return -ENODEV;
    241	val = of_get_property(ct, "#interrupt-cells", NULL);
    242	if (val == NULL || *val != 1)
    243		return -ENODEV;
    244
    245	node = intspec[0] >> 24;
    246	ext = (intspec[0] >> 16) & 0xff;
    247	class = (intspec[0] >> 8) & 0xff;
    248	unit = intspec[0] & 0xff;
    249
    250	/* Check if node is in supported range */
    251	if (node > 1)
    252		return -EINVAL;
    253
    254	/* Build up interrupt number, special case for IO exceptions */
    255	*out_hwirq = (node << IIC_IRQ_NODE_SHIFT);
    256	if (unit == IIC_UNIT_IIC && class == 1)
    257		*out_hwirq |= IIC_IRQ_TYPE_IOEXC | ext;
    258	else
    259		*out_hwirq |= IIC_IRQ_TYPE_NORMAL |
    260			(class << IIC_IRQ_CLASS_SHIFT) | unit;
    261
    262	/* Dummy flags, ignored by iic code */
    263	*out_flags = IRQ_TYPE_EDGE_RISING;
    264
    265	return 0;
    266}
    267
    268static const struct irq_domain_ops iic_host_ops = {
    269	.match = iic_host_match,
    270	.map = iic_host_map,
    271	.xlate = iic_host_xlate,
    272};
    273
    274static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
    275				struct device_node *node)
    276{
    277	/* XXX FIXME: should locate the linux CPU number from the HW cpu
    278	 * number properly. We are lucky for now
    279	 */
    280	struct iic *iic = &per_cpu(cpu_iic, hw_cpu);
    281
    282	iic->regs = ioremap(addr, sizeof(struct cbe_iic_thread_regs));
    283	BUG_ON(iic->regs == NULL);
    284
    285	iic->target_id = ((hw_cpu & 2) << 3) | ((hw_cpu & 1) ? 0xf : 0xe);
    286	iic->eoi_stack[0] = 0xff;
    287	iic->node = of_node_get(node);
    288	out_be64(&iic->regs->prio, 0);
    289
    290	printk(KERN_INFO "IIC for CPU %d target id 0x%x : %pOF\n",
    291	       hw_cpu, iic->target_id, node);
    292}
    293
    294static int __init setup_iic(void)
    295{
    296	struct device_node *dn;
    297	struct resource r0, r1;
    298	unsigned int node, cascade, found = 0;
    299	struct cbe_iic_regs __iomem *node_iic;
    300	const u32 *np;
    301
    302	for_each_node_by_name(dn, "interrupt-controller") {
    303		if (!of_device_is_compatible(dn,
    304				     "IBM,CBEA-Internal-Interrupt-Controller"))
    305			continue;
    306		np = of_get_property(dn, "ibm,interrupt-server-ranges", NULL);
    307		if (np == NULL) {
    308			printk(KERN_WARNING "IIC: CPU association not found\n");
    309			of_node_put(dn);
    310			return -ENODEV;
    311		}
    312		if (of_address_to_resource(dn, 0, &r0) ||
    313		    of_address_to_resource(dn, 1, &r1)) {
    314			printk(KERN_WARNING "IIC: Can't resolve addresses\n");
    315			of_node_put(dn);
    316			return -ENODEV;
    317		}
    318		found++;
    319		init_one_iic(np[0], r0.start, dn);
    320		init_one_iic(np[1], r1.start, dn);
    321
    322		/* Setup cascade for IO exceptions. XXX cleanup tricks to get
    323		 * node vs CPU etc...
    324		 * Note that we configure the IIC_IRR here with a hard coded
    325		 * priority of 1. We might want to improve that later.
    326		 */
    327		node = np[0] >> 1;
    328		node_iic = cbe_get_cpu_iic_regs(np[0]);
    329		cascade = node << IIC_IRQ_NODE_SHIFT;
    330		cascade |= 1 << IIC_IRQ_CLASS_SHIFT;
    331		cascade |= IIC_UNIT_IIC;
    332		cascade = irq_create_mapping(iic_host, cascade);
    333		if (!cascade)
    334			continue;
    335		/*
    336		 * irq_data is a generic pointer that gets passed back
    337		 * to us later, so the forced cast is fine.
    338		 */
    339		irq_set_handler_data(cascade, (void __force *)node_iic);
    340		irq_set_chained_handler(cascade, iic_ioexc_cascade);
    341		out_be64(&node_iic->iic_ir,
    342			 (1 << 12)		/* priority */ |
    343			 (node << 4)		/* dest node */ |
    344			 IIC_UNIT_THREAD_0	/* route them to thread 0 */);
    345		/* Flush pending (make sure it triggers if there is
    346		 * anything pending
    347		 */
    348		out_be64(&node_iic->iic_is, 0xfffffffffffffffful);
    349	}
    350
    351	if (found)
    352		return 0;
    353	else
    354		return -ENODEV;
    355}
    356
    357void __init iic_init_IRQ(void)
    358{
    359	/* Setup an irq host data structure */
    360	iic_host = irq_domain_add_linear(NULL, IIC_SOURCE_COUNT, &iic_host_ops,
    361					 NULL);
    362	BUG_ON(iic_host == NULL);
    363	irq_set_default_host(iic_host);
    364
    365	/* Discover and initialize iics */
    366	if (setup_iic() < 0)
    367		panic("IIC: Failed to initialize !\n");
    368
    369	/* Set master interrupt handling function */
    370	ppc_md.get_irq = iic_get_irq;
    371
    372	/* Enable on current CPU */
    373	iic_setup_cpu();
    374}
    375
    376void iic_set_interrupt_routing(int cpu, int thread, int priority)
    377{
    378	struct cbe_iic_regs __iomem *iic_regs = cbe_get_cpu_iic_regs(cpu);
    379	u64 iic_ir = 0;
    380	int node = cpu >> 1;
    381
    382	/* Set which node and thread will handle the next interrupt */
    383	iic_ir |= CBE_IIC_IR_PRIO(priority) |
    384		  CBE_IIC_IR_DEST_NODE(node);
    385	if (thread == 0)
    386		iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_0);
    387	else
    388		iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_1);
    389	out_be64(&iic_regs->iic_ir, iic_ir);
    390}