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