diff options
Diffstat (limited to 'drivers/hv/hv.c')
-rw-r--r-- | drivers/hv/hv.c | 72 |
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 @@ | |||
34 | struct hv_context hv_context = { | 35 | struct 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 | */ |
43 | unsigned int host_info_eax; | ||
44 | unsigned int host_info_ebx; | ||
45 | unsigned int host_info_ecx; | ||
46 | unsigned int host_info_edx; | ||
47 | |||
44 | static int query_hypervisor_info(void) | 48 | static 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 | ||
191 | cleanup: | 178 | cleanup: |
@@ -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 | */ |
276 | u16 hv_signal_event(void) | 259 | u16 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 | ||
361 | cleanup: | 361 | cleanup: |