diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mshyperv.c')
-rw-r--r-- | arch/x86/kernel/cpu/mshyperv.c | 54 |
1 files changed, 53 insertions, 1 deletions
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); | ||