diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-19 23:10:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-19 23:10:21 -0500 |
commit | 29d50523298eb80742cedd9ec4d42d6d6dbfb5ee (patch) | |
tree | 344d6583f403e5957def18ea8b6ed35cd9fe9db0 /arch | |
parent | 026f149ca38adf96118d3b5fdba6977797861ce6 (diff) | |
parent | cb20e5f2c8d6ba7440a32f4d70c0755bceb36e78 (diff) |
Merge branch 'x86-hyperv-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/hyperv changes from Ingo Molnar:
"The biggest change is support for Windows 8's improved hypervisor
interrupt model on the Linux Hyper-V guest subsystem code side.
Smallish fixes otherwise."
* 'x86-hyperv-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86, hyperv: HYPERV depends on X86_LOCAL_APIC
X86: Handle Hyper-V vmbus interrupts as special hypervisor interrupts
X86: Add a check to catch Xen emulation of Hyper-V
x86: Hyper-V: register clocksource only if its advertised
Diffstat (limited to 'arch')
-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 |
5 files changed, 73 insertions, 5 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 | */ |