diff options
-rw-r--r-- | arch/x86/include/asm/irq_vectors.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/mshyperv.h | 4 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mshyperv.c | 44 | ||||
-rw-r--r-- | arch/x86/kernel/entry_32.S | 9 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 7 | ||||
-rw-r--r-- | drivers/xen/events.c | 7 |
6 files changed, 68 insertions, 7 deletions
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 1508e518c7e3..aac5fa62a86c 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h | |||
@@ -109,8 +109,8 @@ | |||
109 | 109 | ||
110 | #define UV_BAU_MESSAGE 0xf5 | 110 | #define UV_BAU_MESSAGE 0xf5 |
111 | 111 | ||
112 | /* Xen vector callback to receive events in a HVM domain */ | 112 | /* Vector on which hypervisor callbacks will be delivered */ |
113 | #define XEN_HVM_EVTCHN_CALLBACK 0xf3 | 113 | #define HYPERVISOR_CALLBACK_VECTOR 0xf3 |
114 | 114 | ||
115 | /* | 115 | /* |
116 | * Local APIC timer IRQ vector is on a different priority level, | 116 | * Local APIC timer IRQ vector is on a different priority level, |
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 79ce5685ab64..c2934be2446a 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h | |||
@@ -11,4 +11,8 @@ struct ms_hyperv_info { | |||
11 | 11 | ||
12 | extern struct ms_hyperv_info ms_hyperv; | 12 | extern struct ms_hyperv_info ms_hyperv; |
13 | 13 | ||
14 | void hyperv_callback_vector(void); | ||
15 | void hyperv_vector_handler(struct pt_regs *regs); | ||
16 | void hv_register_vmbus_handler(int irq, irq_handler_t handler); | ||
17 | |||
14 | #endif | 18 | #endif |
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 4dab317f79b9..a7d26d83fb70 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c | |||
@@ -14,10 +14,15 @@ | |||
14 | #include <linux/time.h> | 14 | #include <linux/time.h> |
15 | #include <linux/clocksource.h> | 15 | #include <linux/clocksource.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/hardirq.h> | ||
18 | #include <linux/interrupt.h> | ||
17 | #include <asm/processor.h> | 19 | #include <asm/processor.h> |
18 | #include <asm/hypervisor.h> | 20 | #include <asm/hypervisor.h> |
19 | #include <asm/hyperv.h> | 21 | #include <asm/hyperv.h> |
20 | #include <asm/mshyperv.h> | 22 | #include <asm/mshyperv.h> |
23 | #include <asm/desc.h> | ||
24 | #include <asm/idle.h> | ||
25 | #include <asm/irq_regs.h> | ||
21 | 26 | ||
22 | struct ms_hyperv_info ms_hyperv; | 27 | struct ms_hyperv_info ms_hyperv; |
23 | EXPORT_SYMBOL_GPL(ms_hyperv); | 28 | EXPORT_SYMBOL_GPL(ms_hyperv); |
@@ -77,6 +82,12 @@ static void __init ms_hyperv_init_platform(void) | |||
77 | 82 | ||
78 | if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) | 83 | if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) |
79 | clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100); | 84 | clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100); |
85 | #if IS_ENABLED(CONFIG_HYPERV) | ||
86 | /* | ||
87 | * Setup the IDT for hypervisor callback. | ||
88 | */ | ||
89 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, hyperv_callback_vector); | ||
90 | #endif | ||
80 | } | 91 | } |
81 | 92 | ||
82 | const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { | 93 | const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { |
@@ -85,3 +96,36 @@ const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { | |||
85 | .init_platform = ms_hyperv_init_platform, | 96 | .init_platform = ms_hyperv_init_platform, |
86 | }; | 97 | }; |
87 | EXPORT_SYMBOL(x86_hyper_ms_hyperv); | 98 | EXPORT_SYMBOL(x86_hyper_ms_hyperv); |
99 | |||
100 | #if IS_ENABLED(CONFIG_HYPERV) | ||
101 | static int vmbus_irq = -1; | ||
102 | static irq_handler_t vmbus_isr; | ||
103 | |||
104 | void hv_register_vmbus_handler(int irq, irq_handler_t handler) | ||
105 | { | ||
106 | vmbus_irq = irq; | ||
107 | vmbus_isr = handler; | ||
108 | } | ||
109 | |||
110 | void hyperv_vector_handler(struct pt_regs *regs) | ||
111 | { | ||
112 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
113 | struct irq_desc *desc; | ||
114 | |||
115 | irq_enter(); | ||
116 | exit_idle(); | ||
117 | |||
118 | desc = irq_to_desc(vmbus_irq); | ||
119 | |||
120 | if (desc) | ||
121 | generic_handle_irq_desc(vmbus_irq, desc); | ||
122 | |||
123 | irq_exit(); | ||
124 | set_irq_regs(old_regs); | ||
125 | } | ||
126 | #else | ||
127 | void hv_register_vmbus_handler(int irq, irq_handler_t handler) | ||
128 | { | ||
129 | } | ||
130 | #endif | ||
131 | EXPORT_SYMBOL_GPL(hv_register_vmbus_handler); | ||
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 6ed91d9980e2..8831176aa5ef 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -1091,11 +1091,18 @@ ENTRY(xen_failsafe_callback) | |||
1091 | _ASM_EXTABLE(4b,9b) | 1091 | _ASM_EXTABLE(4b,9b) |
1092 | ENDPROC(xen_failsafe_callback) | 1092 | ENDPROC(xen_failsafe_callback) |
1093 | 1093 | ||
1094 | BUILD_INTERRUPT3(xen_hvm_callback_vector, XEN_HVM_EVTCHN_CALLBACK, | 1094 | BUILD_INTERRUPT3(xen_hvm_callback_vector, HYPERVISOR_CALLBACK_VECTOR, |
1095 | xen_evtchn_do_upcall) | 1095 | xen_evtchn_do_upcall) |
1096 | 1096 | ||
1097 | #endif /* CONFIG_XEN */ | 1097 | #endif /* CONFIG_XEN */ |
1098 | 1098 | ||
1099 | #if IS_ENABLED(CONFIG_HYPERV) | ||
1100 | |||
1101 | BUILD_INTERRUPT3(hyperv_callback_vector, HYPERVISOR_CALLBACK_VECTOR, | ||
1102 | hyperv_vector_handler) | ||
1103 | |||
1104 | #endif /* CONFIG_HYPERV */ | ||
1105 | |||
1099 | #ifdef CONFIG_FUNCTION_TRACER | 1106 | #ifdef CONFIG_FUNCTION_TRACER |
1100 | #ifdef CONFIG_DYNAMIC_FTRACE | 1107 | #ifdef CONFIG_DYNAMIC_FTRACE |
1101 | 1108 | ||
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index cb3c591339aa..048f2240f8e6 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -1454,11 +1454,16 @@ ENTRY(xen_failsafe_callback) | |||
1454 | CFI_ENDPROC | 1454 | CFI_ENDPROC |
1455 | END(xen_failsafe_callback) | 1455 | END(xen_failsafe_callback) |
1456 | 1456 | ||
1457 | apicinterrupt XEN_HVM_EVTCHN_CALLBACK \ | 1457 | apicinterrupt HYPERVISOR_CALLBACK_VECTOR \ |
1458 | xen_hvm_callback_vector xen_evtchn_do_upcall | 1458 | xen_hvm_callback_vector xen_evtchn_do_upcall |
1459 | 1459 | ||
1460 | #endif /* CONFIG_XEN */ | 1460 | #endif /* CONFIG_XEN */ |
1461 | 1461 | ||
1462 | #if IS_ENABLED(CONFIG_HYPERV) | ||
1463 | apicinterrupt HYPERVISOR_CALLBACK_VECTOR \ | ||
1464 | hyperv_callback_vector hyperv_vector_handler | ||
1465 | #endif /* CONFIG_HYPERV */ | ||
1466 | |||
1462 | /* | 1467 | /* |
1463 | * Some functions should be protected against kprobes | 1468 | * Some functions should be protected against kprobes |
1464 | */ | 1469 | */ |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 74d77dfa5f63..22f77c5f6012 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -1787,7 +1787,7 @@ void xen_callback_vector(void) | |||
1787 | int rc; | 1787 | int rc; |
1788 | uint64_t callback_via; | 1788 | uint64_t callback_via; |
1789 | if (xen_have_vector_callback) { | 1789 | if (xen_have_vector_callback) { |
1790 | callback_via = HVM_CALLBACK_VECTOR(XEN_HVM_EVTCHN_CALLBACK); | 1790 | callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR); |
1791 | rc = xen_set_callback_via(callback_via); | 1791 | rc = xen_set_callback_via(callback_via); |
1792 | if (rc) { | 1792 | if (rc) { |
1793 | printk(KERN_ERR "Request for Xen HVM callback vector" | 1793 | printk(KERN_ERR "Request for Xen HVM callback vector" |
@@ -1798,8 +1798,9 @@ void xen_callback_vector(void) | |||
1798 | printk(KERN_INFO "Xen HVM callback vector for event delivery is " | 1798 | printk(KERN_INFO "Xen HVM callback vector for event delivery is " |
1799 | "enabled\n"); | 1799 | "enabled\n"); |
1800 | /* in the restore case the vector has already been allocated */ | 1800 | /* in the restore case the vector has already been allocated */ |
1801 | if (!test_bit(XEN_HVM_EVTCHN_CALLBACK, used_vectors)) | 1801 | if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) |
1802 | alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector); | 1802 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, |
1803 | xen_hvm_callback_vector); | ||
1803 | } | 1804 | } |
1804 | } | 1805 | } |
1805 | #else | 1806 | #else |