diff options
author | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2010-06-24 11:42:04 -0400 |
---|---|---|
committer | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2010-10-22 16:25:41 -0400 |
commit | 42a1de56f35a9c87932f45439dc1b09c8da0cc95 (patch) | |
tree | 4be6a92222ef2efabd1705cd6b3adb7832f7f9a9 | |
parent | 01557baff6e9c371d4c96e01089dca32cf347500 (diff) |
xen: implement xen_hvm_register_pirq
xen_hvm_register_pirq allows the kernel to map a GSI into a Xen pirq and
receive the interrupt as an event channel from that point on.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r-- | arch/x86/pci/xen.c | 38 | ||||
-rw-r--r-- | drivers/xen/events.c | 4 | ||||
-rw-r--r-- | include/xen/interface/physdev.h | 30 |
3 files changed, 71 insertions, 1 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 4e371065ce41..08e3cdccdfa8 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -17,6 +17,44 @@ | |||
17 | #include <xen/events.h> | 17 | #include <xen/events.h> |
18 | #include <asm/xen/pci.h> | 18 | #include <asm/xen/pci.h> |
19 | 19 | ||
20 | #ifdef CONFIG_ACPI | ||
21 | static int xen_hvm_register_pirq(u32 gsi, int triggering) | ||
22 | { | ||
23 | int rc, irq; | ||
24 | struct physdev_map_pirq map_irq; | ||
25 | int shareable = 0; | ||
26 | char *name; | ||
27 | |||
28 | if (!xen_hvm_domain()) | ||
29 | return -1; | ||
30 | |||
31 | map_irq.domid = DOMID_SELF; | ||
32 | map_irq.type = MAP_PIRQ_TYPE_GSI; | ||
33 | map_irq.index = gsi; | ||
34 | map_irq.pirq = -1; | ||
35 | |||
36 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
37 | if (rc) { | ||
38 | printk(KERN_WARNING "xen map irq failed %d\n", rc); | ||
39 | return -1; | ||
40 | } | ||
41 | |||
42 | if (triggering == ACPI_EDGE_SENSITIVE) { | ||
43 | shareable = 0; | ||
44 | name = "ioapic-edge"; | ||
45 | } else { | ||
46 | shareable = 1; | ||
47 | name = "ioapic-level"; | ||
48 | } | ||
49 | |||
50 | irq = xen_map_pirq_gsi(map_irq.pirq, gsi, shareable, name); | ||
51 | |||
52 | printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq); | ||
53 | |||
54 | return irq; | ||
55 | } | ||
56 | #endif | ||
57 | |||
20 | #if defined(CONFIG_PCI_MSI) | 58 | #if defined(CONFIG_PCI_MSI) |
21 | #include <linux/msi.h> | 59 | #include <linux/msi.h> |
22 | 60 | ||
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 07e56e5a5d2d..239b011ef56f 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <asm/idle.h> | 36 | #include <asm/idle.h> |
37 | #include <asm/io_apic.h> | 37 | #include <asm/io_apic.h> |
38 | #include <asm/sync_bitops.h> | 38 | #include <asm/sync_bitops.h> |
39 | #include <asm/xen/pci.h> | ||
39 | #include <asm/xen/hypercall.h> | 40 | #include <asm/xen/hypercall.h> |
40 | #include <asm/xen/hypervisor.h> | 41 | #include <asm/xen/hypervisor.h> |
41 | 42 | ||
@@ -75,7 +76,8 @@ enum xen_irq_type { | |||
75 | * event channel - irq->event channel mapping | 76 | * event channel - irq->event channel mapping |
76 | * cpu - cpu this event channel is bound to | 77 | * cpu - cpu this event channel is bound to |
77 | * index - type-specific information: | 78 | * index - type-specific information: |
78 | * PIRQ - vector, with MSB being "needs EIO" | 79 | * PIRQ - vector, with MSB being "needs EIO", or physical IRQ of the HVM |
80 | * guest, or GSI (real passthrough IRQ) of the device. | ||
79 | * VIRQ - virq number | 81 | * VIRQ - virq number |
80 | * IPI - IPI vector | 82 | * IPI - IPI vector |
81 | * EVTCHN - | 83 | * EVTCHN - |
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index fbb58833f13e..69a72b96a6cb 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h | |||
@@ -106,6 +106,36 @@ struct physdev_irq { | |||
106 | uint32_t vector; | 106 | uint32_t vector; |
107 | }; | 107 | }; |
108 | 108 | ||
109 | #define MAP_PIRQ_TYPE_MSI 0x0 | ||
110 | #define MAP_PIRQ_TYPE_GSI 0x1 | ||
111 | #define MAP_PIRQ_TYPE_UNKNOWN 0x2 | ||
112 | |||
113 | #define PHYSDEVOP_map_pirq 13 | ||
114 | struct physdev_map_pirq { | ||
115 | domid_t domid; | ||
116 | /* IN */ | ||
117 | int type; | ||
118 | /* IN */ | ||
119 | int index; | ||
120 | /* IN or OUT */ | ||
121 | int pirq; | ||
122 | /* IN */ | ||
123 | int bus; | ||
124 | /* IN */ | ||
125 | int devfn; | ||
126 | /* IN */ | ||
127 | int entry_nr; | ||
128 | /* IN */ | ||
129 | uint64_t table_base; | ||
130 | }; | ||
131 | |||
132 | #define PHYSDEVOP_unmap_pirq 14 | ||
133 | struct physdev_unmap_pirq { | ||
134 | domid_t domid; | ||
135 | /* IN */ | ||
136 | int pirq; | ||
137 | }; | ||
138 | |||
109 | /* | 139 | /* |
110 | * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op() | 140 | * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op() |
111 | * hypercall since 0x00030202. | 141 | * hypercall since 0x00030202. |