diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mshyperv.c')
-rw-r--r-- | arch/x86/kernel/cpu/mshyperv.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 9340f41ce8d3..4488cf0dd499 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c | |||
@@ -37,6 +37,7 @@ EXPORT_SYMBOL_GPL(ms_hyperv); | |||
37 | 37 | ||
38 | #if IS_ENABLED(CONFIG_HYPERV) | 38 | #if IS_ENABLED(CONFIG_HYPERV) |
39 | static void (*vmbus_handler)(void); | 39 | static void (*vmbus_handler)(void); |
40 | static void (*hv_stimer0_handler)(void); | ||
40 | static void (*hv_kexec_handler)(void); | 41 | static void (*hv_kexec_handler)(void); |
41 | static void (*hv_crash_handler)(struct pt_regs *regs); | 42 | static void (*hv_crash_handler)(struct pt_regs *regs); |
42 | 43 | ||
@@ -69,6 +70,41 @@ void hv_remove_vmbus_irq(void) | |||
69 | EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq); | 70 | EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq); |
70 | EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq); | 71 | EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq); |
71 | 72 | ||
73 | /* | ||
74 | * Routines to do per-architecture handling of stimer0 | ||
75 | * interrupts when in Direct Mode | ||
76 | */ | ||
77 | |||
78 | __visible void __irq_entry hv_stimer0_vector_handler(struct pt_regs *regs) | ||
79 | { | ||
80 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
81 | |||
82 | entering_irq(); | ||
83 | inc_irq_stat(hyperv_stimer0_count); | ||
84 | if (hv_stimer0_handler) | ||
85 | hv_stimer0_handler(); | ||
86 | ack_APIC_irq(); | ||
87 | |||
88 | exiting_irq(); | ||
89 | set_irq_regs(old_regs); | ||
90 | } | ||
91 | |||
92 | int hv_setup_stimer0_irq(int *irq, int *vector, void (*handler)(void)) | ||
93 | { | ||
94 | *vector = HYPERV_STIMER0_VECTOR; | ||
95 | *irq = 0; /* Unused on x86/x64 */ | ||
96 | hv_stimer0_handler = handler; | ||
97 | return 0; | ||
98 | } | ||
99 | EXPORT_SYMBOL_GPL(hv_setup_stimer0_irq); | ||
100 | |||
101 | void hv_remove_stimer0_irq(int irq) | ||
102 | { | ||
103 | /* We have no way to deallocate the interrupt gate */ | ||
104 | hv_stimer0_handler = NULL; | ||
105 | } | ||
106 | EXPORT_SYMBOL_GPL(hv_remove_stimer0_irq); | ||
107 | |||
72 | void hv_setup_kexec_handler(void (*handler)(void)) | 108 | void hv_setup_kexec_handler(void (*handler)(void)) |
73 | { | 109 | { |
74 | hv_kexec_handler = handler; | 110 | hv_kexec_handler = handler; |
@@ -257,6 +293,10 @@ static void __init ms_hyperv_init_platform(void) | |||
257 | alloc_intr_gate(HYPERV_REENLIGHTENMENT_VECTOR, | 293 | alloc_intr_gate(HYPERV_REENLIGHTENMENT_VECTOR, |
258 | hyperv_reenlightenment_vector); | 294 | hyperv_reenlightenment_vector); |
259 | 295 | ||
296 | /* Setup the IDT for stimer0 */ | ||
297 | if (ms_hyperv.misc_features & HV_X64_STIMER_DIRECT_MODE_AVAILABLE) | ||
298 | alloc_intr_gate(HYPERV_STIMER0_VECTOR, | ||
299 | hv_stimer0_callback_vector); | ||
260 | #endif | 300 | #endif |
261 | } | 301 | } |
262 | 302 | ||