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