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_domain.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_TRANSLATE_SHIFT          15
125 #define HVM_IRQ_DPCI_MACH_PCI        (1u << _HVM_IRQ_DPCI_MACH_PCI_SHIFT)
126 #define HVM_IRQ_DPCI_MACH_MSI        (1u << _HVM_IRQ_DPCI_MACH_MSI_SHIFT)
127 #define HVM_IRQ_DPCI_MAPPED          (1u << _HVM_IRQ_DPCI_MAPPED_SHIFT)
128 #define HVM_IRQ_DPCI_EOI_LATCH       (1u << _HVM_IRQ_DPCI_EOI_LATCH_SHIFT)
129 #define HVM_IRQ_DPCI_GUEST_PCI       (1u << _HVM_IRQ_DPCI_GUEST_PCI_SHIFT)
130 #define HVM_IRQ_DPCI_GUEST_MSI       (1u << _HVM_IRQ_DPCI_GUEST_MSI_SHIFT)
131 #define HVM_IRQ_DPCI_IDENTITY_GSI    (1u << _HVM_IRQ_DPCI_IDENTITY_GSI_SHIFT)
132 #define HVM_IRQ_DPCI_TRANSLATE       (1u << _HVM_IRQ_DPCI_TRANSLATE_SHIFT)
133 
134 struct hvm_gmsi_info {
135     uint32_t gvec;
136     uint32_t gflags;
137     int dest_vcpu_id; /* -1 :multi-dest, non-negative: dest_vcpu_id */
138     bool posted; /* directly deliver to guest via VT-d PI? */
139 };
140 
141 struct hvm_girq_dpci_mapping {
142     struct list_head list;
143     uint8_t bus;
144     uint8_t device;
145     uint8_t intx;
146     uint8_t machine_gsi;
147 };
148 
149 #define NR_ISAIRQS  16
150 #define NR_LINK     4
151 #define NR_HVM_DOMU_IRQS ARRAY_SIZE(((struct hvm_hw_vioapic *)0)->redirtbl)
152 
153 /* Protected by domain's event_lock */
154 struct hvm_irq_dpci {
155     /* Guest IRQ to guest device/intx mapping. */
156     struct list_head girq[NR_HVM_DOMU_IRQS];
157     /* Record of mapped ISA IRQs */
158     DECLARE_BITMAP(isairq_map, NR_ISAIRQS);
159     /* Record of mapped Links */
160     uint8_t link_cnt[NR_LINK];
161 };
162 
163 /* Machine IRQ to guest device/intx mapping. */
164 struct hvm_pirq_dpci {
165     uint32_t flags;
166     unsigned int state;
167     bool masked;
168     uint16_t pending;
169     struct list_head digl_list;
170     struct domain *dom;
171     struct hvm_gmsi_info gmsi;
172     struct timer timer;
173     struct list_head softirq_list;
174 };
175 
176 void pt_pirq_init(struct domain *, struct hvm_pirq_dpci *);
177 bool pt_pirq_cleanup_check(struct hvm_pirq_dpci *);
178 int pt_pirq_iterate(struct domain *d,
179                     int (*cb)(struct domain *,
180                               struct hvm_pirq_dpci *, void *arg),
181                     void *arg);
182 
183 bool pt_pirq_softirq_active(struct hvm_pirq_dpci *);
184 /* Modify state of a PCI INTx wire. */
185 void hvm_pci_intx_assert(struct domain *d, unsigned int device,
186                          unsigned int intx);
187 void hvm_pci_intx_deassert(struct domain *d, unsigned int device,
188                            unsigned int intx);
189 
190 /*
191  * Modify state of an ISA device's IRQ wire. For some cases, we are
192  * interested in the interrupt vector of the irq, but once the irq_lock
193  * is released, the vector may be changed by others. get_vector() callback
194  * allows us to get the interrupt vector in the protection of irq_lock.
195  * For most cases, just set get_vector to NULL.
196  */
197 int hvm_isa_irq_assert(struct domain *d, unsigned int isa_irq,
198                        int (*get_vector)(const struct domain *d,
199                                          unsigned int gsi));
200 void hvm_isa_irq_deassert(struct domain *d, unsigned int isa_irq);
201 
202 /* Modify state of GSIs. */
203 void hvm_gsi_assert(struct domain *d, unsigned int gsi);
204 void hvm_gsi_deassert(struct domain *d, unsigned int gsi);
205 
206 int hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
207 
208 int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data);
209 
210 void hvm_maybe_deassert_evtchn_irq(void);
211 void hvm_assert_evtchn_irq(struct vcpu *v);
212 void hvm_set_callback_via(struct domain *d, uint64_t via);
213 
214 #endif /* __ASM_X86_HVM_IRQ_H__ */
215