aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv/hv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv/hv.c')
-rw-r--r--drivers/hv/hv.c72
1 files changed, 36 insertions, 36 deletions
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 3648f8f0f368..1c5481da6e4a 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -27,6 +27,7 @@
27#include <linux/vmalloc.h> 27#include <linux/vmalloc.h>
28#include <linux/hyperv.h> 28#include <linux/hyperv.h>
29#include <linux/version.h> 29#include <linux/version.h>
30#include <linux/interrupt.h>
30#include <asm/hyperv.h> 31#include <asm/hyperv.h>
31#include "hyperv_vmbus.h" 32#include "hyperv_vmbus.h"
32 33
@@ -34,13 +35,16 @@
34struct hv_context hv_context = { 35struct hv_context hv_context = {
35 .synic_initialized = false, 36 .synic_initialized = false,
36 .hypercall_page = NULL, 37 .hypercall_page = NULL,
37 .signal_event_param = NULL,
38 .signal_event_buffer = NULL,
39}; 38};
40 39
41/* 40/*
42 * query_hypervisor_info - Get version info of the windows hypervisor 41 * query_hypervisor_info - Get version info of the windows hypervisor
43 */ 42 */
43unsigned int host_info_eax;
44unsigned int host_info_ebx;
45unsigned int host_info_ecx;
46unsigned int host_info_edx;
47
44static int query_hypervisor_info(void) 48static int query_hypervisor_info(void)
45{ 49{
46 unsigned int eax; 50 unsigned int eax;
@@ -70,13 +74,10 @@ static int query_hypervisor_info(void)
70 edx = 0; 74 edx = 0;
71 op = HVCPUID_VERSION; 75 op = HVCPUID_VERSION;
72 cpuid(op, &eax, &ebx, &ecx, &edx); 76 cpuid(op, &eax, &ebx, &ecx, &edx);
73 pr_info("Hyper-V Host OS Build:%d-%d.%d-%d-%d.%d\n", 77 host_info_eax = eax;
74 eax, 78 host_info_ebx = ebx;
75 ebx >> 16, 79 host_info_ecx = ecx;
76 ebx & 0xFFFF, 80 host_info_edx = edx;
77 ecx,
78 edx >> 24,
79 edx & 0xFFFFFF);
80 } 81 }
81 return max_leaf; 82 return max_leaf;
82} 83}
@@ -137,6 +138,10 @@ int hv_init(void)
137 memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS); 138 memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
138 memset(hv_context.synic_message_page, 0, 139 memset(hv_context.synic_message_page, 0,
139 sizeof(void *) * NR_CPUS); 140 sizeof(void *) * NR_CPUS);
141 memset(hv_context.vp_index, 0,
142 sizeof(int) * NR_CPUS);
143 memset(hv_context.event_dpc, 0,
144 sizeof(void *) * NR_CPUS);
140 145
141 max_leaf = query_hypervisor_info(); 146 max_leaf = query_hypervisor_info();
142 147
@@ -168,24 +173,6 @@ int hv_init(void)
168 173
169 hv_context.hypercall_page = virtaddr; 174 hv_context.hypercall_page = virtaddr;
170 175
171 /* Setup the global signal event param for the signal event hypercall */
172 hv_context.signal_event_buffer =
173 kmalloc(sizeof(struct hv_input_signal_event_buffer),
174 GFP_KERNEL);
175 if (!hv_context.signal_event_buffer)
176 goto cleanup;
177
178 hv_context.signal_event_param =
179 (struct hv_input_signal_event *)
180 (ALIGN((unsigned long)
181 hv_context.signal_event_buffer,
182 HV_HYPERCALL_PARAM_ALIGN));
183 hv_context.signal_event_param->connectionid.asu32 = 0;
184 hv_context.signal_event_param->connectionid.u.id =
185 VMBUS_EVENT_CONNECTION_ID;
186 hv_context.signal_event_param->flag_number = 0;
187 hv_context.signal_event_param->rsvdz = 0;
188
189 return 0; 176 return 0;
190 177
191cleanup: 178cleanup:
@@ -213,10 +200,6 @@ void hv_cleanup(void)
213 /* Reset our OS id */ 200 /* Reset our OS id */
214 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); 201 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
215 202
216 kfree(hv_context.signal_event_buffer);
217 hv_context.signal_event_buffer = NULL;
218 hv_context.signal_event_param = NULL;
219
220 if (hv_context.hypercall_page) { 203 if (hv_context.hypercall_page) {
221 hypercall_msr.as_uint64 = 0; 204 hypercall_msr.as_uint64 = 0;
222 wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 205 wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
@@ -273,13 +256,12 @@ int hv_post_message(union hv_connection_id connection_id,
273 * 256 *
274 * This involves a hypercall. 257 * This involves a hypercall.
275 */ 258 */
276u16 hv_signal_event(void) 259u16 hv_signal_event(void *con_id)
277{ 260{
278 u16 status; 261 u16 status;
279 262
280 status = do_hypercall(HVCALL_SIGNAL_EVENT, 263 status = (do_hypercall(HVCALL_SIGNAL_EVENT, con_id, NULL) & 0xFFFF);
281 hv_context.signal_event_param, 264
282 NULL) & 0xFFFF;
283 return status; 265 return status;
284} 266}
285 267
@@ -297,6 +279,7 @@ void hv_synic_init(void *irqarg)
297 union hv_synic_siefp siefp; 279 union hv_synic_siefp siefp;
298 union hv_synic_sint shared_sint; 280 union hv_synic_sint shared_sint;
299 union hv_synic_scontrol sctrl; 281 union hv_synic_scontrol sctrl;
282 u64 vp_index;
300 283
301 u32 irq_vector = *((u32 *)(irqarg)); 284 u32 irq_vector = *((u32 *)(irqarg));
302 int cpu = smp_processor_id(); 285 int cpu = smp_processor_id();
@@ -307,6 +290,15 @@ void hv_synic_init(void *irqarg)
307 /* Check the version */ 290 /* Check the version */
308 rdmsrl(HV_X64_MSR_SVERSION, version); 291 rdmsrl(HV_X64_MSR_SVERSION, version);
309 292
293 hv_context.event_dpc[cpu] = (struct tasklet_struct *)
294 kmalloc(sizeof(struct tasklet_struct),
295 GFP_ATOMIC);
296 if (hv_context.event_dpc[cpu] == NULL) {
297 pr_err("Unable to allocate event dpc\n");
298 goto cleanup;
299 }
300 tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu);
301
310 hv_context.synic_message_page[cpu] = 302 hv_context.synic_message_page[cpu] =
311 (void *)get_zeroed_page(GFP_ATOMIC); 303 (void *)get_zeroed_page(GFP_ATOMIC);
312 304
@@ -345,7 +337,7 @@ void hv_synic_init(void *irqarg)
345 shared_sint.as_uint64 = 0; 337 shared_sint.as_uint64 = 0;
346 shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */ 338 shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
347 shared_sint.masked = false; 339 shared_sint.masked = false;
348 shared_sint.auto_eoi = false; 340 shared_sint.auto_eoi = true;
349 341
350 wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); 342 wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
351 343
@@ -356,6 +348,14 @@ void hv_synic_init(void *irqarg)
356 wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64); 348 wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
357 349
358 hv_context.synic_initialized = true; 350 hv_context.synic_initialized = true;
351
352 /*
353 * Setup the mapping between Hyper-V's notion
354 * of cpuid and Linux' notion of cpuid.
355 * This array will be indexed using Linux cpuid.
356 */
357 rdmsrl(HV_X64_MSR_VP_INDEX, vp_index);
358 hv_context.vp_index[cpu] = (u32)vp_index;
359 return; 359 return;
360 360
361cleanup: 361cleanup: