diff options
author | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2012-01-30 11:21:48 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-03-20 15:34:07 -0400 |
commit | 9846ff10af12f9e7caac696737db6c990592a74a (patch) | |
tree | f0b047fedc93c820ed63657fd5c9bb28457b69ce | |
parent | 102b208e6b3b16d3611b67a7af9a93d30b92c006 (diff) |
xen: support pirq_eoi_map
The pirq_eoi_map is a bitmap offered by Xen to check which pirqs need to
be EOI'd without having to issue an hypercall every time.
We use PHYSDEVOP_pirq_eoi_gmfn_v2 to map the bitmap, then if we
succeed we use pirq_eoi_map to check whether pirqs need eoi.
Changes in v3:
- explicitly use PHYSDEVOP_pirq_eoi_gmfn_v2 rather than
PHYSDEVOP_pirq_eoi_gmfn;
- introduce pirq_check_eoi_map, a function to check if a pirq needs an
eoi using the map;
-rename pirq_needs_eoi into pirq_needs_eoi_flag;
- introduce a function pointer called pirq_needs_eoi that is going to be
set to the right implementation depending on the availability of
PHYSDEVOP_pirq_eoi_gmfn_v2.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r-- | drivers/xen/events.c | 26 | ||||
-rw-r--r-- | include/xen/interface/physdev.h | 21 |
2 files changed, 44 insertions, 3 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index e5e5812a1014..4b33acd8ed4e 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/idle.h> | 37 | #include <asm/idle.h> |
38 | #include <asm/io_apic.h> | 38 | #include <asm/io_apic.h> |
39 | #include <asm/sync_bitops.h> | 39 | #include <asm/sync_bitops.h> |
40 | #include <asm/xen/page.h> | ||
40 | #include <asm/xen/pci.h> | 41 | #include <asm/xen/pci.h> |
41 | #include <asm/xen/hypercall.h> | 42 | #include <asm/xen/hypercall.h> |
42 | #include <asm/xen/hypervisor.h> | 43 | #include <asm/xen/hypervisor.h> |
@@ -109,6 +110,8 @@ struct irq_info { | |||
109 | #define PIRQ_SHAREABLE (1 << 1) | 110 | #define PIRQ_SHAREABLE (1 << 1) |
110 | 111 | ||
111 | static int *evtchn_to_irq; | 112 | static int *evtchn_to_irq; |
113 | static unsigned long *pirq_eoi_map; | ||
114 | static bool (*pirq_needs_eoi)(unsigned irq); | ||
112 | 115 | ||
113 | static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG], | 116 | static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG], |
114 | cpu_evtchn_mask); | 117 | cpu_evtchn_mask); |
@@ -269,10 +272,14 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn) | |||
269 | return ret; | 272 | return ret; |
270 | } | 273 | } |
271 | 274 | ||
272 | static bool pirq_needs_eoi(unsigned irq) | 275 | static bool pirq_check_eoi_map(unsigned irq) |
273 | { | 276 | { |
274 | struct irq_info *info = info_for_irq(irq); | 277 | return test_bit(irq, pirq_eoi_map); |
278 | } | ||
275 | 279 | ||
280 | static bool pirq_needs_eoi_flag(unsigned irq) | ||
281 | { | ||
282 | struct irq_info *info = info_for_irq(irq); | ||
276 | BUG_ON(info->type != IRQT_PIRQ); | 283 | BUG_ON(info->type != IRQT_PIRQ); |
277 | 284 | ||
278 | return info->u.pirq.flags & PIRQ_NEEDS_EOI; | 285 | return info->u.pirq.flags & PIRQ_NEEDS_EOI; |
@@ -1768,7 +1775,7 @@ void xen_callback_vector(void) {} | |||
1768 | 1775 | ||
1769 | void __init xen_init_IRQ(void) | 1776 | void __init xen_init_IRQ(void) |
1770 | { | 1777 | { |
1771 | int i; | 1778 | int i, rc; |
1772 | 1779 | ||
1773 | evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq), | 1780 | evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq), |
1774 | GFP_KERNEL); | 1781 | GFP_KERNEL); |
@@ -1782,6 +1789,8 @@ void __init xen_init_IRQ(void) | |||
1782 | for (i = 0; i < NR_EVENT_CHANNELS; i++) | 1789 | for (i = 0; i < NR_EVENT_CHANNELS; i++) |
1783 | mask_evtchn(i); | 1790 | mask_evtchn(i); |
1784 | 1791 | ||
1792 | pirq_needs_eoi = pirq_needs_eoi_flag; | ||
1793 | |||
1785 | if (xen_hvm_domain()) { | 1794 | if (xen_hvm_domain()) { |
1786 | xen_callback_vector(); | 1795 | xen_callback_vector(); |
1787 | native_init_IRQ(); | 1796 | native_init_IRQ(); |
@@ -1789,8 +1798,19 @@ void __init xen_init_IRQ(void) | |||
1789 | * __acpi_register_gsi can point at the right function */ | 1798 | * __acpi_register_gsi can point at the right function */ |
1790 | pci_xen_hvm_init(); | 1799 | pci_xen_hvm_init(); |
1791 | } else { | 1800 | } else { |
1801 | struct physdev_pirq_eoi_gmfn eoi_gmfn; | ||
1802 | |||
1792 | irq_ctx_init(smp_processor_id()); | 1803 | irq_ctx_init(smp_processor_id()); |
1793 | if (xen_initial_domain()) | 1804 | if (xen_initial_domain()) |
1794 | pci_xen_initial_domain(); | 1805 | pci_xen_initial_domain(); |
1806 | |||
1807 | pirq_eoi_map = (void *)__get_free_page(GFP_KERNEL|__GFP_ZERO); | ||
1808 | eoi_gmfn.gmfn = virt_to_mfn(pirq_eoi_map); | ||
1809 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn_v2, &eoi_gmfn); | ||
1810 | if (rc != 0) { | ||
1811 | free_page((unsigned long) pirq_eoi_map); | ||
1812 | pirq_eoi_map = NULL; | ||
1813 | } else | ||
1814 | pirq_needs_eoi = pirq_check_eoi_map; | ||
1795 | } | 1815 | } |
1796 | } | 1816 | } |
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index 0c28989007fb..9ce788d8cf49 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h | |||
@@ -39,6 +39,27 @@ struct physdev_eoi { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Register a shared page for the hypervisor to indicate whether the guest | ||
43 | * must issue PHYSDEVOP_eoi. The semantics of PHYSDEVOP_eoi change slightly | ||
44 | * once the guest used this function in that the associated event channel | ||
45 | * will automatically get unmasked. The page registered is used as a bit | ||
46 | * array indexed by Xen's PIRQ value. | ||
47 | */ | ||
48 | #define PHYSDEVOP_pirq_eoi_gmfn_v1 17 | ||
49 | /* | ||
50 | * Register a shared page for the hypervisor to indicate whether the | ||
51 | * guest must issue PHYSDEVOP_eoi. This hypercall is very similar to | ||
52 | * PHYSDEVOP_pirq_eoi_gmfn_v1 but it doesn't change the semantics of | ||
53 | * PHYSDEVOP_eoi. The page registered is used as a bit array indexed by | ||
54 | * Xen's PIRQ value. | ||
55 | */ | ||
56 | #define PHYSDEVOP_pirq_eoi_gmfn_v2 28 | ||
57 | struct physdev_pirq_eoi_gmfn { | ||
58 | /* IN */ | ||
59 | unsigned long gmfn; | ||
60 | }; | ||
61 | |||
62 | /* | ||
42 | * Query the status of an IRQ line. | 63 | * Query the status of an IRQ line. |
43 | * @arg == pointer to physdev_irq_status_query structure. | 64 | * @arg == pointer to physdev_irq_status_query structure. |
44 | */ | 65 | */ |