diff options
| author | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2010-09-02 09:51:39 -0400 |
|---|---|---|
| committer | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2010-10-22 16:25:43 -0400 |
| commit | 38aa66fcb79e0a46c24bba96b6f2b851a6ec2037 (patch) | |
| tree | ada0747fc6a242581dc8c612bae53161f97ab14a | |
| parent | 6b0661a5e6fbfb159b78a39c0476905aa9b575fe (diff) | |
xen: remap GSIs as pirqs when running as initial domain
Implement xen_register_gsi to setup the correct triggering and polarity
properties of a gsi.
Implement xen_register_pirq to register a particular gsi as pirq and
receive interrupts as events.
Call xen_setup_pirqs to register all the legacy ISA irqs as pirqs.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
| -rw-r--r-- | arch/x86/include/asm/xen/pci.h | 7 | ||||
| -rw-r--r-- | arch/x86/pci/xen.c | 135 | ||||
| -rw-r--r-- | drivers/xen/events.c | 13 | ||||
| -rw-r--r-- | include/xen/interface/physdev.h | 10 |
4 files changed, 165 insertions, 0 deletions
diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h index f89a42aff284..2329b3eaf8d3 100644 --- a/arch/x86/include/asm/xen/pci.h +++ b/arch/x86/include/asm/xen/pci.h | |||
| @@ -13,6 +13,13 @@ static inline int pci_xen_hvm_init(void) | |||
| 13 | return -1; | 13 | return -1; |
| 14 | } | 14 | } |
| 15 | #endif | 15 | #endif |
| 16 | #if defined(CONFIG_XEN_DOM0) | ||
| 17 | void __init xen_setup_pirqs(void); | ||
| 18 | #else | ||
| 19 | static inline void __init xen_setup_pirqs(void) | ||
| 20 | { | ||
| 21 | } | ||
| 22 | #endif | ||
| 16 | 23 | ||
| 17 | #if defined(CONFIG_PCI_MSI) | 24 | #if defined(CONFIG_PCI_MSI) |
| 18 | #if defined(CONFIG_PCI_XEN) | 25 | #if defined(CONFIG_PCI_XEN) |
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index b5bd6420851e..dd0b5fdb27b9 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
| @@ -257,3 +257,138 @@ int __init pci_xen_hvm_init(void) | |||
| 257 | #endif | 257 | #endif |
| 258 | return 0; | 258 | return 0; |
| 259 | } | 259 | } |
| 260 | |||
| 261 | #ifdef CONFIG_XEN_DOM0 | ||
| 262 | static int xen_register_pirq(u32 gsi, int triggering) | ||
| 263 | { | ||
| 264 | int rc, irq; | ||
| 265 | struct physdev_map_pirq map_irq; | ||
| 266 | int shareable = 0; | ||
| 267 | char *name; | ||
| 268 | |||
| 269 | if (!xen_pv_domain()) | ||
| 270 | return -1; | ||
| 271 | |||
| 272 | if (triggering == ACPI_EDGE_SENSITIVE) { | ||
| 273 | shareable = 0; | ||
| 274 | name = "ioapic-edge"; | ||
| 275 | } else { | ||
| 276 | shareable = 1; | ||
| 277 | name = "ioapic-level"; | ||
| 278 | } | ||
| 279 | |||
| 280 | irq = xen_allocate_pirq(gsi, shareable, name); | ||
| 281 | |||
| 282 | printk(KERN_DEBUG "xen: --> irq=%d\n", irq); | ||
| 283 | |||
| 284 | if (irq < 0) | ||
| 285 | goto out; | ||
| 286 | |||
| 287 | map_irq.domid = DOMID_SELF; | ||
| 288 | map_irq.type = MAP_PIRQ_TYPE_GSI; | ||
| 289 | map_irq.index = gsi; | ||
| 290 | map_irq.pirq = irq; | ||
| 291 | |||
| 292 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
| 293 | if (rc) { | ||
| 294 | printk(KERN_WARNING "xen map irq failed %d\n", rc); | ||
| 295 | return -1; | ||
| 296 | } | ||
| 297 | |||
| 298 | out: | ||
| 299 | return irq; | ||
| 300 | } | ||
| 301 | |||
| 302 | static int xen_register_gsi(u32 gsi, int triggering, int polarity) | ||
| 303 | { | ||
| 304 | int rc, irq; | ||
| 305 | struct physdev_setup_gsi setup_gsi; | ||
| 306 | |||
| 307 | if (!xen_pv_domain()) | ||
| 308 | return -1; | ||
| 309 | |||
| 310 | printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n", | ||
| 311 | gsi, triggering, polarity); | ||
| 312 | |||
| 313 | irq = xen_register_pirq(gsi, triggering); | ||
| 314 | |||
| 315 | setup_gsi.gsi = gsi; | ||
| 316 | setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1); | ||
| 317 | setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | ||
| 318 | |||
| 319 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi); | ||
| 320 | if (rc == -EEXIST) | ||
| 321 | printk(KERN_INFO "Already setup the GSI :%d\n", gsi); | ||
| 322 | else if (rc) { | ||
| 323 | printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n", | ||
| 324 | gsi, rc); | ||
| 325 | } | ||
| 326 | |||
| 327 | return irq; | ||
| 328 | } | ||
| 329 | |||
| 330 | static __init void xen_setup_acpi_sci(void) | ||
| 331 | { | ||
| 332 | int rc; | ||
| 333 | int trigger, polarity; | ||
| 334 | int gsi = acpi_sci_override_gsi; | ||
| 335 | |||
| 336 | if (!gsi) | ||
| 337 | return; | ||
| 338 | |||
| 339 | rc = acpi_get_override_irq(gsi, &trigger, &polarity); | ||
| 340 | if (rc) { | ||
| 341 | printk(KERN_WARNING "xen: acpi_get_override_irq failed for acpi" | ||
| 342 | " sci, rc=%d\n", rc); | ||
| 343 | return; | ||
| 344 | } | ||
| 345 | trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; | ||
| 346 | polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; | ||
| 347 | |||
| 348 | printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d " | ||
| 349 | "polarity=%d\n", gsi, trigger, polarity); | ||
| 350 | |||
| 351 | gsi = xen_register_gsi(gsi, trigger, polarity); | ||
| 352 | printk(KERN_INFO "xen: acpi sci %d\n", gsi); | ||
| 353 | |||
| 354 | return; | ||
| 355 | } | ||
| 356 | |||
| 357 | static int acpi_register_gsi_xen(struct device *dev, u32 gsi, | ||
| 358 | int trigger, int polarity) | ||
| 359 | { | ||
| 360 | return xen_register_gsi(gsi, trigger, polarity); | ||
| 361 | } | ||
| 362 | |||
| 363 | static int __init pci_xen_initial_domain(void) | ||
| 364 | { | ||
| 365 | xen_setup_acpi_sci(); | ||
| 366 | __acpi_register_gsi = acpi_register_gsi_xen; | ||
| 367 | |||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | void __init xen_setup_pirqs(void) | ||
| 372 | { | ||
| 373 | int irq; | ||
| 374 | |||
| 375 | pci_xen_initial_domain(); | ||
| 376 | |||
| 377 | if (0 == nr_ioapics) { | ||
| 378 | for (irq = 0; irq < NR_IRQS_LEGACY; irq++) | ||
| 379 | xen_allocate_pirq(irq, 0, "xt-pic"); | ||
| 380 | return; | ||
| 381 | } | ||
| 382 | |||
| 383 | /* Pre-allocate legacy irqs */ | ||
| 384 | for (irq = 0; irq < NR_IRQS_LEGACY; irq++) { | ||
| 385 | int trigger, polarity; | ||
| 386 | |||
| 387 | if (acpi_get_override_irq(irq, &trigger, &polarity) == -1) | ||
| 388 | continue; | ||
| 389 | |||
| 390 | xen_register_pirq(irq, | ||
| 391 | trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE); | ||
| 392 | } | ||
| 393 | } | ||
| 394 | #endif | ||
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index efa683ee8840..c649ac0aaeef 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
| @@ -681,6 +681,8 @@ out: | |||
| 681 | int xen_destroy_irq(int irq) | 681 | int xen_destroy_irq(int irq) |
| 682 | { | 682 | { |
| 683 | struct irq_desc *desc; | 683 | struct irq_desc *desc; |
| 684 | struct physdev_unmap_pirq unmap_irq; | ||
| 685 | struct irq_info *info = info_for_irq(irq); | ||
| 684 | int rc = -ENOENT; | 686 | int rc = -ENOENT; |
| 685 | 687 | ||
| 686 | spin_lock(&irq_mapping_update_lock); | 688 | spin_lock(&irq_mapping_update_lock); |
| @@ -689,6 +691,15 @@ int xen_destroy_irq(int irq) | |||
| 689 | if (!desc) | 691 | if (!desc) |
| 690 | goto out; | 692 | goto out; |
| 691 | 693 | ||
| 694 | if (xen_initial_domain()) { | ||
| 695 | unmap_irq.pirq = info->u.pirq.gsi; | ||
| 696 | unmap_irq.domid = DOMID_SELF; | ||
| 697 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); | ||
| 698 | if (rc) { | ||
| 699 | printk(KERN_WARNING "unmap irq failed %d\n", rc); | ||
| 700 | goto out; | ||
| 701 | } | ||
| 702 | } | ||
| 692 | irq_info[irq] = mk_unbound_info(); | 703 | irq_info[irq] = mk_unbound_info(); |
| 693 | 704 | ||
| 694 | irq_free_desc(irq); | 705 | irq_free_desc(irq); |
| @@ -1425,5 +1436,7 @@ void __init xen_init_IRQ(void) | |||
| 1425 | pci_xen_hvm_init(); | 1436 | pci_xen_hvm_init(); |
| 1426 | } else { | 1437 | } else { |
| 1427 | irq_ctx_init(smp_processor_id()); | 1438 | irq_ctx_init(smp_processor_id()); |
| 1439 | if (xen_initial_domain()) | ||
| 1440 | xen_setup_pirqs(); | ||
| 1428 | } | 1441 | } |
| 1429 | } | 1442 | } |
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index 69a72b96a6cb..a85d76c2e360 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h | |||
| @@ -151,6 +151,16 @@ struct physdev_op { | |||
| 151 | } u; | 151 | } u; |
| 152 | }; | 152 | }; |
| 153 | 153 | ||
| 154 | #define PHYSDEVOP_setup_gsi 21 | ||
| 155 | struct physdev_setup_gsi { | ||
| 156 | int gsi; | ||
| 157 | /* IN */ | ||
| 158 | uint8_t triggering; | ||
| 159 | /* IN */ | ||
| 160 | uint8_t polarity; | ||
| 161 | /* IN */ | ||
| 162 | }; | ||
| 163 | |||
| 154 | #define PHYSDEVOP_get_nr_pirqs 22 | 164 | #define PHYSDEVOP_get_nr_pirqs 22 |
| 155 | struct physdev_nr_pirqs { | 165 | struct physdev_nr_pirqs { |
| 156 | /* OUT */ | 166 | /* OUT */ |
