提交 29d50523 编写于 作者: L Linus Torvalds

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
...@@ -109,8 +109,8 @@ ...@@ -109,8 +109,8 @@
#define UV_BAU_MESSAGE 0xf5 #define UV_BAU_MESSAGE 0xf5
/* Xen vector callback to receive events in a HVM domain */ /* Vector on which hypervisor callbacks will be delivered */
#define XEN_HVM_EVTCHN_CALLBACK 0xf3 #define HYPERVISOR_CALLBACK_VECTOR 0xf3
/* /*
* Local APIC timer IRQ vector is on a different priority level, * Local APIC timer IRQ vector is on a different priority level,
......
...@@ -11,4 +11,8 @@ struct ms_hyperv_info { ...@@ -11,4 +11,8 @@ struct ms_hyperv_info {
extern struct ms_hyperv_info ms_hyperv; extern struct ms_hyperv_info ms_hyperv;
void hyperv_callback_vector(void);
void hyperv_vector_handler(struct pt_regs *regs);
void hv_register_vmbus_handler(int irq, irq_handler_t handler);
#endif #endif
...@@ -14,10 +14,15 @@ ...@@ -14,10 +14,15 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/clocksource.h> #include <linux/clocksource.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/hardirq.h>
#include <linux/interrupt.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/hypervisor.h> #include <asm/hypervisor.h>
#include <asm/hyperv.h> #include <asm/hyperv.h>
#include <asm/mshyperv.h> #include <asm/mshyperv.h>
#include <asm/desc.h>
#include <asm/idle.h>
#include <asm/irq_regs.h>
struct ms_hyperv_info ms_hyperv; struct ms_hyperv_info ms_hyperv;
EXPORT_SYMBOL_GPL(ms_hyperv); EXPORT_SYMBOL_GPL(ms_hyperv);
...@@ -30,6 +35,13 @@ static bool __init ms_hyperv_platform(void) ...@@ -30,6 +35,13 @@ static bool __init ms_hyperv_platform(void)
if (!boot_cpu_has(X86_FEATURE_HYPERVISOR)) if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
return false; return false;
/*
* Xen emulates Hyper-V to support enlightened Windows.
* Check to see first if we are on a Xen Hypervisor.
*/
if (xen_cpuid_base())
return false;
cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS,
&eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]); &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]);
...@@ -68,7 +80,14 @@ static void __init ms_hyperv_init_platform(void) ...@@ -68,7 +80,14 @@ static void __init ms_hyperv_init_platform(void)
printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
ms_hyperv.features, ms_hyperv.hints); ms_hyperv.features, ms_hyperv.hints);
clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100); if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
#if IS_ENABLED(CONFIG_HYPERV)
/*
* Setup the IDT for hypervisor callback.
*/
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, hyperv_callback_vector);
#endif
} }
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
...@@ -77,3 +96,36 @@ const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { ...@@ -77,3 +96,36 @@ const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
.init_platform = ms_hyperv_init_platform, .init_platform = ms_hyperv_init_platform,
}; };
EXPORT_SYMBOL(x86_hyper_ms_hyperv); EXPORT_SYMBOL(x86_hyper_ms_hyperv);
#if IS_ENABLED(CONFIG_HYPERV)
static int vmbus_irq = -1;
static irq_handler_t vmbus_isr;
void hv_register_vmbus_handler(int irq, irq_handler_t handler)
{
vmbus_irq = irq;
vmbus_isr = handler;
}
void hyperv_vector_handler(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc *desc;
irq_enter();
exit_idle();
desc = irq_to_desc(vmbus_irq);
if (desc)
generic_handle_irq_desc(vmbus_irq, desc);
irq_exit();
set_irq_regs(old_regs);
}
#else
void hv_register_vmbus_handler(int irq, irq_handler_t handler)
{
}
#endif
EXPORT_SYMBOL_GPL(hv_register_vmbus_handler);
...@@ -1091,11 +1091,18 @@ ENTRY(xen_failsafe_callback) ...@@ -1091,11 +1091,18 @@ ENTRY(xen_failsafe_callback)
_ASM_EXTABLE(4b,9b) _ASM_EXTABLE(4b,9b)
ENDPROC(xen_failsafe_callback) ENDPROC(xen_failsafe_callback)
BUILD_INTERRUPT3(xen_hvm_callback_vector, XEN_HVM_EVTCHN_CALLBACK, BUILD_INTERRUPT3(xen_hvm_callback_vector, HYPERVISOR_CALLBACK_VECTOR,
xen_evtchn_do_upcall) xen_evtchn_do_upcall)
#endif /* CONFIG_XEN */ #endif /* CONFIG_XEN */
#if IS_ENABLED(CONFIG_HYPERV)
BUILD_INTERRUPT3(hyperv_callback_vector, HYPERVISOR_CALLBACK_VECTOR,
hyperv_vector_handler)
#endif /* CONFIG_HYPERV */
#ifdef CONFIG_FUNCTION_TRACER #ifdef CONFIG_FUNCTION_TRACER
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
......
...@@ -1454,11 +1454,16 @@ ENTRY(xen_failsafe_callback) ...@@ -1454,11 +1454,16 @@ ENTRY(xen_failsafe_callback)
CFI_ENDPROC CFI_ENDPROC
END(xen_failsafe_callback) END(xen_failsafe_callback)
apicinterrupt XEN_HVM_EVTCHN_CALLBACK \ apicinterrupt HYPERVISOR_CALLBACK_VECTOR \
xen_hvm_callback_vector xen_evtchn_do_upcall xen_hvm_callback_vector xen_evtchn_do_upcall
#endif /* CONFIG_XEN */ #endif /* CONFIG_XEN */
#if IS_ENABLED(CONFIG_HYPERV)
apicinterrupt HYPERVISOR_CALLBACK_VECTOR \
hyperv_callback_vector hyperv_vector_handler
#endif /* CONFIG_HYPERV */
/* /*
* Some functions should be protected against kprobes * Some functions should be protected against kprobes
*/ */
......
...@@ -2,7 +2,7 @@ menu "Microsoft Hyper-V guest support" ...@@ -2,7 +2,7 @@ menu "Microsoft Hyper-V guest support"
config HYPERV config HYPERV
tristate "Microsoft Hyper-V client drivers" tristate "Microsoft Hyper-V client drivers"
depends on X86 && ACPI && PCI depends on X86 && ACPI && PCI && X86_LOCAL_APIC
help help
Select this option to run Linux as a Hyper-V client operating Select this option to run Linux as a Hyper-V client operating
system. system.
......
...@@ -1787,7 +1787,7 @@ void xen_callback_vector(void) ...@@ -1787,7 +1787,7 @@ void xen_callback_vector(void)
int rc; int rc;
uint64_t callback_via; uint64_t callback_via;
if (xen_have_vector_callback) { if (xen_have_vector_callback) {
callback_via = HVM_CALLBACK_VECTOR(XEN_HVM_EVTCHN_CALLBACK); callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR);
rc = xen_set_callback_via(callback_via); rc = xen_set_callback_via(callback_via);
if (rc) { if (rc) {
printk(KERN_ERR "Request for Xen HVM callback vector" printk(KERN_ERR "Request for Xen HVM callback vector"
...@@ -1798,8 +1798,9 @@ void xen_callback_vector(void) ...@@ -1798,8 +1798,9 @@ void xen_callback_vector(void)
printk(KERN_INFO "Xen HVM callback vector for event delivery is " printk(KERN_INFO "Xen HVM callback vector for event delivery is "
"enabled\n"); "enabled\n");
/* in the restore case the vector has already been allocated */ /* in the restore case the vector has already been allocated */
if (!test_bit(XEN_HVM_EVTCHN_CALLBACK, used_vectors)) if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors))
alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector); alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
xen_hvm_callback_vector);
} }
} }
#else #else
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册