hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/hv/hv.c
....@@ -1,23 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2009, Microsoft Corporation.
3
- *
4
- * This program is free software; you can redistribute it and/or modify it
5
- * under the terms and conditions of the GNU General Public License,
6
- * version 2, as published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11
- * more details.
12
- *
13
- * You should have received a copy of the GNU General Public License along with
14
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
- * Place - Suite 330, Boston, MA 02111-1307 USA.
164 *
175 * Authors:
186 * Haiyang Zhang <haiyangz@microsoft.com>
197 * Hank Janssen <hjanssen@microsoft.com>
20
- *
218 */
229 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2310
....@@ -29,28 +16,12 @@
2916 #include <linux/version.h>
3017 #include <linux/random.h>
3118 #include <linux/clockchips.h>
19
+#include <clocksource/hyperv_timer.h>
3220 #include <asm/mshyperv.h>
3321 #include "hyperv_vmbus.h"
3422
3523 /* The one and only */
36
-struct hv_context hv_context = {
37
- .synic_initialized = false,
38
-};
39
-
40
-/*
41
- * If false, we're using the old mechanism for stimer0 interrupts
42
- * where it sends a VMbus message when it expires. The old
43
- * mechanism is used when running on older versions of Hyper-V
44
- * that don't support Direct Mode. While Hyper-V provides
45
- * four stimer's per CPU, Linux uses only stimer0.
46
- */
47
-static bool direct_mode_enabled;
48
-static int stimer0_irq;
49
-static int stimer0_vector;
50
-
51
-#define HV_TIMER_FREQUENCY (10 * 1000 * 1000) /* 100ns period */
52
-#define HV_MAX_MAX_DELTA_TICKS 0xffffffff
53
-#define HV_MIN_DELTA_TICKS 1
24
+struct hv_context hv_context;
5425
5526 /*
5627 * hv_init - Main initialization routine.
....@@ -62,9 +33,6 @@
6233 hv_context.cpu_context = alloc_percpu(struct hv_per_cpu_context);
6334 if (!hv_context.cpu_context)
6435 return -ENOMEM;
65
-
66
- direct_mode_enabled = ms_hyperv.misc_features &
67
- HV_STIMER_DIRECT_MODE_AVAILABLE;
6836 return 0;
6937 }
7038
....@@ -103,89 +71,6 @@
10371 return status & 0xFFFF;
10472 }
10573
106
-/*
107
- * ISR for when stimer0 is operating in Direct Mode. Direct Mode
108
- * does not use VMbus or any VMbus messages, so process here and not
109
- * in the VMbus driver code.
110
- */
111
-
112
-static void hv_stimer0_isr(void)
113
-{
114
- struct hv_per_cpu_context *hv_cpu;
115
-
116
- hv_cpu = this_cpu_ptr(hv_context.cpu_context);
117
- hv_cpu->clk_evt->event_handler(hv_cpu->clk_evt);
118
- add_interrupt_randomness(stimer0_vector, 0);
119
-}
120
-
121
-static int hv_ce_set_next_event(unsigned long delta,
122
- struct clock_event_device *evt)
123
-{
124
- u64 current_tick;
125
-
126
- WARN_ON(!clockevent_state_oneshot(evt));
127
-
128
- current_tick = hyperv_cs->read(NULL);
129
- current_tick += delta;
130
- hv_init_timer(0, current_tick);
131
- return 0;
132
-}
133
-
134
-static int hv_ce_shutdown(struct clock_event_device *evt)
135
-{
136
- hv_init_timer(0, 0);
137
- hv_init_timer_config(0, 0);
138
- if (direct_mode_enabled)
139
- hv_disable_stimer0_percpu_irq(stimer0_irq);
140
-
141
- return 0;
142
-}
143
-
144
-static int hv_ce_set_oneshot(struct clock_event_device *evt)
145
-{
146
- union hv_timer_config timer_cfg;
147
-
148
- timer_cfg.as_uint64 = 0;
149
- timer_cfg.enable = 1;
150
- timer_cfg.auto_enable = 1;
151
- if (direct_mode_enabled) {
152
- /*
153
- * When it expires, the timer will directly interrupt
154
- * on the specified hardware vector/IRQ.
155
- */
156
- timer_cfg.direct_mode = 1;
157
- timer_cfg.apic_vector = stimer0_vector;
158
- hv_enable_stimer0_percpu_irq(stimer0_irq);
159
- } else {
160
- /*
161
- * When it expires, the timer will generate a VMbus message,
162
- * to be handled by the normal VMbus interrupt handler.
163
- */
164
- timer_cfg.direct_mode = 0;
165
- timer_cfg.sintx = VMBUS_MESSAGE_SINT;
166
- }
167
- hv_init_timer_config(0, timer_cfg.as_uint64);
168
- return 0;
169
-}
170
-
171
-static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu)
172
-{
173
- dev->name = "Hyper-V clockevent";
174
- dev->features = CLOCK_EVT_FEAT_ONESHOT;
175
- dev->cpumask = cpumask_of(cpu);
176
- dev->rating = 1000;
177
- /*
178
- * Avoid settint dev->owner = THIS_MODULE deliberately as doing so will
179
- * result in clockevents_config_and_register() taking additional
180
- * references to the hv_vmbus module making it impossible to unload.
181
- */
182
-
183
- dev->set_state_shutdown = hv_ce_shutdown;
184
- dev->set_state_oneshot = hv_ce_set_oneshot;
185
- dev->set_next_event = hv_ce_set_next_event;
186
-}
187
-
188
-
18974 int hv_synic_alloc(void)
19075 {
19176 int cpu;
....@@ -214,14 +99,6 @@
21499 tasklet_init(&hv_cpu->msg_dpc,
215100 vmbus_on_msg_dpc, (unsigned long) hv_cpu);
216101
217
- hv_cpu->clk_evt = kzalloc(sizeof(struct clock_event_device),
218
- GFP_KERNEL);
219
- if (hv_cpu->clk_evt == NULL) {
220
- pr_err("Unable to allocate clock event device\n");
221
- goto err;
222
- }
223
- hv_init_clockevent_device(hv_cpu->clk_evt, cpu);
224
-
225102 hv_cpu->synic_message_page =
226103 (void *)get_zeroed_page(GFP_ATOMIC);
227104 if (hv_cpu->synic_message_page == NULL) {
....@@ -240,14 +117,7 @@
240117 pr_err("Unable to allocate post msg page\n");
241118 goto err;
242119 }
243
-
244
- INIT_LIST_HEAD(&hv_cpu->chan_list);
245120 }
246
-
247
- if (direct_mode_enabled &&
248
- hv_setup_stimer0_irq(&stimer0_irq, &stimer0_vector,
249
- hv_stimer0_isr))
250
- goto err;
251121
252122 return 0;
253123 err:
....@@ -267,7 +137,6 @@
267137 struct hv_per_cpu_context *hv_cpu
268138 = per_cpu_ptr(hv_context.cpu_context, cpu);
269139
270
- kfree(hv_cpu->clk_evt);
271140 free_page((unsigned long)hv_cpu->synic_event_page);
272141 free_page((unsigned long)hv_cpu->synic_message_page);
273142 free_page((unsigned long)hv_cpu->post_msg_page);
....@@ -283,7 +152,7 @@
283152 * retrieve the initialized message and event pages. Otherwise, we create and
284153 * initialize the message and event pages.
285154 */
286
-int hv_synic_init(unsigned int cpu)
155
+void hv_synic_enable_regs(unsigned int cpu)
287156 {
288157 struct hv_per_cpu_context *hv_cpu
289158 = per_cpu_ptr(hv_context.cpu_context, cpu);
....@@ -296,7 +165,7 @@
296165 hv_get_simp(simp.as_uint64);
297166 simp.simp_enabled = 1;
298167 simp.base_simp_gpa = virt_to_phys(hv_cpu->synic_message_page)
299
- >> PAGE_SHIFT;
168
+ >> HV_HYP_PAGE_SHIFT;
300169
301170 hv_set_simp(simp.as_uint64);
302171
....@@ -304,20 +173,16 @@
304173 hv_get_siefp(siefp.as_uint64);
305174 siefp.siefp_enabled = 1;
306175 siefp.base_siefp_gpa = virt_to_phys(hv_cpu->synic_event_page)
307
- >> PAGE_SHIFT;
176
+ >> HV_HYP_PAGE_SHIFT;
308177
309178 hv_set_siefp(siefp.as_uint64);
310179
311180 /* Setup the shared SINT. */
312181 hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
313182
314
- shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR;
183
+ shared_sint.vector = hv_get_vector();
315184 shared_sint.masked = false;
316
- if (ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED)
317
- shared_sint.auto_eoi = false;
318
- else
319
- shared_sint.auto_eoi = true;
320
-
185
+ shared_sint.auto_eoi = hv_recommend_using_aeoi();
321186 hv_set_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
322187
323188 /* Enable the global synic bit */
....@@ -325,93 +190,26 @@
325190 sctrl.enable = 1;
326191
327192 hv_set_synic_state(sctrl.as_uint64);
328
-
329
- hv_context.synic_initialized = true;
330
-
331
- /*
332
- * Register the per-cpu clockevent source.
333
- */
334
- if (ms_hyperv.features & HV_MSR_SYNTIMER_AVAILABLE)
335
- clockevents_config_and_register(hv_cpu->clk_evt,
336
- HV_TIMER_FREQUENCY,
337
- HV_MIN_DELTA_TICKS,
338
- HV_MAX_MAX_DELTA_TICKS);
339
- return 0;
340193 }
341194
342
-/*
343
- * hv_synic_clockevents_cleanup - Cleanup clockevent devices
344
- */
345
-void hv_synic_clockevents_cleanup(void)
195
+int hv_synic_init(unsigned int cpu)
346196 {
347
- int cpu;
197
+ hv_synic_enable_regs(cpu);
348198
349
- if (!(ms_hyperv.features & HV_MSR_SYNTIMER_AVAILABLE))
350
- return;
199
+ hv_stimer_legacy_init(cpu, VMBUS_MESSAGE_SINT);
351200
352
- if (direct_mode_enabled)
353
- hv_remove_stimer0_irq(stimer0_irq);
354
-
355
- for_each_present_cpu(cpu) {
356
- struct hv_per_cpu_context *hv_cpu
357
- = per_cpu_ptr(hv_context.cpu_context, cpu);
358
-
359
- clockevents_unbind_device(hv_cpu->clk_evt, cpu);
360
- }
201
+ return 0;
361202 }
362203
363204 /*
364205 * hv_synic_cleanup - Cleanup routine for hv_synic_init().
365206 */
366
-int hv_synic_cleanup(unsigned int cpu)
207
+void hv_synic_disable_regs(unsigned int cpu)
367208 {
368209 union hv_synic_sint shared_sint;
369210 union hv_synic_simp simp;
370211 union hv_synic_siefp siefp;
371212 union hv_synic_scontrol sctrl;
372
- struct vmbus_channel *channel, *sc;
373
- bool channel_found = false;
374
- unsigned long flags;
375
-
376
- if (!hv_context.synic_initialized)
377
- return -EFAULT;
378
-
379
- /*
380
- * Search for channels which are bound to the CPU we're about to
381
- * cleanup. In case we find one and vmbus is still connected we need to
382
- * fail, this will effectively prevent CPU offlining. There is no way
383
- * we can re-bind channels to different CPUs for now.
384
- */
385
- mutex_lock(&vmbus_connection.channel_mutex);
386
- list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
387
- if (channel->target_cpu == cpu) {
388
- channel_found = true;
389
- break;
390
- }
391
- spin_lock_irqsave(&channel->lock, flags);
392
- list_for_each_entry(sc, &channel->sc_list, sc_list) {
393
- if (sc->target_cpu == cpu) {
394
- channel_found = true;
395
- break;
396
- }
397
- }
398
- spin_unlock_irqrestore(&channel->lock, flags);
399
- if (channel_found)
400
- break;
401
- }
402
- mutex_unlock(&vmbus_connection.channel_mutex);
403
-
404
- if (channel_found && vmbus_connection.conn_state == CONNECTED)
405
- return -EBUSY;
406
-
407
- /* Turn off clockevent device */
408
- if (ms_hyperv.features & HV_MSR_SYNTIMER_AVAILABLE) {
409
- struct hv_per_cpu_context *hv_cpu
410
- = this_cpu_ptr(hv_context.cpu_context);
411
-
412
- clockevents_unbind_device(hv_cpu->clk_evt, cpu);
413
- hv_ce_shutdown(hv_cpu->clk_evt);
414
- }
415213
416214 hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
417215
....@@ -437,6 +235,54 @@
437235 hv_get_synic_state(sctrl.as_uint64);
438236 sctrl.enable = 0;
439237 hv_set_synic_state(sctrl.as_uint64);
238
+}
239
+
240
+int hv_synic_cleanup(unsigned int cpu)
241
+{
242
+ struct vmbus_channel *channel, *sc;
243
+ bool channel_found = false;
244
+
245
+ /*
246
+ * Hyper-V does not provide a way to change the connect CPU once
247
+ * it is set; we must prevent the connect CPU from going offline
248
+ * while the VM is running normally. But in the panic or kexec()
249
+ * path where the vmbus is already disconnected, the CPU must be
250
+ * allowed to shut down.
251
+ */
252
+ if (cpu == VMBUS_CONNECT_CPU &&
253
+ vmbus_connection.conn_state == CONNECTED)
254
+ return -EBUSY;
255
+
256
+ /*
257
+ * Search for channels which are bound to the CPU we're about to
258
+ * cleanup. In case we find one and vmbus is still connected, we
259
+ * fail; this will effectively prevent CPU offlining.
260
+ *
261
+ * TODO: Re-bind the channels to different CPUs.
262
+ */
263
+ mutex_lock(&vmbus_connection.channel_mutex);
264
+ list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
265
+ if (channel->target_cpu == cpu) {
266
+ channel_found = true;
267
+ break;
268
+ }
269
+ list_for_each_entry(sc, &channel->sc_list, sc_list) {
270
+ if (sc->target_cpu == cpu) {
271
+ channel_found = true;
272
+ break;
273
+ }
274
+ }
275
+ if (channel_found)
276
+ break;
277
+ }
278
+ mutex_unlock(&vmbus_connection.channel_mutex);
279
+
280
+ if (channel_found && vmbus_connection.conn_state == CONNECTED)
281
+ return -EBUSY;
282
+
283
+ hv_stimer_legacy_cleanup(cpu);
284
+
285
+ hv_synic_disable_regs(cpu);
440286
441287 return 0;
442288 }