/*
* Copyright 2012 Michael Ellerman, IBM Corporation.
* Copyright 2012 Benjamin Herrenschmidt, IBM Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/kvm_host.h>
#include <linux/err.h>
#include <linux/gfp.h>
#include <linux/anon_inodes.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <asm/kvm_book3s.h>
#include <asm/kvm_ppc.h>
#include <asm/hvcall.h>
#include <asm/xics.h>
#include <asm/debug.h>
#include <asm/time.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include "book3s_xics.h"
#if 1
#define XICS_DBG(fmt...) do { } while (0)
#else
#define XICS_DBG(fmt...) trace_printk(fmt)
#endif
#define ENABLE_REALMODE true
#define DEBUG_REALMODE false
/*
* LOCKING
* =======
*
* Each ICS has a spin lock protecting the information about the IRQ
* sources and avoiding simultaneous deliveries if the same interrupt.
*
* ICP operations are done via a single compare & swap transaction
* (most ICP state fits in the union kvmppc_icp_state)
*/
/*
* TODO
* ====
*
* - To speed up resends, keep a bitmap of "resend" set bits in the
* ICS
*
* - Speed up server# -> ICP lookup (array ? hash table ?)
*
* - Make ICS lockless as well, or at least a per-interrupt lock or hashed
* locks array to improve scalability
*/
/* -- ICS routines -- */
static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
u32 new_irq);
/*
* Return value ideally indicates how the interrupt was handled, but no
* callers look at it (given that we don't implement KVM_IRQ_LINE_STATUS),
* so just return 0.
*/
static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level)
{
struct ics_irq_state *state;
struct kvmppc_ics *ics;
u16 src;
XICS_DBG("ics deliver %#x (level: %d)\n", irq, level);
ics = kvmppc_xics_find_ics(xics, irq, &src);
if (!ics) {
XICS_DBG("ics_deliver_irq: IRQ 0x%06x not found !\n", irq);
return -EINVAL;
}
state = &ics->irq_state[src];