aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-01-30 11:21:48 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-03-20 15:34:07 -0400
commit9846ff10af12f9e7caac696737db6c990592a74a (patch)
treef0b047fedc93c820ed63657fd5c9bb28457b69ce
parent102b208e6b3b16d3611b67a7af9a93d30b92c006 (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.c26
-rw-r--r--include/xen/interface/physdev.h21
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
111static int *evtchn_to_irq; 112static int *evtchn_to_irq;
113static unsigned long *pirq_eoi_map;
114static bool (*pirq_needs_eoi)(unsigned irq);
112 115
113static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG], 116static 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
272static bool pirq_needs_eoi(unsigned irq) 275static 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
280static 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
1769void __init xen_init_IRQ(void) 1776void __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
57struct 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 */