Drivers: hv: vmbus: Implement Direct Mode for stimer0
The 2016 version of Hyper-V offers the option to operate the guest VM per-vcpu stimer's in Direct Mode, which means the timer interupts on its own vector rather than queueing a VMbus message. Direct Mode reduces timer processing overhead in both the hypervisor and the guest, and avoids having timer interrupts pollute the VMbus interrupt stream for the synthetic NIC and storage. This patch enables Direct Mode by default on stimer0 when running on a version of Hyper-V that supports it. In prep for coming support of Hyper-V on ARM64, the arch independent portion of the code contains calls to routines that will be populated on ARM64 but are not needed and do nothing on x86. Signed-off-by: Michael Kelley <mikelley@microsoft.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
ce767047b1
commit
248e742a39
@@ -37,6 +37,7 @@ EXPORT_SYMBOL_GPL(ms_hyperv);
|
||||
|
||||
#if IS_ENABLED(CONFIG_HYPERV)
|
||||
static void (*vmbus_handler)(void);
|
||||
static void (*hv_stimer0_handler)(void);
|
||||
static void (*hv_kexec_handler)(void);
|
||||
static void (*hv_crash_handler)(struct pt_regs *regs);
|
||||
|
||||
@@ -69,6 +70,41 @@ void hv_remove_vmbus_irq(void)
|
||||
EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq);
|
||||
EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq);
|
||||
|
||||
/*
|
||||
* Routines to do per-architecture handling of stimer0
|
||||
* interrupts when in Direct Mode
|
||||
*/
|
||||
|
||||
__visible void __irq_entry hv_stimer0_vector_handler(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
|
||||
entering_irq();
|
||||
inc_irq_stat(hyperv_stimer0_count);
|
||||
if (hv_stimer0_handler)
|
||||
hv_stimer0_handler();
|
||||
ack_APIC_irq();
|
||||
|
||||
exiting_irq();
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
int hv_setup_stimer0_irq(int *irq, int *vector, void (*handler)(void))
|
||||
{
|
||||
*vector = HYPERV_STIMER0_VECTOR;
|
||||
*irq = 0; /* Unused on x86/x64 */
|
||||
hv_stimer0_handler = handler;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hv_setup_stimer0_irq);
|
||||
|
||||
void hv_remove_stimer0_irq(int irq)
|
||||
{
|
||||
/* We have no way to deallocate the interrupt gate */
|
||||
hv_stimer0_handler = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hv_remove_stimer0_irq);
|
||||
|
||||
void hv_setup_kexec_handler(void (*handler)(void))
|
||||
{
|
||||
hv_kexec_handler = handler;
|
||||
@@ -257,6 +293,10 @@ static void __init ms_hyperv_init_platform(void)
|
||||
alloc_intr_gate(HYPERV_REENLIGHTENMENT_VECTOR,
|
||||
hyperv_reenlightenment_vector);
|
||||
|
||||
/* Setup the IDT for stimer0 */
|
||||
if (ms_hyperv.misc_features & HV_X64_STIMER_DIRECT_MODE_AVAILABLE)
|
||||
alloc_intr_gate(HYPERV_STIMER0_VECTOR,
|
||||
hv_stimer0_callback_vector);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user