1 /******************************************************************************
2 * irq.h
3 *
4 * Interrupt distribution and delivery logic.
5 *
6 * Copyright (c) 2006, K A Fraser, XenSource Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #ifndef __ASM_X86_HVM_IRQ_H__
22 #define __ASM_X86_HVM_IRQ_H__
23
24 #include <xen/timer.h>
25
26 #include <asm/hvm/hvm.h>
27 #include <asm/hvm/vpic.h>
28 #include <asm/hvm/vioapic.h>
29
30 struct hvm_irq {
31 /*
32 * Virtual interrupt wires for a single PCI bus.
33 * Indexed by: device*4 + INTx#.
34 */
35 struct hvm_hw_pci_irqs pci_intx;
36
37 /*
38 * Virtual interrupt wires for ISA devices.
39 * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
40 */
41 struct hvm_hw_isa_irqs isa_irq;
42
43 /*
44 * PCI-ISA interrupt router.
45 * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
46 * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
47 * The router provides a programmable mapping from each link to a GSI.
48 */
49 struct hvm_hw_pci_link pci_link;
50
51 /* Virtual interrupt and via-link for paravirtual platform driver. */
52 uint32_t callback_via_asserted;
53 union {
54 enum {
55 HVMIRQ_callback_none,
56 HVMIRQ_callback_gsi,
57 HVMIRQ_callback_pci_intx,
58 HVMIRQ_callback_vector
59 } callback_via_type;
60 };
61 union {
62 uint32_t gsi;
63 struct { uint8_t dev, intx; } pci;
64 uint32_t vector;
65 } callback_via;
66
67 /* Number of INTx wires asserting each PCI-ISA link. */
68 u8 pci_link_assert_count[4];
69
70 /*
71 * GSIs map onto PIC/IO-APIC in the usual way:
72 * 0-7: Master 8259 PIC, IO-APIC pins 0-7
73 * 8-15: Slave 8259 PIC, IO-APIC pins 8-15
74 * 16+ : IO-APIC pins 16+
75 */
76
77 /* Last VCPU that was delivered a LowestPrio interrupt. */
78 u8 round_robin_prev_vcpu;
79
80 struct hvm_irq_dpci *dpci;
81
82 /*
83 * Number of wires asserting each GSI.
84 *
85 * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space
86 * except ISA IRQ 0, which is connected to GSI 2.
87 * PCI links map into this space via the PCI-ISA bridge.
88 *
89 * GSIs 16+ are used only be PCI devices. The mapping from PCI device to
90 * GSI is as follows: ((device*4 + device/8 + INTx#) & 31) + 16
91 */
92 unsigned int nr_gsis;
93 u8 gsi_assert_count[];
94 };
95
96 #define hvm_pci_intx_gsi(dev, intx) \
97 (((((dev)<<2) + ((dev)>>3) + (intx)) & 31) + 16)
98 #define hvm_pci_intx_link(dev, intx) \
99 (((dev) + (intx)) & 3)
100 #define hvm_domain_irq(d) ((d)->arch.hvm.irq)
101 #define hvm_irq_size(cnt) offsetof(struct hvm_irq, gsi_assert_count[cnt])
102
103 #define hvm_isa_irq_to_gsi(isa_irq) ((isa_irq) ? : 2)
104
105 /* Check/Acknowledge next pending interrupt. */
106 struct hvm_intack hvm_vcpu_has_pending_irq(struct vcpu *v);
107 struct hvm_intack hvm_vcpu_ack_pending_irq(struct vcpu *v,
108 struct hvm_intack intack);
109
110 struct dev_intx_gsi_link {
111 struct list_head list;
112 uint8_t bus;
113 uint8_t device;
114 uint8_t intx;
115 };
116
117 #define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0
118 #define _HVM_IRQ_DPCI_MACH_MSI_SHIFT 1
119 #define _HVM_IRQ_DPCI_MAPPED_SHIFT 2
120 #define _HVM_IRQ_DPCI_EOI_LATCH_SHIFT 3
121 #define _HVM_IRQ_DPCI_GUEST_PCI_SHIFT 4
122 #define _HVM_IRQ_DPCI_GUEST_MSI_SHIFT 5
123 #define _HVM_IRQ_DPCI_IDENTITY_GSI_SHIFT 6
124 #define _HVM_IRQ_DPCI_NO_EOI_SHIFT 7
125 #define _HVM_IRQ_DPCI_TRANSLATE_SHIFT 15
126 #define HVM_IRQ_DPCI_MACH_PCI (1u << _HVM_IRQ_DPCI_MACH_PCI_SHIFT)
127 #define HVM_IRQ_DPCI_MACH_MSI (1u << _HVM_IRQ_DPCI_MACH_MSI_SHIFT)
128 #define HVM_IRQ_DPCI_MAPPED (1u << _HVM_IRQ_DPCI_MAPPED_SHIFT)
129 #define HVM_IRQ_DPCI_EOI_LATCH (1u << _HVM_IRQ_DPCI_EOI_LATCH_SHIFT)
130 #define HVM_IRQ_DPCI_GUEST_PCI (1u << _HVM_IRQ_DPCI_GUEST_PCI_SHIFT)
131 #define HVM_IRQ_DPCI_GUEST_MSI (1u << _HVM_IRQ_DPCI_GUEST_MSI_SHIFT)
132 #define HVM_IRQ_DPCI_IDENTITY_GSI (1u << _HVM_IRQ_DPCI_IDENTITY_GSI_SHIFT)
133 #define HVM_IRQ_DPCI_NO_EOI (1u << _HVM_IRQ_DPCI_NO_EOI_SHIFT)
134 #define HVM_IRQ_DPCI_TRANSLATE (1u << _HVM_IRQ_DPCI_TRANSLATE_SHIFT)
135
136 struct hvm_gmsi_info {
137 uint32_t gvec;
138 uint32_t gflags;
139 int dest_vcpu_id; /* -1 :multi-dest, non-negative: dest_vcpu_id */
140 bool posted; /* directly deliver to guest via VT-d PI? */
141 };
142
143 struct hvm_girq_dpci_mapping {
144 struct list_head list;
145 uint8_t bus;
146 uint8_t device;
147 uint8_t intx;
148 uint8_t machine_gsi;
149 };
150
151 #define NR_ISAIRQS 16
152 #define NR_LINK 4
153 #define NR_HVM_DOMU_IRQS ARRAY_SIZE(((struct hvm_hw_vioapic *)0)->redirtbl)
154
155 /* Protected by domain's event_lock */
156 struct hvm_irq_dpci {
157 /* Guest IRQ to guest device/intx mapping. */
158 struct list_head girq[NR_HVM_DOMU_IRQS];
159 /* Record of mapped ISA IRQs */
160 DECLARE_BITMAP(isairq_map, NR_ISAIRQS);
161 /* Record of mapped Links */
162 uint8_t link_cnt[NR_LINK];
163 /* Clean up: Entry with a softirq invocation pending / in progress. */
164 struct hvm_pirq_dpci *pending_pirq_dpci;
165 };
166
167 /* Machine IRQ to guest device/intx mapping. */
168 struct hvm_pirq_dpci {
169 uint32_t flags;
170 unsigned int state;
171 bool masked;
172 uint16_t pending;
173 struct list_head digl_list;
174 struct domain *dom;
175 struct hvm_gmsi_info gmsi;
176 struct timer timer;
177 struct list_head softirq_list;
178 };
179
180 void pt_pirq_init(struct domain *, struct hvm_pirq_dpci *);
181 bool pt_pirq_cleanup_check(struct hvm_pirq_dpci *);
182 int pt_pirq_iterate(struct domain *d,
183 int (*cb)(struct domain *,
184 struct hvm_pirq_dpci *, void *arg),
185 void *arg);
186
187 #ifdef CONFIG_HVM
188 bool pt_pirq_softirq_active(struct hvm_pirq_dpci *);
189 #else
pt_pirq_softirq_active(struct hvm_pirq_dpci * dpci)190 static inline bool pt_pirq_softirq_active(struct hvm_pirq_dpci *dpci)
191 {
192 return false;
193 }
194 #endif
195
196 /* Modify state of a PCI INTx wire. */
197 void hvm_pci_intx_assert(struct domain *d, unsigned int device,
198 unsigned int intx);
199 void hvm_pci_intx_deassert(struct domain *d, unsigned int device,
200 unsigned int intx);
201
202 /*
203 * Modify state of an ISA device's IRQ wire. For some cases, we are
204 * interested in the interrupt vector of the irq, but once the irq_lock
205 * is released, the vector may be changed by others. get_vector() callback
206 * allows us to get the interrupt vector in the protection of irq_lock.
207 * For most cases, just set get_vector to NULL.
208 */
209 int hvm_isa_irq_assert(struct domain *d, unsigned int isa_irq,
210 int (*get_vector)(const struct domain *d,
211 unsigned int gsi));
212 void hvm_isa_irq_deassert(struct domain *d, unsigned int isa_irq);
213
214 /* Modify state of GSIs. */
215 void hvm_gsi_assert(struct domain *d, unsigned int gsi);
216 void hvm_gsi_deassert(struct domain *d, unsigned int gsi);
217
218 int hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
219
220 int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data);
221
222 /* Assert/deassert an IO APIC pin. */
223 int hvm_ioapic_assert(struct domain *d, unsigned int gsi, bool level);
224 void hvm_ioapic_deassert(struct domain *d, unsigned int gsi);
225
226 void hvm_maybe_deassert_evtchn_irq(void);
227 void hvm_assert_evtchn_irq(struct vcpu *v);
228 void hvm_set_callback_via(struct domain *d, uint64_t via);
229
230 struct pirq;
231 bool hvm_domain_use_pirq(const struct domain *, const struct pirq *);
232
233 #endif /* __ASM_X86_HVM_IRQ_H__ */
234