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 (19512B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  PS3 interrupt routines.
      4 *
      5 *  Copyright (C) 2006 Sony Computer Entertainment Inc.
      6 *  Copyright 2006 Sony Corp.
      7 */
      8
      9#include <linux/kernel.h>
     10#include <linux/export.h>
     11#include <linux/irq.h>
     12#include <linux/irqdomain.h>
     13
     14#include <asm/machdep.h>
     15#include <asm/udbg.h>
     16#include <asm/lv1call.h>
     17#include <asm/smp.h>
     18
     19#include "platform.h"
     20
     21#if defined(DEBUG)
     22#define DBG udbg_printf
     23#define FAIL udbg_printf
     24#else
     25#define DBG pr_devel
     26#define FAIL pr_debug
     27#endif
     28
     29/**
     30 * struct ps3_bmp - a per cpu irq status and mask bitmap structure
     31 * @status: 256 bit status bitmap indexed by plug
     32 * @unused_1: Alignment
     33 * @mask: 256 bit mask bitmap indexed by plug
     34 * @unused_2: Alignment
     35 *
     36 * The HV maintains per SMT thread mappings of HV outlet to HV plug on
     37 * behalf of the guest.  These mappings are implemented as 256 bit guest
     38 * supplied bitmaps indexed by plug number.  The addresses of the bitmaps
     39 * are registered with the HV through lv1_configure_irq_state_bitmap().
     40 * The HV requires that the 512 bits of status + mask not cross a page
     41 * boundary.  PS3_BMP_MINALIGN is used to define this minimal 64 byte
     42 * alignment.
     43 *
     44 * The HV supports 256 plugs per thread, assigned as {0..255}, for a total
     45 * of 512 plugs supported on a processor.  To simplify the logic this
     46 * implementation equates HV plug value to Linux virq value, constrains each
     47 * interrupt to have a system wide unique plug number, and limits the range
     48 * of the plug values to map into the first dword of the bitmaps.  This
     49 * gives a usable range of plug values of  {NR_IRQS_LEGACY..63}.  Note
     50 * that there is no constraint on how many in this set an individual thread
     51 * can acquire.
     52 *
     53 * The mask is declared as unsigned long so we can use set/clear_bit on it.
     54 */
     55
     56#define PS3_BMP_MINALIGN 64
     57
     58struct ps3_bmp {
     59	struct {
     60		u64 status;
     61		u64 unused_1[3];
     62		unsigned long mask;
     63		u64 unused_2[3];
     64	};
     65};
     66
     67/**
     68 * struct ps3_private - a per cpu data structure
     69 * @bmp: ps3_bmp structure
     70 * @bmp_lock: Synchronize access to bmp.
     71 * @ipi_debug_brk_mask: Mask for debug break IPIs
     72 * @ppe_id: HV logical_ppe_id
     73 * @thread_id: HV thread_id
     74 * @ipi_mask: Mask of IPI virqs
     75 */
     76
     77struct ps3_private {
     78	struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
     79	spinlock_t bmp_lock;
     80	u64 ppe_id;
     81	u64 thread_id;
     82	unsigned long ipi_debug_brk_mask;
     83	unsigned long ipi_mask;
     84};
     85
     86static DEFINE_PER_CPU(struct ps3_private, ps3_private);
     87
     88/**
     89 * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp.
     90 * @virq: The assigned Linux virq.
     91 *
     92 * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
     93 */
     94
     95static void ps3_chip_mask(struct irq_data *d)
     96{
     97	struct ps3_private *pd = irq_data_get_irq_chip_data(d);
     98	unsigned long flags;
     99
    100	DBG("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
    101		pd->thread_id, d->irq);
    102
    103	local_irq_save(flags);
    104	clear_bit(63 - d->irq, &pd->bmp.mask);
    105	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
    106	local_irq_restore(flags);
    107}
    108
    109/**
    110 * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp.
    111 * @virq: The assigned Linux virq.
    112 *
    113 * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
    114 */
    115
    116static void ps3_chip_unmask(struct irq_data *d)
    117{
    118	struct ps3_private *pd = irq_data_get_irq_chip_data(d);
    119	unsigned long flags;
    120
    121	DBG("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
    122		pd->thread_id, d->irq);
    123
    124	local_irq_save(flags);
    125	set_bit(63 - d->irq, &pd->bmp.mask);
    126	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
    127	local_irq_restore(flags);
    128}
    129
    130/**
    131 * ps3_chip_eoi - HV end-of-interrupt.
    132 * @virq: The assigned Linux virq.
    133 *
    134 * Calls lv1_end_of_interrupt_ext().
    135 */
    136
    137static void ps3_chip_eoi(struct irq_data *d)
    138{
    139	const struct ps3_private *pd = irq_data_get_irq_chip_data(d);
    140
    141	/* non-IPIs are EOIed here. */
    142
    143	if (!test_bit(63 - d->irq, &pd->ipi_mask))
    144		lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
    145}
    146
    147/**
    148 * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip.
    149 */
    150
    151static struct irq_chip ps3_irq_chip = {
    152	.name = "ps3",
    153	.irq_mask = ps3_chip_mask,
    154	.irq_unmask = ps3_chip_unmask,
    155	.irq_eoi = ps3_chip_eoi,
    156};
    157
    158/**
    159 * ps3_virq_setup - virq related setup.
    160 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
    161 * serviced on.
    162 * @outlet: The HV outlet from the various create outlet routines.
    163 * @virq: The assigned Linux virq.
    164 *
    165 * Calls irq_create_mapping() to get a virq and sets the chip data to
    166 * ps3_private data.
    167 */
    168
    169static int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
    170			  unsigned int *virq)
    171{
    172	int result;
    173	struct ps3_private *pd;
    174
    175	/* This defines the default interrupt distribution policy. */
    176
    177	if (cpu == PS3_BINDING_CPU_ANY)
    178		cpu = 0;
    179
    180	pd = &per_cpu(ps3_private, cpu);
    181
    182	*virq = irq_create_mapping(NULL, outlet);
    183
    184	if (!*virq) {
    185		FAIL("%s:%d: irq_create_mapping failed: outlet %lu\n",
    186			__func__, __LINE__, outlet);
    187		result = -ENOMEM;
    188		goto fail_create;
    189	}
    190
    191	DBG("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__,
    192		outlet, cpu, *virq);
    193
    194	result = irq_set_chip_data(*virq, pd);
    195
    196	if (result) {
    197		FAIL("%s:%d: irq_set_chip_data failed\n",
    198			__func__, __LINE__);
    199		goto fail_set;
    200	}
    201
    202	ps3_chip_mask(irq_get_irq_data(*virq));
    203
    204	return result;
    205
    206fail_set:
    207	irq_dispose_mapping(*virq);
    208fail_create:
    209	return result;
    210}
    211
    212/**
    213 * ps3_virq_destroy - virq related teardown.
    214 * @virq: The assigned Linux virq.
    215 *
    216 * Clears chip data and calls irq_dispose_mapping() for the virq.
    217 */
    218
    219static int ps3_virq_destroy(unsigned int virq)
    220{
    221	const struct ps3_private *pd = irq_get_chip_data(virq);
    222
    223	DBG("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
    224		__LINE__, pd->ppe_id, pd->thread_id, virq);
    225
    226	irq_set_chip_data(virq, NULL);
    227	irq_dispose_mapping(virq);
    228
    229	DBG("%s:%d <-\n", __func__, __LINE__);
    230	return 0;
    231}
    232
    233/**
    234 * ps3_irq_plug_setup - Generic outlet and virq related setup.
    235 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
    236 * serviced on.
    237 * @outlet: The HV outlet from the various create outlet routines.
    238 * @virq: The assigned Linux virq.
    239 *
    240 * Sets up virq and connects the irq plug.
    241 */
    242
    243int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
    244	unsigned int *virq)
    245{
    246	int result;
    247	struct ps3_private *pd;
    248
    249	result = ps3_virq_setup(cpu, outlet, virq);
    250
    251	if (result) {
    252		FAIL("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__);
    253		goto fail_setup;
    254	}
    255
    256	pd = irq_get_chip_data(*virq);
    257
    258	/* Binds outlet to cpu + virq. */
    259
    260	result = lv1_connect_irq_plug_ext(pd->ppe_id, pd->thread_id, *virq,
    261		outlet, 0);
    262
    263	if (result) {
    264		FAIL("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
    265		__func__, __LINE__, ps3_result(result));
    266		result = -EPERM;
    267		goto fail_connect;
    268	}
    269
    270	return result;
    271
    272fail_connect:
    273	ps3_virq_destroy(*virq);
    274fail_setup:
    275	return result;
    276}
    277EXPORT_SYMBOL_GPL(ps3_irq_plug_setup);
    278
    279/**
    280 * ps3_irq_plug_destroy - Generic outlet and virq related teardown.
    281 * @virq: The assigned Linux virq.
    282 *
    283 * Disconnects the irq plug and tears down virq.
    284 * Do not call for system bus event interrupts setup with
    285 * ps3_sb_event_receive_port_setup().
    286 */
    287
    288int ps3_irq_plug_destroy(unsigned int virq)
    289{
    290	int result;
    291	const struct ps3_private *pd = irq_get_chip_data(virq);
    292
    293	DBG("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
    294		__LINE__, pd->ppe_id, pd->thread_id, virq);
    295
    296	ps3_chip_mask(irq_get_irq_data(virq));
    297
    298	result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq);
    299
    300	if (result)
    301		FAIL("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
    302		__func__, __LINE__, ps3_result(result));
    303
    304	ps3_virq_destroy(virq);
    305
    306	return result;
    307}
    308EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy);
    309
    310/**
    311 * ps3_event_receive_port_setup - Setup an event receive port.
    312 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
    313 * serviced on.
    314 * @virq: The assigned Linux virq.
    315 *
    316 * The virq can be used with lv1_connect_interrupt_event_receive_port() to
    317 * arrange to receive interrupts from system-bus devices, or with
    318 * ps3_send_event_locally() to signal events.
    319 */
    320
    321int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq)
    322{
    323	int result;
    324	u64 outlet;
    325
    326	result = lv1_construct_event_receive_port(&outlet);
    327
    328	if (result) {
    329		FAIL("%s:%d: lv1_construct_event_receive_port failed: %s\n",
    330			__func__, __LINE__, ps3_result(result));
    331		*virq = 0;
    332		return result;
    333	}
    334
    335	result = ps3_irq_plug_setup(cpu, outlet, virq);
    336	BUG_ON(result);
    337
    338	return result;
    339}
    340EXPORT_SYMBOL_GPL(ps3_event_receive_port_setup);
    341
    342/**
    343 * ps3_event_receive_port_destroy - Destroy an event receive port.
    344 * @virq: The assigned Linux virq.
    345 *
    346 * Since ps3_event_receive_port_destroy destroys the receive port outlet,
    347 * SB devices need to call disconnect_interrupt_event_receive_port() before
    348 * this.
    349 */
    350
    351int ps3_event_receive_port_destroy(unsigned int virq)
    352{
    353	int result;
    354
    355	DBG(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
    356
    357	ps3_chip_mask(irq_get_irq_data(virq));
    358
    359	result = lv1_destruct_event_receive_port(virq_to_hw(virq));
    360
    361	if (result)
    362		FAIL("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
    363			__func__, __LINE__, ps3_result(result));
    364
    365	/*
    366	 * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu()
    367	 * calls from interrupt context (smp_call_function) when kexecing.
    368	 */
    369
    370	DBG(" <- %s:%d\n", __func__, __LINE__);
    371	return result;
    372}
    373
    374int ps3_send_event_locally(unsigned int virq)
    375{
    376	return lv1_send_event_locally(virq_to_hw(virq));
    377}
    378
    379/**
    380 * ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
    381 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
    382 * serviced on.
    383 * @dev: The system bus device instance.
    384 * @virq: The assigned Linux virq.
    385 *
    386 * An event irq represents a virtual device interrupt.  The interrupt_id
    387 * coresponds to the software interrupt number.
    388 */
    389
    390int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
    391	enum ps3_cpu_binding cpu, unsigned int *virq)
    392{
    393	/* this should go in system-bus.c */
    394
    395	int result;
    396
    397	result = ps3_event_receive_port_setup(cpu, virq);
    398
    399	if (result)
    400		return result;
    401
    402	result = lv1_connect_interrupt_event_receive_port(dev->bus_id,
    403		dev->dev_id, virq_to_hw(*virq), dev->interrupt_id);
    404
    405	if (result) {
    406		FAIL("%s:%d: lv1_connect_interrupt_event_receive_port"
    407			" failed: %s\n", __func__, __LINE__,
    408			ps3_result(result));
    409		ps3_event_receive_port_destroy(*virq);
    410		*virq = 0;
    411		return result;
    412	}
    413
    414	DBG("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
    415		dev->interrupt_id, *virq);
    416
    417	return 0;
    418}
    419EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
    420
    421int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
    422	unsigned int virq)
    423{
    424	/* this should go in system-bus.c */
    425
    426	int result;
    427
    428	DBG(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
    429		dev->interrupt_id, virq);
    430
    431	result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id,
    432		dev->dev_id, virq_to_hw(virq), dev->interrupt_id);
    433
    434	if (result)
    435		FAIL("%s:%d: lv1_disconnect_interrupt_event_receive_port"
    436			" failed: %s\n", __func__, __LINE__,
    437			ps3_result(result));
    438
    439	result = ps3_event_receive_port_destroy(virq);
    440	BUG_ON(result);
    441
    442	/*
    443	 * ps3_event_receive_port_destroy() destroys the IRQ plug,
    444	 * so don't call ps3_irq_plug_destroy() here.
    445	 */
    446
    447	result = ps3_virq_destroy(virq);
    448	BUG_ON(result);
    449
    450	DBG(" <- %s:%d\n", __func__, __LINE__);
    451	return result;
    452}
    453EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy);
    454
    455/**
    456 * ps3_io_irq_setup - Setup a system bus io irq.
    457 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
    458 * serviced on.
    459 * @interrupt_id: The device interrupt id read from the system repository.
    460 * @virq: The assigned Linux virq.
    461 *
    462 * An io irq represents a non-virtualized device interrupt.  interrupt_id
    463 * coresponds to the interrupt number of the interrupt controller.
    464 */
    465
    466int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
    467	unsigned int *virq)
    468{
    469	int result;
    470	u64 outlet;
    471
    472	result = lv1_construct_io_irq_outlet(interrupt_id, &outlet);
    473
    474	if (result) {
    475		FAIL("%s:%d: lv1_construct_io_irq_outlet failed: %s\n",
    476			__func__, __LINE__, ps3_result(result));
    477		return result;
    478	}
    479
    480	result = ps3_irq_plug_setup(cpu, outlet, virq);
    481	BUG_ON(result);
    482
    483	return result;
    484}
    485EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
    486
    487int ps3_io_irq_destroy(unsigned int virq)
    488{
    489	int result;
    490	unsigned long outlet = virq_to_hw(virq);
    491
    492	ps3_chip_mask(irq_get_irq_data(virq));
    493
    494	/*
    495	 * lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
    496	 * so call ps3_irq_plug_destroy() first.
    497	 */
    498
    499	result = ps3_irq_plug_destroy(virq);
    500	BUG_ON(result);
    501
    502	result = lv1_destruct_io_irq_outlet(outlet);
    503
    504	if (result)
    505		FAIL("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
    506			__func__, __LINE__, ps3_result(result));
    507
    508	return result;
    509}
    510EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
    511
    512/**
    513 * ps3_vuart_irq_setup - Setup the system virtual uart virq.
    514 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
    515 * serviced on.
    516 * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap.
    517 * @virq: The assigned Linux virq.
    518 *
    519 * The system supports only a single virtual uart, so multiple calls without
    520 * freeing the interrupt will return a wrong state error.
    521 */
    522
    523int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
    524	unsigned int *virq)
    525{
    526	int result;
    527	u64 outlet;
    528	u64 lpar_addr;
    529
    530	BUG_ON(!is_kernel_addr((u64)virt_addr_bmp));
    531
    532	lpar_addr = ps3_mm_phys_to_lpar(__pa(virt_addr_bmp));
    533
    534	result = lv1_configure_virtual_uart_irq(lpar_addr, &outlet);
    535
    536	if (result) {
    537		FAIL("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n",
    538			__func__, __LINE__, ps3_result(result));
    539		return result;
    540	}
    541
    542	result = ps3_irq_plug_setup(cpu, outlet, virq);
    543	BUG_ON(result);
    544
    545	return result;
    546}
    547EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup);
    548
    549int ps3_vuart_irq_destroy(unsigned int virq)
    550{
    551	int result;
    552
    553	ps3_chip_mask(irq_get_irq_data(virq));
    554	result = lv1_deconfigure_virtual_uart_irq();
    555
    556	if (result) {
    557		FAIL("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n",
    558			__func__, __LINE__, ps3_result(result));
    559		return result;
    560	}
    561
    562	result = ps3_irq_plug_destroy(virq);
    563	BUG_ON(result);
    564
    565	return result;
    566}
    567EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy);
    568
    569/**
    570 * ps3_spe_irq_setup - Setup an spe virq.
    571 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
    572 * serviced on.
    573 * @spe_id: The spe_id returned from lv1_construct_logical_spe().
    574 * @class: The spe interrupt class {0,1,2}.
    575 * @virq: The assigned Linux virq.
    576 *
    577 */
    578
    579int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
    580	unsigned int class, unsigned int *virq)
    581{
    582	int result;
    583	u64 outlet;
    584
    585	BUG_ON(class > 2);
    586
    587	result = lv1_get_spe_irq_outlet(spe_id, class, &outlet);
    588
    589	if (result) {
    590		FAIL("%s:%d: lv1_get_spe_irq_outlet failed: %s\n",
    591			__func__, __LINE__, ps3_result(result));
    592		return result;
    593	}
    594
    595	result = ps3_irq_plug_setup(cpu, outlet, virq);
    596	BUG_ON(result);
    597
    598	return result;
    599}
    600
    601int ps3_spe_irq_destroy(unsigned int virq)
    602{
    603	int result;
    604
    605	ps3_chip_mask(irq_get_irq_data(virq));
    606
    607	result = ps3_irq_plug_destroy(virq);
    608	BUG_ON(result);
    609
    610	return result;
    611}
    612
    613
    614#define PS3_INVALID_OUTLET ((irq_hw_number_t)-1)
    615#define PS3_PLUG_MAX 63
    616
    617#if defined(DEBUG)
    618static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu,
    619	const char* func, int line)
    620{
    621	pr_debug("%s:%d: %s %u {%04llx_%04llx_%04llx_%04llx}\n",
    622		func, line, header, cpu,
    623		*p >> 48, (*p >> 32) & 0xffff, (*p >> 16) & 0xffff,
    624		*p & 0xffff);
    625}
    626
    627static void __maybe_unused _dump_256_bmp(const char *header,
    628	const u64 *p, unsigned cpu, const char* func, int line)
    629{
    630	pr_debug("%s:%d: %s %u {%016llx:%016llx:%016llx:%016llx}\n",
    631		func, line, header, cpu, p[0], p[1], p[2], p[3]);
    632}
    633
    634#define dump_bmp(_x) _dump_bmp(_x, __func__, __LINE__)
    635static void _dump_bmp(struct ps3_private* pd, const char* func, int line)
    636{
    637	unsigned long flags;
    638
    639	spin_lock_irqsave(&pd->bmp_lock, flags);
    640	_dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line);
    641	_dump_64_bmp("mask", (u64*)&pd->bmp.mask, pd->thread_id, func, line);
    642	spin_unlock_irqrestore(&pd->bmp_lock, flags);
    643}
    644
    645#define dump_mask(_x) _dump_mask(_x, __func__, __LINE__)
    646static void __maybe_unused _dump_mask(struct ps3_private *pd,
    647	const char* func, int line)
    648{
    649	unsigned long flags;
    650
    651	spin_lock_irqsave(&pd->bmp_lock, flags);
    652	_dump_64_bmp("mask", (u64*)&pd->bmp.mask, pd->thread_id, func, line);
    653	spin_unlock_irqrestore(&pd->bmp_lock, flags);
    654}
    655#else
    656static void dump_bmp(struct ps3_private* pd) {};
    657#endif /* defined(DEBUG) */
    658
    659static int ps3_host_map(struct irq_domain *h, unsigned int virq,
    660	irq_hw_number_t hwirq)
    661{
    662	DBG("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
    663		virq);
    664
    665	irq_set_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
    666
    667	return 0;
    668}
    669
    670static int ps3_host_match(struct irq_domain *h, struct device_node *np,
    671			  enum irq_domain_bus_token bus_token)
    672{
    673	/* Match all */
    674	return 1;
    675}
    676
    677static const struct irq_domain_ops ps3_host_ops = {
    678	.map = ps3_host_map,
    679	.match = ps3_host_match,
    680};
    681
    682void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
    683{
    684	struct ps3_private *pd = &per_cpu(ps3_private, cpu);
    685
    686	set_bit(63 - virq, &pd->ipi_debug_brk_mask);
    687
    688	DBG("%s:%d: cpu %u, virq %u, mask %lxh\n", __func__, __LINE__,
    689		cpu, virq, pd->ipi_debug_brk_mask);
    690}
    691
    692void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq)
    693{
    694	struct ps3_private *pd = &per_cpu(ps3_private, cpu);
    695
    696	set_bit(63 - virq, &pd->ipi_mask);
    697
    698	DBG("%s:%d: cpu %u, virq %u, ipi_mask %lxh\n", __func__, __LINE__,
    699		cpu, virq, pd->ipi_mask);
    700}
    701
    702static unsigned int ps3_get_irq(void)
    703{
    704	struct ps3_private *pd = this_cpu_ptr(&ps3_private);
    705	u64 x = (pd->bmp.status & pd->bmp.mask);
    706	unsigned int plug;
    707
    708	/* check for ipi break first to stop this cpu ASAP */
    709
    710	if (x & pd->ipi_debug_brk_mask)
    711		x &= pd->ipi_debug_brk_mask;
    712
    713	asm volatile("cntlzd %0,%1" : "=r" (plug) : "r" (x));
    714	plug &= 0x3f;
    715
    716	if (unlikely(!plug)) {
    717		DBG("%s:%d: no plug found: thread_id %llu\n", __func__,
    718			__LINE__, pd->thread_id);
    719		dump_bmp(&per_cpu(ps3_private, 0));
    720		dump_bmp(&per_cpu(ps3_private, 1));
    721		return 0;
    722	}
    723
    724#if defined(DEBUG)
    725	if (unlikely(plug < NR_IRQS_LEGACY || plug > PS3_PLUG_MAX)) {
    726		dump_bmp(&per_cpu(ps3_private, 0));
    727		dump_bmp(&per_cpu(ps3_private, 1));
    728		BUG();
    729	}
    730#endif
    731
    732	/* IPIs are EOIed here. */
    733
    734	if (test_bit(63 - plug, &pd->ipi_mask))
    735		lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, plug);
    736
    737	return plug;
    738}
    739
    740void __init ps3_init_IRQ(void)
    741{
    742	int result;
    743	unsigned cpu;
    744	struct irq_domain *host;
    745
    746	host = irq_domain_add_nomap(NULL, PS3_PLUG_MAX + 1, &ps3_host_ops, NULL);
    747	irq_set_default_host(host);
    748
    749	for_each_possible_cpu(cpu) {
    750		struct ps3_private *pd = &per_cpu(ps3_private, cpu);
    751
    752		lv1_get_logical_ppe_id(&pd->ppe_id);
    753		pd->thread_id = get_hard_smp_processor_id(cpu);
    754		spin_lock_init(&pd->bmp_lock);
    755
    756		DBG("%s:%d: ppe_id %llu, thread_id %llu, bmp %lxh\n",
    757			__func__, __LINE__, pd->ppe_id, pd->thread_id,
    758			ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
    759
    760		result = lv1_configure_irq_state_bitmap(pd->ppe_id,
    761			pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
    762
    763		if (result)
    764			FAIL("%s:%d: lv1_configure_irq_state_bitmap failed:"
    765				" %s\n", __func__, __LINE__,
    766				ps3_result(result));
    767	}
    768
    769	ppc_md.get_irq = ps3_get_irq;
    770}
    771
    772void ps3_shutdown_IRQ(int cpu)
    773{
    774	int result;
    775	u64 ppe_id;
    776	u64 thread_id = get_hard_smp_processor_id(cpu);
    777
    778	lv1_get_logical_ppe_id(&ppe_id);
    779	result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0);
    780
    781	DBG("%s:%d: lv1_configure_irq_state_bitmap (%llu:%llu/%d) %s\n", __func__,
    782		__LINE__, ppe_id, thread_id, cpu, ps3_result(result));
    783}