drivers/hv: Migrate to new 'set-state' interface
[firefly-linux-kernel-4.4.55.git] / drivers / hv / hv.c
1 /*
2  * 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.
16  *
17  * Authors:
18  *   Haiyang Zhang <haiyangz@microsoft.com>
19  *   Hank Janssen  <hjanssen@microsoft.com>
20  *
21  */
22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24 #include <linux/kernel.h>
25 #include <linux/mm.h>
26 #include <linux/slab.h>
27 #include <linux/vmalloc.h>
28 #include <linux/hyperv.h>
29 #include <linux/version.h>
30 #include <linux/interrupt.h>
31 #include <linux/clockchips.h>
32 #include <asm/hyperv.h>
33 #include <asm/mshyperv.h>
34 #include "hyperv_vmbus.h"
35
36 /* The one and only */
37 struct hv_context hv_context = {
38         .synic_initialized      = false,
39         .hypercall_page         = NULL,
40 };
41
42 #define HV_TIMER_FREQUENCY (10 * 1000 * 1000) /* 100ns period */
43 #define HV_MAX_MAX_DELTA_TICKS 0xffffffff
44 #define HV_MIN_DELTA_TICKS 1
45
46 /*
47  * query_hypervisor_info - Get version info of the windows hypervisor
48  */
49 unsigned int host_info_eax;
50 unsigned int host_info_ebx;
51 unsigned int host_info_ecx;
52 unsigned int host_info_edx;
53
54 static int query_hypervisor_info(void)
55 {
56         unsigned int eax;
57         unsigned int ebx;
58         unsigned int ecx;
59         unsigned int edx;
60         unsigned int max_leaf;
61         unsigned int op;
62
63         /*
64         * Its assumed that this is called after confirming that Viridian
65         * is present. Query id and revision.
66         */
67         eax = 0;
68         ebx = 0;
69         ecx = 0;
70         edx = 0;
71         op = HVCPUID_VENDOR_MAXFUNCTION;
72         cpuid(op, &eax, &ebx, &ecx, &edx);
73
74         max_leaf = eax;
75
76         if (max_leaf >= HVCPUID_VERSION) {
77                 eax = 0;
78                 ebx = 0;
79                 ecx = 0;
80                 edx = 0;
81                 op = HVCPUID_VERSION;
82                 cpuid(op, &eax, &ebx, &ecx, &edx);
83                 host_info_eax = eax;
84                 host_info_ebx = ebx;
85                 host_info_ecx = ecx;
86                 host_info_edx = edx;
87         }
88         return max_leaf;
89 }
90
91 /*
92  * do_hypercall- Invoke the specified hypercall
93  */
94 static u64 do_hypercall(u64 control, void *input, void *output)
95 {
96         u64 input_address = (input) ? virt_to_phys(input) : 0;
97         u64 output_address = (output) ? virt_to_phys(output) : 0;
98         void *hypercall_page = hv_context.hypercall_page;
99 #ifdef CONFIG_X86_64
100         u64 hv_status = 0;
101
102         if (!hypercall_page)
103                 return (u64)ULLONG_MAX;
104
105         __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
106         __asm__ __volatile__("call *%3" : "=a" (hv_status) :
107                              "c" (control), "d" (input_address),
108                              "m" (hypercall_page));
109
110         return hv_status;
111
112 #else
113
114         u32 control_hi = control >> 32;
115         u32 control_lo = control & 0xFFFFFFFF;
116         u32 hv_status_hi = 1;
117         u32 hv_status_lo = 1;
118         u32 input_address_hi = input_address >> 32;
119         u32 input_address_lo = input_address & 0xFFFFFFFF;
120         u32 output_address_hi = output_address >> 32;
121         u32 output_address_lo = output_address & 0xFFFFFFFF;
122
123         if (!hypercall_page)
124                 return (u64)ULLONG_MAX;
125
126         __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
127                               "=a"(hv_status_lo) : "d" (control_hi),
128                               "a" (control_lo), "b" (input_address_hi),
129                               "c" (input_address_lo), "D"(output_address_hi),
130                               "S"(output_address_lo), "m" (hypercall_page));
131
132         return hv_status_lo | ((u64)hv_status_hi << 32);
133 #endif /* !x86_64 */
134 }
135
136 /*
137  * hv_init - Main initialization routine.
138  *
139  * This routine must be called before any other routines in here are called
140  */
141 int hv_init(void)
142 {
143         int max_leaf;
144         union hv_x64_msr_hypercall_contents hypercall_msr;
145         void *virtaddr = NULL;
146
147         memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
148         memset(hv_context.synic_message_page, 0,
149                sizeof(void *) * NR_CPUS);
150         memset(hv_context.post_msg_page, 0,
151                sizeof(void *) * NR_CPUS);
152         memset(hv_context.vp_index, 0,
153                sizeof(int) * NR_CPUS);
154         memset(hv_context.event_dpc, 0,
155                sizeof(void *) * NR_CPUS);
156         memset(hv_context.clk_evt, 0,
157                sizeof(void *) * NR_CPUS);
158
159         max_leaf = query_hypervisor_info();
160
161         /*
162          * Write our OS ID.
163          */
164         hv_context.guestid = generate_guest_id(0, LINUX_VERSION_CODE, 0);
165         wrmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
166
167         /* See if the hypercall page is already set */
168         rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
169
170         virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
171
172         if (!virtaddr)
173                 goto cleanup;
174
175         hypercall_msr.enable = 1;
176
177         hypercall_msr.guest_physical_address = vmalloc_to_pfn(virtaddr);
178         wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
179
180         /* Confirm that hypercall page did get setup. */
181         hypercall_msr.as_uint64 = 0;
182         rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
183
184         if (!hypercall_msr.enable)
185                 goto cleanup;
186
187         hv_context.hypercall_page = virtaddr;
188
189         return 0;
190
191 cleanup:
192         if (virtaddr) {
193                 if (hypercall_msr.enable) {
194                         hypercall_msr.as_uint64 = 0;
195                         wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
196                 }
197
198                 vfree(virtaddr);
199         }
200
201         return -ENOTSUPP;
202 }
203
204 /*
205  * hv_cleanup - Cleanup routine.
206  *
207  * This routine is called normally during driver unloading or exiting.
208  */
209 void hv_cleanup(void)
210 {
211         union hv_x64_msr_hypercall_contents hypercall_msr;
212
213         /* Reset our OS id */
214         wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
215
216         if (hv_context.hypercall_page) {
217                 hypercall_msr.as_uint64 = 0;
218                 wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
219                 vfree(hv_context.hypercall_page);
220                 hv_context.hypercall_page = NULL;
221         }
222 }
223
224 /*
225  * hv_post_message - Post a message using the hypervisor message IPC.
226  *
227  * This involves a hypercall.
228  */
229 int hv_post_message(union hv_connection_id connection_id,
230                   enum hv_message_type message_type,
231                   void *payload, size_t payload_size)
232 {
233
234         struct hv_input_post_message *aligned_msg;
235         u16 status;
236
237         if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
238                 return -EMSGSIZE;
239
240         aligned_msg = (struct hv_input_post_message *)
241                         hv_context.post_msg_page[get_cpu()];
242
243         aligned_msg->connectionid = connection_id;
244         aligned_msg->reserved = 0;
245         aligned_msg->message_type = message_type;
246         aligned_msg->payload_size = payload_size;
247         memcpy((void *)aligned_msg->payload, payload, payload_size);
248
249         status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL)
250                 & 0xFFFF;
251
252         put_cpu();
253         return status;
254 }
255
256
257 /*
258  * hv_signal_event -
259  * Signal an event on the specified connection using the hypervisor event IPC.
260  *
261  * This involves a hypercall.
262  */
263 u16 hv_signal_event(void *con_id)
264 {
265         u16 status;
266
267         status = (do_hypercall(HVCALL_SIGNAL_EVENT, con_id, NULL) & 0xFFFF);
268
269         return status;
270 }
271
272 static int hv_ce_set_next_event(unsigned long delta,
273                                 struct clock_event_device *evt)
274 {
275         cycle_t current_tick;
276
277         WARN_ON(!clockevent_state_oneshot(evt));
278
279         rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
280         current_tick += delta;
281         wrmsrl(HV_X64_MSR_STIMER0_COUNT, current_tick);
282         return 0;
283 }
284
285 static int hv_ce_shutdown(struct clock_event_device *evt)
286 {
287         wrmsrl(HV_X64_MSR_STIMER0_COUNT, 0);
288         wrmsrl(HV_X64_MSR_STIMER0_CONFIG, 0);
289
290         return 0;
291 }
292
293 static int hv_ce_set_oneshot(struct clock_event_device *evt)
294 {
295         union hv_timer_config timer_cfg;
296
297         timer_cfg.enable = 1;
298         timer_cfg.auto_enable = 1;
299         timer_cfg.sintx = VMBUS_MESSAGE_SINT;
300         wrmsrl(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
301
302         return 0;
303 }
304
305 static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu)
306 {
307         dev->name = "Hyper-V clockevent";
308         dev->features = CLOCK_EVT_FEAT_ONESHOT;
309         dev->cpumask = cpumask_of(cpu);
310         dev->rating = 1000;
311         /*
312          * Avoid settint dev->owner = THIS_MODULE deliberately as doing so will
313          * result in clockevents_config_and_register() taking additional
314          * references to the hv_vmbus module making it impossible to unload.
315          */
316
317         dev->set_state_shutdown = hv_ce_shutdown;
318         dev->set_state_oneshot = hv_ce_set_oneshot;
319         dev->set_next_event = hv_ce_set_next_event;
320 }
321
322
323 int hv_synic_alloc(void)
324 {
325         size_t size = sizeof(struct tasklet_struct);
326         size_t ced_size = sizeof(struct clock_event_device);
327         int cpu;
328
329         hv_context.hv_numa_map = kzalloc(sizeof(struct cpumask) * nr_node_ids,
330                                          GFP_ATOMIC);
331         if (hv_context.hv_numa_map == NULL) {
332                 pr_err("Unable to allocate NUMA map\n");
333                 goto err;
334         }
335
336         for_each_online_cpu(cpu) {
337                 hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
338                 if (hv_context.event_dpc[cpu] == NULL) {
339                         pr_err("Unable to allocate event dpc\n");
340                         goto err;
341                 }
342                 tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu);
343
344                 hv_context.clk_evt[cpu] = kzalloc(ced_size, GFP_ATOMIC);
345                 if (hv_context.clk_evt[cpu] == NULL) {
346                         pr_err("Unable to allocate clock event device\n");
347                         goto err;
348                 }
349
350                 hv_init_clockevent_device(hv_context.clk_evt[cpu], cpu);
351
352                 hv_context.synic_message_page[cpu] =
353                         (void *)get_zeroed_page(GFP_ATOMIC);
354
355                 if (hv_context.synic_message_page[cpu] == NULL) {
356                         pr_err("Unable to allocate SYNIC message page\n");
357                         goto err;
358                 }
359
360                 hv_context.synic_event_page[cpu] =
361                         (void *)get_zeroed_page(GFP_ATOMIC);
362
363                 if (hv_context.synic_event_page[cpu] == NULL) {
364                         pr_err("Unable to allocate SYNIC event page\n");
365                         goto err;
366                 }
367
368                 hv_context.post_msg_page[cpu] =
369                         (void *)get_zeroed_page(GFP_ATOMIC);
370
371                 if (hv_context.post_msg_page[cpu] == NULL) {
372                         pr_err("Unable to allocate post msg page\n");
373                         goto err;
374                 }
375         }
376
377         return 0;
378 err:
379         return -ENOMEM;
380 }
381
382 static void hv_synic_free_cpu(int cpu)
383 {
384         kfree(hv_context.event_dpc[cpu]);
385         kfree(hv_context.clk_evt[cpu]);
386         if (hv_context.synic_event_page[cpu])
387                 free_page((unsigned long)hv_context.synic_event_page[cpu]);
388         if (hv_context.synic_message_page[cpu])
389                 free_page((unsigned long)hv_context.synic_message_page[cpu]);
390         if (hv_context.post_msg_page[cpu])
391                 free_page((unsigned long)hv_context.post_msg_page[cpu]);
392 }
393
394 void hv_synic_free(void)
395 {
396         int cpu;
397
398         kfree(hv_context.hv_numa_map);
399         for_each_online_cpu(cpu)
400                 hv_synic_free_cpu(cpu);
401 }
402
403 /*
404  * hv_synic_init - Initialize the Synthethic Interrupt Controller.
405  *
406  * If it is already initialized by another entity (ie x2v shim), we need to
407  * retrieve the initialized message and event pages.  Otherwise, we create and
408  * initialize the message and event pages.
409  */
410 void hv_synic_init(void *arg)
411 {
412         u64 version;
413         union hv_synic_simp simp;
414         union hv_synic_siefp siefp;
415         union hv_synic_sint shared_sint;
416         union hv_synic_scontrol sctrl;
417         u64 vp_index;
418
419         int cpu = smp_processor_id();
420
421         if (!hv_context.hypercall_page)
422                 return;
423
424         /* Check the version */
425         rdmsrl(HV_X64_MSR_SVERSION, version);
426
427         /* Setup the Synic's message page */
428         rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
429         simp.simp_enabled = 1;
430         simp.base_simp_gpa = virt_to_phys(hv_context.synic_message_page[cpu])
431                 >> PAGE_SHIFT;
432
433         wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
434
435         /* Setup the Synic's event page */
436         rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
437         siefp.siefp_enabled = 1;
438         siefp.base_siefp_gpa = virt_to_phys(hv_context.synic_event_page[cpu])
439                 >> PAGE_SHIFT;
440
441         wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
442
443         /* Setup the shared SINT. */
444         rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
445
446         shared_sint.as_uint64 = 0;
447         shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR;
448         shared_sint.masked = false;
449         shared_sint.auto_eoi = true;
450
451         wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
452
453         /* Enable the global synic bit */
454         rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
455         sctrl.enable = 1;
456
457         wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
458
459         hv_context.synic_initialized = true;
460
461         /*
462          * Setup the mapping between Hyper-V's notion
463          * of cpuid and Linux' notion of cpuid.
464          * This array will be indexed using Linux cpuid.
465          */
466         rdmsrl(HV_X64_MSR_VP_INDEX, vp_index);
467         hv_context.vp_index[cpu] = (u32)vp_index;
468
469         INIT_LIST_HEAD(&hv_context.percpu_list[cpu]);
470
471         /*
472          * Register the per-cpu clockevent source.
473          */
474         if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE)
475                 clockevents_config_and_register(hv_context.clk_evt[cpu],
476                                                 HV_TIMER_FREQUENCY,
477                                                 HV_MIN_DELTA_TICKS,
478                                                 HV_MAX_MAX_DELTA_TICKS);
479         return;
480 }
481
482 /*
483  * hv_synic_clockevents_cleanup - Cleanup clockevent devices
484  */
485 void hv_synic_clockevents_cleanup(void)
486 {
487         int cpu;
488
489         if (!(ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE))
490                 return;
491
492         for_each_online_cpu(cpu)
493                 clockevents_unbind_device(hv_context.clk_evt[cpu], cpu);
494 }
495
496 /*
497  * hv_synic_cleanup - Cleanup routine for hv_synic_init().
498  */
499 void hv_synic_cleanup(void *arg)
500 {
501         union hv_synic_sint shared_sint;
502         union hv_synic_simp simp;
503         union hv_synic_siefp siefp;
504         union hv_synic_scontrol sctrl;
505         int cpu = smp_processor_id();
506
507         if (!hv_context.synic_initialized)
508                 return;
509
510         /* Turn off clockevent device */
511         if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE)
512                 hv_ce_shutdown(hv_context.clk_evt[cpu]);
513
514         rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
515
516         shared_sint.masked = 1;
517
518         /* Need to correctly cleanup in the case of SMP!!! */
519         /* Disable the interrupt */
520         wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
521
522         rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
523         simp.simp_enabled = 0;
524         simp.base_simp_gpa = 0;
525
526         wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
527
528         rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
529         siefp.siefp_enabled = 0;
530         siefp.base_siefp_gpa = 0;
531
532         wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
533
534         /* Disable the global synic bit */
535         rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
536         sctrl.enable = 0;
537         wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
538 }