aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/events.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r--drivers/xen/events.c70
1 files changed, 63 insertions, 7 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index db8f506817f0..d659480125f0 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -29,6 +29,7 @@
29#include <linux/bootmem.h> 29#include <linux/bootmem.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31 31
32#include <asm/desc.h>
32#include <asm/ptrace.h> 33#include <asm/ptrace.h>
33#include <asm/irq.h> 34#include <asm/irq.h>
34#include <asm/idle.h> 35#include <asm/idle.h>
@@ -36,10 +37,14 @@
36#include <asm/xen/hypercall.h> 37#include <asm/xen/hypercall.h>
37#include <asm/xen/hypervisor.h> 38#include <asm/xen/hypervisor.h>
38 39
40#include <xen/xen.h>
41#include <xen/hvm.h>
39#include <xen/xen-ops.h> 42#include <xen/xen-ops.h>
40#include <xen/events.h> 43#include <xen/events.h>
41#include <xen/interface/xen.h> 44#include <xen/interface/xen.h>
42#include <xen/interface/event_channel.h> 45#include <xen/interface/event_channel.h>
46#include <xen/interface/hvm/hvm_op.h>
47#include <xen/interface/hvm/params.h>
43 48
44/* 49/*
45 * This lock protects updates to the following mapping and reference-count 50 * This lock protects updates to the following mapping and reference-count
@@ -617,17 +622,13 @@ static DEFINE_PER_CPU(unsigned, xed_nesting_count);
617 * a bitset of words which contain pending event bits. The second 622 * a bitset of words which contain pending event bits. The second
618 * level is a bitset of pending events themselves. 623 * level is a bitset of pending events themselves.
619 */ 624 */
620void xen_evtchn_do_upcall(struct pt_regs *regs) 625static void __xen_evtchn_do_upcall(void)
621{ 626{
622 int cpu = get_cpu(); 627 int cpu = get_cpu();
623 struct pt_regs *old_regs = set_irq_regs(regs);
624 struct shared_info *s = HYPERVISOR_shared_info; 628 struct shared_info *s = HYPERVISOR_shared_info;
625 struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); 629 struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
626 unsigned count; 630 unsigned count;
627 631
628 exit_idle();
629 irq_enter();
630
631 do { 632 do {
632 unsigned long pending_words; 633 unsigned long pending_words;
633 634
@@ -667,10 +668,26 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
667 } while(count != 1); 668 } while(count != 1);
668 669
669out: 670out:
671
672 put_cpu();
673}
674
675void xen_evtchn_do_upcall(struct pt_regs *regs)
676{
677 struct pt_regs *old_regs = set_irq_regs(regs);
678
679 exit_idle();
680 irq_enter();
681
682 __xen_evtchn_do_upcall();
683
670 irq_exit(); 684 irq_exit();
671 set_irq_regs(old_regs); 685 set_irq_regs(old_regs);
686}
672 687
673 put_cpu(); 688void xen_hvm_evtchn_do_upcall(void)
689{
690 __xen_evtchn_do_upcall();
674} 691}
675 692
676/* Rebind a new event channel to an existing irq. */ 693/* Rebind a new event channel to an existing irq. */
@@ -933,6 +950,40 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
933 .retrigger = retrigger_dynirq, 950 .retrigger = retrigger_dynirq,
934}; 951};
935 952
953int xen_set_callback_via(uint64_t via)
954{
955 struct xen_hvm_param a;
956 a.domid = DOMID_SELF;
957 a.index = HVM_PARAM_CALLBACK_IRQ;
958 a.value = via;
959 return HYPERVISOR_hvm_op(HVMOP_set_param, &a);
960}
961EXPORT_SYMBOL_GPL(xen_set_callback_via);
962
963/* Vector callbacks are better than PCI interrupts to receive event
964 * channel notifications because we can receive vector callbacks on any
965 * vcpu and we don't need PCI support or APIC interactions. */
966void xen_callback_vector(void)
967{
968 int rc;
969 uint64_t callback_via;
970 if (xen_have_vector_callback) {
971 callback_via = HVM_CALLBACK_VECTOR(XEN_HVM_EVTCHN_CALLBACK);
972 rc = xen_set_callback_via(callback_via);
973 if (rc) {
974 printk(KERN_ERR "Request for Xen HVM callback vector"
975 " failed.\n");
976 xen_have_vector_callback = 0;
977 return;
978 }
979 printk(KERN_INFO "Xen HVM callback vector for event delivery is "
980 "enabled\n");
981 /* in the restore case the vector has already been allocated */
982 if (!test_bit(XEN_HVM_EVTCHN_CALLBACK, used_vectors))
983 alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector);
984 }
985}
986
936void __init xen_init_IRQ(void) 987void __init xen_init_IRQ(void)
937{ 988{
938 int i; 989 int i;
@@ -947,5 +998,10 @@ void __init xen_init_IRQ(void)
947 for (i = 0; i < NR_EVENT_CHANNELS; i++) 998 for (i = 0; i < NR_EVENT_CHANNELS; i++)
948 mask_evtchn(i); 999 mask_evtchn(i);
949 1000
950 irq_ctx_init(smp_processor_id()); 1001 if (xen_hvm_domain()) {
1002 xen_callback_vector();
1003 native_init_IRQ();
1004 } else {
1005 irq_ctx_init(smp_processor_id());
1006 }
951} 1007}