aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/xen/irq.h
blob: f2e62158ff0bedbb2db6bf2a1557e7045a34eb9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#ifndef __XEN_IRQ_H__
#define __XEN_IRQ_H__

#include <xen/cpumask.h>
#include <xen/rcupdate.h>
#include <xen/spinlock.h>
#include <xen/time.h>
#include <xen/list.h>
#include <asm/regs.h>
#include <asm/hardirq.h>

struct irqaction {
    void (*handler)(int, void *, struct cpu_user_regs *);
    const char *name;
    void *dev_id;
    bool_t free_on_release;
};

/*
 * IRQ line status.
 */
#define IRQ_INPROGRESS    (1u<<0) /* IRQ handler active - do not enter! */
#define IRQ_DISABLED      (1u<<1) /* IRQ disabled - do not enter! */
#define IRQ_PENDING       (1u<<2) /* IRQ pending - replay on enable */
#define IRQ_REPLAY        (1u<<3) /* IRQ has been replayed but not acked yet */
#define IRQ_GUEST         (1u<<4) /* IRQ is handled by guest OS(es) */
#define IRQ_MOVE_PENDING  (1u<<5) /* IRQ is migrating to another CPUs */
#define IRQ_PER_CPU       (1u<<6) /* IRQ is per CPU */
#define IRQ_GUEST_EOI_PENDING (1u<<7) /* IRQ was disabled, pending a guest EOI */

/* Special IRQ numbers. */
#define AUTO_ASSIGN_IRQ         (-1)
#define NEVER_ASSIGN_IRQ        (-2)
#define FREE_TO_ASSIGN_IRQ      (-3)

struct irq_desc;

/*
 * Interrupt controller descriptor. This is all we need
 * to describe about the low-level hardware. 
 */
struct hw_interrupt_type {
    const char *typename;
    unsigned int (*startup)(struct irq_desc *);
    void (*shutdown)(struct irq_desc *);
    void (*enable)(struct irq_desc *);
    void (*disable)(struct irq_desc *);
    void (*ack)(struct irq_desc *);
#ifdef CONFIG_X86
    void (*end)(struct irq_desc *, u8 vector);
#else
    void (*end)(struct irq_desc *);
#endif
    void (*set_affinity)(struct irq_desc *, const cpumask_t *);
};

typedef const struct hw_interrupt_type hw_irq_controller;

#include <asm/irq.h>

struct msi_desc;
/*
 * This is the "IRQ descriptor", which contains various information
 * about the irq, including what kind of hardware handling it has,
 * whether it is disabled etc etc.
 */
typedef struct irq_desc {
    unsigned int status;        /* IRQ status */
    hw_irq_controller *handler;
    struct msi_desc   *msi_desc;
    struct irqaction *action;   /* IRQ action list */
    int irq;
    spinlock_t lock;
    struct arch_irq_desc arch;
    cpumask_var_t affinity;

    /* irq ratelimit */
    s_time_t rl_quantum_start;
    unsigned int rl_cnt;
    struct list_head rl_link;
} __cacheline_aligned irq_desc_t;

#ifndef irq_to_desc
#define irq_to_desc(irq)    (&irq_desc[irq])
#endif

int init_one_irq_desc(struct irq_desc *);
int arch_init_one_irq_desc(struct irq_desc *);

#define irq_desc_initialized(desc) ((desc)->handler != NULL)

extern int setup_irq(unsigned int irq, struct irqaction *);
extern void release_irq(unsigned int irq);
extern int request_irq(unsigned int irq,
               void (*handler)(int, void *, struct cpu_user_regs *),
               const char * devname, void *dev_id);

extern hw_irq_controller no_irq_type;
extern void no_action(int cpl, void *dev_id, struct cpu_user_regs *regs);
extern unsigned int irq_startup_none(struct irq_desc *);
extern void irq_actor_none(struct irq_desc *);
#define irq_shutdown_none irq_actor_none
#define irq_disable_none irq_actor_none
#define irq_enable_none irq_actor_none

struct domain;
struct vcpu;

struct pirq {
    int pirq;
    u16 evtchn;
    bool_t masked;
    struct rcu_head rcu_head;
    struct arch_pirq arch;
};

#define pirq_info(d, p) ((struct pirq *)radix_tree_lookup(&(d)->pirq_tree, p))

/* Use this instead of pirq_info() if the structure may need allocating. */
extern struct pirq *pirq_get_info(struct domain *, int pirq);

#define pirq_field(d, p, f, def) ({ \
    const struct pirq *__pi = pirq_info(d, p); \
    __pi ? __pi->f : def; \
})
#define pirq_to_evtchn(d, pirq) pirq_field(d, pirq, evtchn, 0)
#define pirq_masked(d, pirq) pirq_field(d, pirq, masked, 0)

void pirq_cleanup_check(struct pirq *, struct domain *);

#define pirq_cleanup_check(pirq, d) \
    ((pirq)->evtchn ? pirq_cleanup_check(pirq, d) : (void)0)

extern void pirq_guest_eoi(struct pirq *);
extern void desc_guest_eoi(struct irq_desc *, struct pirq *);
extern int pirq_guest_unmask(struct domain *d);
extern int pirq_guest_bind(struct vcpu *, struct pirq *, int will_share);
extern void pirq_guest_unbind(struct domain *d, struct pirq *);
extern void pirq_set_affinity(struct domain *d, int irq, const cpumask_t *);
extern irq_desc_t *domain_spin_lock_irq_desc(
    struct domain *d, int irq, unsigned long *pflags);
extern irq_desc_t *pirq_spin_lock_irq_desc(
    const struct pirq *, unsigned long *pflags);

static inline void set_native_irq_info(unsigned int irq, const cpumask_t *mask)
{
    cpumask_copy(irq_to_desc(irq)->affinity, mask);
}

unsigned int set_desc_affinity(struct irq_desc *, const cpumask_t *);

#endif /* __XEN_IRQ_H__ */