/root/src/xen/xen/include/asm/hvm/irq.h
Line | Count | Source (jump to first uncovered line) |
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 | 0 | (((((dev)<<2) + ((dev)>>3) + (intx)) & 31) + 16) |
98 | | #define hvm_pci_intx_link(dev, intx) \ |
99 | 0 | (((dev) + (intx)) & 3) |
100 | 5.09M | #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 | 297 | #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 | 6 | #define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0 |
118 | 42 | #define _HVM_IRQ_DPCI_MACH_MSI_SHIFT 1 |
119 | 4.24k | #define _HVM_IRQ_DPCI_MAPPED_SHIFT 2 |
120 | 67 | #define _HVM_IRQ_DPCI_EOI_LATCH_SHIFT 3 |
121 | 6 | #define _HVM_IRQ_DPCI_GUEST_PCI_SHIFT 4 |
122 | 4.49k | #define _HVM_IRQ_DPCI_GUEST_MSI_SHIFT 5 |
123 | 374 | #define _HVM_IRQ_DPCI_IDENTITY_GSI_SHIFT 6 |
124 | 608 | #define _HVM_IRQ_DPCI_TRANSLATE_SHIFT 15 |
125 | 6 | #define HVM_IRQ_DPCI_MACH_PCI (1u << _HVM_IRQ_DPCI_MACH_PCI_SHIFT) |
126 | 42 | #define HVM_IRQ_DPCI_MACH_MSI (1u << _HVM_IRQ_DPCI_MACH_MSI_SHIFT) |
127 | 4.24k | #define HVM_IRQ_DPCI_MAPPED (1u << _HVM_IRQ_DPCI_MAPPED_SHIFT) |
128 | 67 | #define HVM_IRQ_DPCI_EOI_LATCH (1u << _HVM_IRQ_DPCI_EOI_LATCH_SHIFT) |
129 | 6 | #define HVM_IRQ_DPCI_GUEST_PCI (1u << _HVM_IRQ_DPCI_GUEST_PCI_SHIFT) |
130 | 4.49k | #define HVM_IRQ_DPCI_GUEST_MSI (1u << _HVM_IRQ_DPCI_GUEST_MSI_SHIFT) |
131 | 374 | #define HVM_IRQ_DPCI_IDENTITY_GSI (1u << _HVM_IRQ_DPCI_IDENTITY_GSI_SHIFT) |
132 | 608 | #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 | 0 | #define NR_ISAIRQS 16 |
150 | 0 | #define NR_LINK 4 |
151 | 0 | #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 | | /* Modify state of an ISA device's IRQ wire. */ |
191 | | void hvm_isa_irq_assert(struct domain *d, unsigned int isa_irq); |
192 | | void hvm_isa_irq_deassert(struct domain *d, unsigned int isa_irq); |
193 | | |
194 | | /* Modify state of GSIs. */ |
195 | | void hvm_gsi_assert(struct domain *d, unsigned int gsi); |
196 | | void hvm_gsi_deassert(struct domain *d, unsigned int gsi); |
197 | | |
198 | | int hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq); |
199 | | |
200 | | int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data); |
201 | | |
202 | | void hvm_maybe_deassert_evtchn_irq(void); |
203 | | void hvm_assert_evtchn_irq(struct vcpu *v); |
204 | | void hvm_set_callback_via(struct domain *d, uint64_t via); |
205 | | |
206 | | #endif /* __ASM_X86_HVM_IRQ_H__ */ |