1 /* 2 * Xen PCI Frontend Stub - puts some "dummy" functions in to the Linux 3 * x86 PCI core to support the Xen PCI Frontend 4 * 5 * Author: Ryan Wilson <hap9@epoch.ncsc.mil> 6 */ 7 #include <linux/module.h> 8 #include <linux/init.h> 9 #include <linux/pci.h> 10 #include <linux/acpi.h> 11 12 #include <linux/io.h> 13 #include <asm/io_apic.h> 14 #include <asm/pci_x86.h> 15 16 #include <asm/xen/hypervisor.h> 17 18 #include <xen/features.h> 19 #include <xen/events.h> 20 #include <asm/xen/pci.h> 21 22 #ifdef CONFIG_ACPI 23 static int xen_hvm_register_pirq(u32 gsi, int triggering) 24 { 25 int rc, irq; 26 struct physdev_map_pirq map_irq; 27 int shareable = 0; 28 char *name; 29 30 if (!xen_hvm_domain()) 31 return -1; 32 33 map_irq.domid = DOMID_SELF; 34 map_irq.type = MAP_PIRQ_TYPE_GSI; 35 map_irq.index = gsi; 36 map_irq.pirq = -1; 37 38 rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); 39 if (rc) { 40 printk(KERN_WARNING "xen map irq failed %d\n", rc); 41 return -1; 42 } 43 44 if (triggering == ACPI_EDGE_SENSITIVE) { 45 shareable = 0; 46 name = "ioapic-edge"; 47 } else { 48 shareable = 1; 49 name = "ioapic-level"; 50 } 51 52 irq = xen_map_pirq_gsi(map_irq.pirq, gsi, shareable, name); 53 54 printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq); 55 56 return irq; 57 } 58 59 static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, 60 int trigger, int polarity) 61 { 62 return xen_hvm_register_pirq(gsi, trigger); 63 } 64 #endif 65 66 #if defined(CONFIG_PCI_MSI) 67 #include <linux/msi.h> 68 #include <asm/msidef.h> 69 70 struct xen_pci_frontend_ops *xen_pci_frontend; 71 EXPORT_SYMBOL_GPL(xen_pci_frontend); 72 73 #define XEN_PIRQ_MSI_DATA (MSI_DATA_TRIGGER_EDGE | \ 74 MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0)) 75 76 static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq, 77 struct msi_msg *msg) 78 { 79 /* We set vector == 0 to tell the hypervisor we don't care about it, 80 * but we want a pirq setup instead. 81 * We use the dest_id field to pass the pirq that we want. */ 82 msg->address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(pirq); 83 msg->address_lo = 84 MSI_ADDR_BASE_LO | 85 MSI_ADDR_DEST_MODE_PHYSICAL | 86 MSI_ADDR_REDIRECTION_CPU | 87 MSI_ADDR_DEST_ID(pirq); 88 89 msg->data = XEN_PIRQ_MSI_DATA; 90 } 91 92 static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 93 { 94 int irq, pirq, ret = 0; 95 struct msi_desc *msidesc; 96 struct msi_msg msg; 97 98 list_for_each_entry(msidesc, &dev->msi_list, list) { 99 __read_msi_msg(msidesc, &msg); 100 pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | 101 ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); 102 if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) { 103 xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? 104 "msi-x" : "msi", &irq, &pirq, XEN_ALLOC_IRQ); 105 if (irq < 0) 106 goto error; 107 ret = set_irq_msi(irq, msidesc); 108 if (ret < 0) 109 goto error_while; 110 printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d" 111 " pirq=%d\n", irq, pirq); 112 return 0; 113 } 114 xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? 115 "msi-x" : "msi", &irq, &pirq, (XEN_ALLOC_IRQ | XEN_ALLOC_PIRQ)); 116 if (irq < 0 || pirq < 0) 117 goto error; 118 printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq); 119 xen_msi_compose_msg(dev, pirq, &msg); 120 ret = set_irq_msi(irq, msidesc); 121 if (ret < 0) 122 goto error_while; 123 write_msi_msg(irq, &msg); 124 } 125 return 0; 126 127 error_while: 128 unbind_from_irqhandler(irq, NULL); 129 error: 130 if (ret == -ENODEV) 131 dev_err(&dev->dev, "Xen PCI frontend has not registered" \ 132 " MSI/MSI-X support!\n"); 133 134 return ret; 135 } 136 137 /* 138 * For MSI interrupts we have to use drivers/xen/event.s functions to 139 * allocate an irq_desc and setup the right */ 140 141 142 static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 143 { 144 int irq, ret, i; 145 struct msi_desc *msidesc; 146 int *v; 147 148 v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL); 149 if (!v) 150 return -ENOMEM; 151 152 if (type == PCI_CAP_ID_MSIX) 153 ret = xen_pci_frontend_enable_msix(dev, &v, nvec); 154 else 155 ret = xen_pci_frontend_enable_msi(dev, &v); 156 if (ret) 157 goto error; 158 i = 0; 159 list_for_each_entry(msidesc, &dev->msi_list, list) { 160 irq = xen_allocate_pirq(v[i], 0, /* not sharable */ 161 (type == PCI_CAP_ID_MSIX) ? 162 "pcifront-msi-x" : "pcifront-msi"); 163 if (irq < 0) { 164 ret = -1; 165 goto free; 166 } 167 168 ret = set_irq_msi(irq, msidesc); 169 if (ret) 170 goto error_while; 171 i++; 172 } 173 kfree(v); 174 return 0; 175 176 error_while: 177 unbind_from_irqhandler(irq, NULL); 178 error: 179 if (ret == -ENODEV) 180 dev_err(&dev->dev, "Xen PCI frontend has not registered" \ 181 " MSI/MSI-X support!\n"); 182 free: 183 kfree(v); 184 return ret; 185 } 186 187 static void xen_teardown_msi_irqs(struct pci_dev *dev) 188 { 189 struct msi_desc *msidesc; 190 191 msidesc = list_entry(dev->msi_list.next, struct msi_desc, list); 192 if (msidesc->msi_attrib.is_msix) 193 xen_pci_frontend_disable_msix(dev); 194 else 195 xen_pci_frontend_disable_msi(dev); 196 } 197 198 static void xen_teardown_msi_irq(unsigned int irq) 199 { 200 xen_destroy_irq(irq); 201 } 202 203 static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 204 { 205 int irq, ret; 206 struct msi_desc *msidesc; 207 208 list_for_each_entry(msidesc, &dev->msi_list, list) { 209 irq = xen_create_msi_irq(dev, msidesc, type); 210 if (irq < 0) 211 return -1; 212 213 ret = set_irq_msi(irq, msidesc); 214 if (ret) 215 goto error; 216 } 217 return 0; 218 219 error: 220 xen_destroy_irq(irq); 221 return ret; 222 } 223 #endif 224 225 static int xen_pcifront_enable_irq(struct pci_dev *dev) 226 { 227 int rc; 228 int share = 1; 229 230 dev_info(&dev->dev, "Xen PCI enabling IRQ: %d\n", dev->irq); 231 232 if (dev->irq < 0) 233 return -EINVAL; 234 235 if (dev->irq < NR_IRQS_LEGACY) 236 share = 0; 237 238 rc = xen_allocate_pirq(dev->irq, share, "pcifront"); 239 if (rc < 0) { 240 dev_warn(&dev->dev, "Xen PCI IRQ: %d, failed to register:%d\n", 241 dev->irq, rc); 242 return rc; 243 } 244 return 0; 245 } 246 247 int __init pci_xen_init(void) 248 { 249 if (!xen_pv_domain() || xen_initial_domain()) 250 return -ENODEV; 251 252 printk(KERN_INFO "PCI: setting up Xen PCI frontend stub\n"); 253 254 pcibios_set_cache_line_size(); 255 256 pcibios_enable_irq = xen_pcifront_enable_irq; 257 pcibios_disable_irq = NULL; 258 259 #ifdef CONFIG_ACPI 260 /* Keep ACPI out of the picture */ 261 acpi_noirq = 1; 262 #endif 263 264 #ifdef CONFIG_PCI_MSI 265 x86_msi.setup_msi_irqs = xen_setup_msi_irqs; 266 x86_msi.teardown_msi_irq = xen_teardown_msi_irq; 267 x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; 268 #endif 269 return 0; 270 } 271 272 int __init pci_xen_hvm_init(void) 273 { 274 if (!xen_feature(XENFEAT_hvm_pirqs)) 275 return 0; 276 277 #ifdef CONFIG_ACPI 278 /* 279 * We don't want to change the actual ACPI delivery model, 280 * just how GSIs get registered. 281 */ 282 __acpi_register_gsi = acpi_register_gsi_xen_hvm; 283 #endif 284 285 #ifdef CONFIG_PCI_MSI 286 x86_msi.setup_msi_irqs = xen_hvm_setup_msi_irqs; 287 x86_msi.teardown_msi_irq = xen_teardown_msi_irq; 288 #endif 289 return 0; 290 } 291 292 #ifdef CONFIG_XEN_DOM0 293 static int xen_register_pirq(u32 gsi, int triggering) 294 { 295 int rc, irq; 296 struct physdev_map_pirq map_irq; 297 int shareable = 0; 298 char *name; 299 300 if (!xen_pv_domain()) 301 return -1; 302 303 if (triggering == ACPI_EDGE_SENSITIVE) { 304 shareable = 0; 305 name = "ioapic-edge"; 306 } else { 307 shareable = 1; 308 name = "ioapic-level"; 309 } 310 311 irq = xen_allocate_pirq(gsi, shareable, name); 312 313 printk(KERN_DEBUG "xen: --> irq=%d\n", irq); 314 315 if (irq < 0) 316 goto out; 317 318 map_irq.domid = DOMID_SELF; 319 map_irq.type = MAP_PIRQ_TYPE_GSI; 320 map_irq.index = gsi; 321 map_irq.pirq = irq; 322 323 rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); 324 if (rc) { 325 printk(KERN_WARNING "xen map irq failed %d\n", rc); 326 return -1; 327 } 328 329 out: 330 return irq; 331 } 332 333 static int xen_register_gsi(u32 gsi, int triggering, int polarity) 334 { 335 int rc, irq; 336 struct physdev_setup_gsi setup_gsi; 337 338 if (!xen_pv_domain()) 339 return -1; 340 341 printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n", 342 gsi, triggering, polarity); 343 344 irq = xen_register_pirq(gsi, triggering); 345 346 setup_gsi.gsi = gsi; 347 setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1); 348 setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1); 349 350 rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi); 351 if (rc == -EEXIST) 352 printk(KERN_INFO "Already setup the GSI :%d\n", gsi); 353 else if (rc) { 354 printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n", 355 gsi, rc); 356 } 357 358 return irq; 359 } 360 361 static __init void xen_setup_acpi_sci(void) 362 { 363 int rc; 364 int trigger, polarity; 365 int gsi = acpi_sci_override_gsi; 366 367 if (!gsi) 368 return; 369 370 rc = acpi_get_override_irq(gsi, &trigger, &polarity); 371 if (rc) { 372 printk(KERN_WARNING "xen: acpi_get_override_irq failed for acpi" 373 " sci, rc=%d\n", rc); 374 return; 375 } 376 trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; 377 polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; 378 379 printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d " 380 "polarity=%d\n", gsi, trigger, polarity); 381 382 gsi = xen_register_gsi(gsi, trigger, polarity); 383 printk(KERN_INFO "xen: acpi sci %d\n", gsi); 384 385 return; 386 } 387 388 static int acpi_register_gsi_xen(struct device *dev, u32 gsi, 389 int trigger, int polarity) 390 { 391 return xen_register_gsi(gsi, trigger, polarity); 392 } 393 394 static int __init pci_xen_initial_domain(void) 395 { 396 #ifdef CONFIG_PCI_MSI 397 x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; 398 x86_msi.teardown_msi_irq = xen_teardown_msi_irq; 399 #endif 400 xen_setup_acpi_sci(); 401 __acpi_register_gsi = acpi_register_gsi_xen; 402 403 return 0; 404 } 405 406 void __init xen_setup_pirqs(void) 407 { 408 int irq; 409 410 pci_xen_initial_domain(); 411 412 if (0 == nr_ioapics) { 413 for (irq = 0; irq < NR_IRQS_LEGACY; irq++) 414 xen_allocate_pirq(irq, 0, "xt-pic"); 415 return; 416 } 417 418 /* Pre-allocate legacy irqs */ 419 for (irq = 0; irq < NR_IRQS_LEGACY; irq++) { 420 int trigger, polarity; 421 422 if (acpi_get_override_irq(irq, &trigger, &polarity) == -1) 423 continue; 424 425 xen_register_pirq(irq, 426 trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE); 427 } 428 } 429 #endif 430