aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/irq_vectors.h3
-rw-r--r--arch/x86/kernel/entry_32.S3
-rw-r--r--arch/x86/kernel/entry_64.S3
-rw-r--r--arch/x86/xen/enlighten.c28
-rw-r--r--arch/x86/xen/xen-ops.h2
-rw-r--r--drivers/xen/events.c70
-rw-r--r--include/xen/events.h7
-rw-r--r--include/xen/hvm.h6
-rw-r--r--include/xen/interface/features.h3
9 files changed, 118 insertions, 7 deletions
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 8767d99c4f64..e2ca30092557 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -125,6 +125,9 @@
125 */ 125 */
126#define MCE_SELF_VECTOR 0xeb 126#define MCE_SELF_VECTOR 0xeb
127 127
128/* Xen vector callback to receive events in a HVM domain */
129#define XEN_HVM_EVTCHN_CALLBACK 0xe9
130
128#define NR_VECTORS 256 131#define NR_VECTORS 256
129 132
130#define FPU_IRQ 13 133#define FPU_IRQ 13
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index cd49141cf153..6b196834a0dd 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -1166,6 +1166,9 @@ ENTRY(xen_failsafe_callback)
1166.previous 1166.previous
1167ENDPROC(xen_failsafe_callback) 1167ENDPROC(xen_failsafe_callback)
1168 1168
1169BUILD_INTERRUPT3(xen_hvm_callback_vector, XEN_HVM_EVTCHN_CALLBACK,
1170 xen_evtchn_do_upcall)
1171
1169#endif /* CONFIG_XEN */ 1172#endif /* CONFIG_XEN */
1170 1173
1171#ifdef CONFIG_FUNCTION_TRACER 1174#ifdef CONFIG_FUNCTION_TRACER
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 0697ff139837..490ae2bb18a8 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1329,6 +1329,9 @@ ENTRY(xen_failsafe_callback)
1329 CFI_ENDPROC 1329 CFI_ENDPROC
1330END(xen_failsafe_callback) 1330END(xen_failsafe_callback)
1331 1331
1332apicinterrupt XEN_HVM_EVTCHN_CALLBACK \
1333 xen_hvm_callback_vector xen_evtchn_do_upcall
1334
1332#endif /* CONFIG_XEN */ 1335#endif /* CONFIG_XEN */
1333 1336
1334/* 1337/*
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 09b36e9d507a..b211a04c4b2c 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -11,6 +11,7 @@
11 * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 11 * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
12 */ 12 */
13 13
14#include <linux/cpu.h>
14#include <linux/kernel.h> 15#include <linux/kernel.h>
15#include <linux/init.h> 16#include <linux/init.h>
16#include <linux/smp.h> 17#include <linux/smp.h>
@@ -38,6 +39,7 @@
38#include <xen/interface/memory.h> 39#include <xen/interface/memory.h>
39#include <xen/features.h> 40#include <xen/features.h>
40#include <xen/page.h> 41#include <xen/page.h>
42#include <xen/hvm.h>
41#include <xen/hvc-console.h> 43#include <xen/hvc-console.h>
42 44
43#include <asm/paravirt.h> 45#include <asm/paravirt.h>
@@ -80,6 +82,8 @@ struct shared_info xen_dummy_shared_info;
80void *xen_initial_gdt; 82void *xen_initial_gdt;
81 83
82RESERVE_BRK(shared_info_page_brk, PAGE_SIZE); 84RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
85__read_mostly int xen_have_vector_callback;
86EXPORT_SYMBOL_GPL(xen_have_vector_callback);
83 87
84/* 88/*
85 * Point at some empty memory to start with. We map the real shared_info 89 * Point at some empty memory to start with. We map the real shared_info
@@ -1277,6 +1281,24 @@ static void __init init_shared_info(void)
1277 per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; 1281 per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
1278} 1282}
1279 1283
1284static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
1285 unsigned long action, void *hcpu)
1286{
1287 int cpu = (long)hcpu;
1288 switch (action) {
1289 case CPU_UP_PREPARE:
1290 per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
1291 break;
1292 default:
1293 break;
1294 }
1295 return NOTIFY_OK;
1296}
1297
1298static struct notifier_block __cpuinitdata xen_hvm_cpu_notifier = {
1299 .notifier_call = xen_hvm_cpu_notify,
1300};
1301
1280static void __init xen_hvm_guest_init(void) 1302static void __init xen_hvm_guest_init(void)
1281{ 1303{
1282 int r; 1304 int r;
@@ -1287,6 +1309,12 @@ static void __init xen_hvm_guest_init(void)
1287 return; 1309 return;
1288 1310
1289 init_shared_info(); 1311 init_shared_info();
1312
1313 if (xen_feature(XENFEAT_hvm_callback_vector))
1314 xen_have_vector_callback = 1;
1315 register_cpu_notifier(&xen_hvm_cpu_notifier);
1316 have_vcpu_info_placement = 0;
1317 x86_init.irqs.intr_init = xen_init_IRQ;
1290} 1318}
1291 1319
1292static bool __init xen_hvm_platform(void) 1320static bool __init xen_hvm_platform(void)
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index f9153a300bce..0d0e0e6a7479 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -38,6 +38,8 @@ void xen_enable_sysenter(void);
38void xen_enable_syscall(void); 38void xen_enable_syscall(void);
39void xen_vcpu_restore(void); 39void xen_vcpu_restore(void);
40 40
41void xen_callback_vector(void);
42
41void __init xen_build_dynamic_phys_to_machine(void); 43void __init xen_build_dynamic_phys_to_machine(void);
42 44
43void xen_init_irq_ops(void); 45void xen_init_irq_ops(void);
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}
diff --git a/include/xen/events.h b/include/xen/events.h
index e68d59a90ca8..a15d93262e30 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -56,4 +56,11 @@ void xen_poll_irq(int irq);
56/* Determine the IRQ which is bound to an event channel */ 56/* Determine the IRQ which is bound to an event channel */
57unsigned irq_from_evtchn(unsigned int evtchn); 57unsigned irq_from_evtchn(unsigned int evtchn);
58 58
59/* Xen HVM evtchn vector callback */
60extern void xen_hvm_callback_vector(void);
61extern int xen_have_vector_callback;
62int xen_set_callback_via(uint64_t via);
63void xen_evtchn_do_upcall(struct pt_regs *regs);
64void xen_hvm_evtchn_do_upcall(void);
65
59#endif /* _XEN_EVENTS_H */ 66#endif /* _XEN_EVENTS_H */
diff --git a/include/xen/hvm.h b/include/xen/hvm.h
index 5dfe8fb86e67..b193fa2f9fdd 100644
--- a/include/xen/hvm.h
+++ b/include/xen/hvm.h
@@ -3,6 +3,7 @@
3#define XEN_HVM_H__ 3#define XEN_HVM_H__
4 4
5#include <xen/interface/hvm/params.h> 5#include <xen/interface/hvm/params.h>
6#include <asm/xen/hypercall.h>
6 7
7static inline int hvm_get_parameter(int idx, uint64_t *value) 8static inline int hvm_get_parameter(int idx, uint64_t *value)
8{ 9{
@@ -21,4 +22,9 @@ static inline int hvm_get_parameter(int idx, uint64_t *value)
21 return r; 22 return r;
22} 23}
23 24
25#define HVM_CALLBACK_VIA_TYPE_VECTOR 0x2
26#define HVM_CALLBACK_VIA_TYPE_SHIFT 56
27#define HVM_CALLBACK_VECTOR(x) (((uint64_t)HVM_CALLBACK_VIA_TYPE_VECTOR)<<\
28 HVM_CALLBACK_VIA_TYPE_SHIFT | (x))
29
24#endif /* XEN_HVM_H__ */ 30#endif /* XEN_HVM_H__ */
diff --git a/include/xen/interface/features.h b/include/xen/interface/features.h
index f51b6413b054..8ab08b91bf6f 100644
--- a/include/xen/interface/features.h
+++ b/include/xen/interface/features.h
@@ -41,6 +41,9 @@
41/* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */ 41/* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */
42#define XENFEAT_mmu_pt_update_preserve_ad 5 42#define XENFEAT_mmu_pt_update_preserve_ad 5
43 43
44/* x86: Does this Xen host support the HVM callback vector type? */
45#define XENFEAT_hvm_callback_vector 8
46
44#define XENFEAT_NR_SUBMAPS 1 47#define XENFEAT_NR_SUBMAPS 1
45 48
46#endif /* __XEN_PUBLIC_FEATURES_H__ */ 49#endif /* __XEN_PUBLIC_FEATURES_H__ */