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 | 54 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_32.S | 9 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_64.S | 7 | ||||
| -rw-r--r-- | drivers/hv/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/xen/events.c | 7 |
7 files changed, 78 insertions, 9 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 0a630dd4b620..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); |
| @@ -30,6 +35,13 @@ static bool __init ms_hyperv_platform(void) | |||
| 30 | if (!boot_cpu_has(X86_FEATURE_HYPERVISOR)) | 35 | if (!boot_cpu_has(X86_FEATURE_HYPERVISOR)) |
| 31 | return false; | 36 | return false; |
| 32 | 37 | ||
| 38 | /* | ||
| 39 | * Xen emulates Hyper-V to support enlightened Windows. | ||
| 40 | * Check to see first if we are on a Xen Hypervisor. | ||
| 41 | */ | ||
| 42 | if (xen_cpuid_base()) | ||
| 43 | return false; | ||
| 44 | |||
| 33 | cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, | 45 | cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, |
| 34 | &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]); | 46 | &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]); |
| 35 | 47 | ||
| @@ -68,7 +80,14 @@ static void __init ms_hyperv_init_platform(void) | |||
| 68 | printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", | 80 | printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", |
| 69 | ms_hyperv.features, ms_hyperv.hints); | 81 | ms_hyperv.features, ms_hyperv.hints); |
| 70 | 82 | ||
| 71 | clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100); | 83 | if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) |
| 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 | ||
| 72 | } | 91 | } |
| 73 | 92 | ||
| 74 | const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { | 93 | const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { |
| @@ -77,3 +96,36 @@ const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { | |||
| 77 | .init_platform = ms_hyperv_init_platform, | 96 | .init_platform = ms_hyperv_init_platform, |
| 78 | }; | 97 | }; |
| 79 | 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/hv/Kconfig b/drivers/hv/Kconfig index b38ef6d8d049..64630f15f181 100644 --- a/drivers/hv/Kconfig +++ b/drivers/hv/Kconfig | |||
| @@ -2,7 +2,7 @@ menu "Microsoft Hyper-V guest support" | |||
| 2 | 2 | ||
| 3 | config HYPERV | 3 | config HYPERV |
| 4 | tristate "Microsoft Hyper-V client drivers" | 4 | tristate "Microsoft Hyper-V client drivers" |
| 5 | depends on X86 && ACPI && PCI | 5 | depends on X86 && ACPI && PCI && X86_LOCAL_APIC |
| 6 | help | 6 | help |
| 7 | Select this option to run Linux as a Hyper-V client operating | 7 | Select this option to run Linux as a Hyper-V client operating |
| 8 | system. | 8 | system. |
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 |
