Blame view
drivers/hv/hv.c
10 KB
3e7ee4902 Staging: hv: add ... |
1 |
/* |
3e7ee4902 Staging: hv: add ... |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
* Copyright (c) 2009, Microsoft Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. * * Authors: * Haiyang Zhang <haiyangz@microsoft.com> * Hank Janssen <hjanssen@microsoft.com> * */ |
0a46618d5 staging: hv: Repl... |
22 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
a0086dc51 Staging: hv: remo... |
23 24 |
#include <linux/kernel.h> #include <linux/mm.h> |
5a0e3ad6a include cleanup: ... |
25 |
#include <linux/slab.h> |
b7c947f04 Staging: hv: remo... |
26 |
#include <linux/vmalloc.h> |
46a971913 Staging: hv: move... |
27 |
#include <linux/hyperv.h> |
83ba0c4f3 Drivers: hv: Clea... |
28 |
#include <linux/version.h> |
db11f12a1 Drivers: hv: Mana... |
29 |
#include <linux/interrupt.h> |
407dd1644 Staging: hv: remo... |
30 |
#include <asm/hyperv.h> |
0f2a6619e Staging: hv: vmbu... |
31 |
#include "hyperv_vmbus.h" |
3e7ee4902 Staging: hv: add ... |
32 |
|
454f18a96 Staging: hv: Remo... |
33 |
/* The one and only */ |
6a0aaa185 staging: hv: Conv... |
34 35 36 |
struct hv_context hv_context = { .synic_initialized = false, .hypercall_page = NULL, |
3e7ee4902 Staging: hv: add ... |
37 |
}; |
3e1895195 staging: hv: Corr... |
38 |
/* |
d44890c8d staging: hv: Conv... |
39 |
* query_hypervisor_info - Get version info of the windows hypervisor |
0831ad041 Staging: hv: fix ... |
40 |
*/ |
5fbebb2d2 Drivers: hv: Capt... |
41 42 43 44 |
unsigned int host_info_eax; unsigned int host_info_ebx; unsigned int host_info_ecx; unsigned int host_info_edx; |
d44890c8d staging: hv: Conv... |
45 |
static int query_hypervisor_info(void) |
0831ad041 Staging: hv: fix ... |
46 47 48 49 50 |
{ unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; |
b8dfb264f staging: hv: Conv... |
51 |
unsigned int max_leaf; |
0831ad041 Staging: hv: fix ... |
52 |
unsigned int op; |
3e7ee4902 Staging: hv: add ... |
53 |
|
0831ad041 Staging: hv: fix ... |
54 55 56 57 58 59 60 61 |
/* * Its assumed that this is called after confirming that Viridian * is present. Query id and revision. */ eax = 0; ebx = 0; ecx = 0; edx = 0; |
f6feebe07 staging: hv: Conv... |
62 |
op = HVCPUID_VENDOR_MAXFUNCTION; |
0831ad041 Staging: hv: fix ... |
63 |
cpuid(op, &eax, &ebx, &ecx, &edx); |
3e7ee4902 Staging: hv: add ... |
64 |
|
b8dfb264f staging: hv: Conv... |
65 |
max_leaf = eax; |
0831ad041 Staging: hv: fix ... |
66 |
|
b8dfb264f staging: hv: Conv... |
67 |
if (max_leaf >= HVCPUID_VERSION) { |
0831ad041 Staging: hv: fix ... |
68 69 70 71 |
eax = 0; ebx = 0; ecx = 0; edx = 0; |
f6feebe07 staging: hv: Conv... |
72 |
op = HVCPUID_VERSION; |
0831ad041 Staging: hv: fix ... |
73 |
cpuid(op, &eax, &ebx, &ecx, &edx); |
5fbebb2d2 Drivers: hv: Capt... |
74 75 76 77 |
host_info_eax = eax; host_info_ebx = ebx; host_info_ecx = ecx; host_info_edx = edx; |
0831ad041 Staging: hv: fix ... |
78 |
} |
b8dfb264f staging: hv: Conv... |
79 |
return max_leaf; |
0831ad041 Staging: hv: fix ... |
80 |
} |
3e7ee4902 Staging: hv: add ... |
81 |
|
3e1895195 staging: hv: Corr... |
82 |
/* |
d44890c8d staging: hv: Conv... |
83 |
* do_hypercall- Invoke the specified hypercall |
0831ad041 Staging: hv: fix ... |
84 |
*/ |
d44890c8d staging: hv: Conv... |
85 |
static u64 do_hypercall(u64 control, void *input, void *output) |
3e7ee4902 Staging: hv: add ... |
86 |
{ |
530cf2070 Staging: hv: use ... |
87 |
#ifdef CONFIG_X86_64 |
b8dfb264f staging: hv: Conv... |
88 89 90 |
u64 hv_status = 0; u64 input_address = (input) ? virt_to_phys(input) : 0; u64 output_address = (output) ? virt_to_phys(output) : 0; |
dec317fd6 Staging: hv: vmbu... |
91 |
void *hypercall_page = hv_context.hypercall_page; |
3e7ee4902 Staging: hv: add ... |
92 |
|
b8dfb264f staging: hv: Conv... |
93 94 95 96 |
__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8"); __asm__ __volatile__("call *%3" : "=a" (hv_status) : "c" (control), "d" (input_address), "m" (hypercall_page)); |
3e7ee4902 Staging: hv: add ... |
97 |
|
b8dfb264f staging: hv: Conv... |
98 |
return hv_status; |
3e7ee4902 Staging: hv: add ... |
99 100 |
#else |
b8dfb264f staging: hv: Conv... |
101 102 103 104 105 106 107 108 109 110 |
u32 control_hi = control >> 32; u32 control_lo = control & 0xFFFFFFFF; u32 hv_status_hi = 1; u32 hv_status_lo = 1; u64 input_address = (input) ? virt_to_phys(input) : 0; u32 input_address_hi = input_address >> 32; u32 input_address_lo = input_address & 0xFFFFFFFF; u64 output_address = (output) ? virt_to_phys(output) : 0; u32 output_address_hi = output_address >> 32; u32 output_address_lo = output_address & 0xFFFFFFFF; |
dec317fd6 Staging: hv: vmbu... |
111 |
void *hypercall_page = hv_context.hypercall_page; |
3e7ee4902 Staging: hv: add ... |
112 |
|
b8dfb264f staging: hv: Conv... |
113 114 115 116 117 |
__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi), "=a"(hv_status_lo) : "d" (control_hi), "a" (control_lo), "b" (input_address_hi), "c" (input_address_lo), "D"(output_address_hi), "S"(output_address_lo), "m" (hypercall_page)); |
3e7ee4902 Staging: hv: add ... |
118 |
|
b8dfb264f staging: hv: Conv... |
119 |
return hv_status_lo | ((u64)hv_status_hi << 32); |
0831ad041 Staging: hv: fix ... |
120 |
#endif /* !x86_64 */ |
3e7ee4902 Staging: hv: add ... |
121 |
} |
3e1895195 staging: hv: Corr... |
122 |
/* |
d44890c8d staging: hv: Conv... |
123 |
* hv_init - Main initialization routine. |
0831ad041 Staging: hv: fix ... |
124 125 126 |
* * This routine must be called before any other routines in here are called */ |
d44890c8d staging: hv: Conv... |
127 |
int hv_init(void) |
3e7ee4902 Staging: hv: add ... |
128 |
{ |
b8dfb264f staging: hv: Conv... |
129 130 131 |
int max_leaf; union hv_x64_msr_hypercall_contents hypercall_msr; void *virtaddr = NULL; |
3e7ee4902 Staging: hv: add ... |
132 |
|
14c1bf8a8 drivers: hv: Incr... |
133 |
memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS); |
6a0aaa185 staging: hv: Conv... |
134 |
memset(hv_context.synic_message_page, 0, |
14c1bf8a8 drivers: hv: Incr... |
135 |
sizeof(void *) * NR_CPUS); |
917ea427c Drivers: hv: Setu... |
136 137 |
memset(hv_context.vp_index, 0, sizeof(int) * NR_CPUS); |
db11f12a1 Drivers: hv: Mana... |
138 139 |
memset(hv_context.event_dpc, 0, sizeof(void *) * NR_CPUS); |
3e7ee4902 Staging: hv: add ... |
140 |
|
d44890c8d staging: hv: Conv... |
141 |
max_leaf = query_hypervisor_info(); |
3e7ee4902 Staging: hv: add ... |
142 |
|
83ba0c4f3 Drivers: hv: Clea... |
143 144 145 146 147 |
/* * Write our OS ID. */ hv_context.guestid = generate_guest_id(0, LINUX_VERSION_CODE, 0); wrmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid); |
a73e6b7c5 Staging: hv: Remo... |
148 |
|
454f18a96 Staging: hv: Remo... |
149 |
/* See if the hypercall page is already set */ |
b8dfb264f staging: hv: Conv... |
150 |
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); |
3e7ee4902 Staging: hv: add ... |
151 |
|
df3493e0b Staging: hv: Use ... |
152 |
virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC); |
3e7ee4902 Staging: hv: add ... |
153 |
|
98e087022 staging: hv: Remo... |
154 |
if (!virtaddr) |
44939d37c Staging: hv: Chan... |
155 |
goto cleanup; |
3e7ee4902 Staging: hv: add ... |
156 |
|
b8dfb264f staging: hv: Conv... |
157 |
hypercall_msr.enable = 1; |
a73e6b7c5 Staging: hv: Remo... |
158 |
|
b8dfb264f staging: hv: Conv... |
159 160 |
hypercall_msr.guest_physical_address = vmalloc_to_pfn(virtaddr); wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); |
a73e6b7c5 Staging: hv: Remo... |
161 162 |
/* Confirm that hypercall page did get setup. */ |
b8dfb264f staging: hv: Conv... |
163 164 |
hypercall_msr.as_uint64 = 0; rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); |
a73e6b7c5 Staging: hv: Remo... |
165 |
|
98e087022 staging: hv: Remo... |
166 |
if (!hypercall_msr.enable) |
44939d37c Staging: hv: Chan... |
167 |
goto cleanup; |
3e7ee4902 Staging: hv: add ... |
168 |
|
b8dfb264f staging: hv: Conv... |
169 |
hv_context.hypercall_page = virtaddr; |
a73e6b7c5 Staging: hv: Remo... |
170 |
|
5433e0033 Staging: hv: vmbu... |
171 |
return 0; |
3e7ee4902 Staging: hv: add ... |
172 |
|
44939d37c Staging: hv: Chan... |
173 |
cleanup: |
b8dfb264f staging: hv: Conv... |
174 175 176 177 |
if (virtaddr) { if (hypercall_msr.enable) { hypercall_msr.as_uint64 = 0; wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); |
3e7ee4902 Staging: hv: add ... |
178 |
} |
b8dfb264f staging: hv: Conv... |
179 |
vfree(virtaddr); |
3e7ee4902 Staging: hv: add ... |
180 |
} |
5433e0033 Staging: hv: vmbu... |
181 182 |
return -ENOTSUPP; |
3e7ee4902 Staging: hv: add ... |
183 |
} |
3e1895195 staging: hv: Corr... |
184 |
/* |
d44890c8d staging: hv: Conv... |
185 |
* hv_cleanup - Cleanup routine. |
0831ad041 Staging: hv: fix ... |
186 187 188 |
* * This routine is called normally during driver unloading or exiting. */ |
d44890c8d staging: hv: Conv... |
189 |
void hv_cleanup(void) |
3e7ee4902 Staging: hv: add ... |
190 |
{ |
b8dfb264f staging: hv: Conv... |
191 |
union hv_x64_msr_hypercall_contents hypercall_msr; |
3e7ee4902 Staging: hv: add ... |
192 |
|
93e5bd06a Drivers: hv: Make... |
193 194 |
/* Reset our OS id */ wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); |
6a0aaa185 staging: hv: Conv... |
195 |
if (hv_context.hypercall_page) { |
b8dfb264f staging: hv: Conv... |
196 197 |
hypercall_msr.as_uint64 = 0; wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); |
6a0aaa185 staging: hv: Conv... |
198 199 |
vfree(hv_context.hypercall_page); hv_context.hypercall_page = NULL; |
3e7ee4902 Staging: hv: add ... |
200 |
} |
3e7ee4902 Staging: hv: add ... |
201 |
} |
3e1895195 staging: hv: Corr... |
202 |
/* |
d44890c8d staging: hv: Conv... |
203 |
* hv_post_message - Post a message using the hypervisor message IPC. |
0831ad041 Staging: hv: fix ... |
204 205 206 |
* * This involves a hypercall. */ |
415f0a02a hv: fix return ty... |
207 |
int hv_post_message(union hv_connection_id connection_id, |
b8dfb264f staging: hv: Conv... |
208 209 |
enum hv_message_type message_type, void *payload, size_t payload_size) |
3e7ee4902 Staging: hv: add ... |
210 |
{ |
b8dfb264f staging: hv: Conv... |
211 |
struct aligned_input { |
0831ad041 Staging: hv: fix ... |
212 |
u64 alignment8; |
cba4decdd Staging: hv: codi... |
213 |
struct hv_input_post_message msg; |
3e7ee4902 Staging: hv: add ... |
214 |
}; |
b8dfb264f staging: hv: Conv... |
215 |
struct hv_input_post_message *aligned_msg; |
034469e63 Staging: hv: codi... |
216 |
u16 status; |
c4b0bc948 Staging: hv: remo... |
217 |
unsigned long addr; |
3e7ee4902 Staging: hv: add ... |
218 |
|
b8dfb264f staging: hv: Conv... |
219 |
if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT) |
39594abcd Staging: hv: vmbu... |
220 |
return -EMSGSIZE; |
3e7ee4902 Staging: hv: add ... |
221 |
|
b8dfb264f staging: hv: Conv... |
222 |
addr = (unsigned long)kmalloc(sizeof(struct aligned_input), GFP_ATOMIC); |
3e7ee4902 Staging: hv: add ... |
223 |
if (!addr) |
39594abcd Staging: hv: vmbu... |
224 |
return -ENOMEM; |
3e7ee4902 Staging: hv: add ... |
225 |
|
b8dfb264f staging: hv: Conv... |
226 |
aligned_msg = (struct hv_input_post_message *) |
735096819 staging/hv/osd: d... |
227 |
(ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN)); |
3e7ee4902 Staging: hv: add ... |
228 |
|
b8dfb264f staging: hv: Conv... |
229 230 231 232 |
aligned_msg->connectionid = connection_id; aligned_msg->message_type = message_type; aligned_msg->payload_size = payload_size; memcpy((void *)aligned_msg->payload, payload, payload_size); |
3e7ee4902 Staging: hv: add ... |
233 |
|
d44890c8d staging: hv: Conv... |
234 235 |
status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL) & 0xFFFF; |
3e7ee4902 Staging: hv: add ... |
236 |
|
0831ad041 Staging: hv: fix ... |
237 |
kfree((void *)addr); |
3e7ee4902 Staging: hv: add ... |
238 239 240 |
return status; } |
3e1895195 staging: hv: Corr... |
241 |
/* |
d44890c8d staging: hv: Conv... |
242 243 |
* hv_signal_event - * Signal an event on the specified connection using the hypervisor event IPC. |
0831ad041 Staging: hv: fix ... |
244 245 246 |
* * This involves a hypercall. */ |
1f42248d7 Drivers: hv: Chan... |
247 |
u16 hv_signal_event(void *con_id) |
3e7ee4902 Staging: hv: add ... |
248 |
{ |
034469e63 Staging: hv: codi... |
249 |
u16 status; |
3e7ee4902 Staging: hv: add ... |
250 |
|
1f42248d7 Drivers: hv: Chan... |
251 |
status = (do_hypercall(HVCALL_SIGNAL_EVENT, con_id, NULL) & 0xFFFF); |
3e7ee4902 Staging: hv: add ... |
252 253 |
return status; } |
3e1895195 staging: hv: Corr... |
254 |
/* |
d44890c8d staging: hv: Conv... |
255 |
* hv_synic_init - Initialize the Synthethic Interrupt Controller. |
0831ad041 Staging: hv: fix ... |
256 257 258 259 260 |
* * If it is already initialized by another entity (ie x2v shim), we need to * retrieve the initialized message and event pages. Otherwise, we create and * initialize the message and event pages. */ |
302a3c0f2 Drivers: hv: vmbu... |
261 |
void hv_synic_init(void *arg) |
3e7ee4902 Staging: hv: add ... |
262 |
{ |
0831ad041 Staging: hv: fix ... |
263 |
u64 version; |
eacb1b4d2 Staging: hv: typd... |
264 265 |
union hv_synic_simp simp; union hv_synic_siefp siefp; |
b8dfb264f staging: hv: Conv... |
266 |
union hv_synic_sint shared_sint; |
eacb1b4d2 Staging: hv: typd... |
267 |
union hv_synic_scontrol sctrl; |
917ea427c Drivers: hv: Setu... |
268 |
u64 vp_index; |
a73e6b7c5 Staging: hv: Remo... |
269 |
|
7692fd4d4 Staging: hv: fix ... |
270 |
int cpu = smp_processor_id(); |
3e7ee4902 Staging: hv: add ... |
271 |
|
6a0aaa185 staging: hv: Conv... |
272 |
if (!hv_context.hypercall_page) |
7692fd4d4 Staging: hv: fix ... |
273 |
return; |
3e7ee4902 Staging: hv: add ... |
274 |
|
454f18a96 Staging: hv: Remo... |
275 |
/* Check the version */ |
a51ed7d65 Staging: hv: remo... |
276 |
rdmsrl(HV_X64_MSR_SVERSION, version); |
3e7ee4902 Staging: hv: add ... |
277 |
|
333494842 driver: hv: remov... |
278 279 |
hv_context.event_dpc[cpu] = kmalloc(sizeof(struct tasklet_struct), GFP_ATOMIC); |
db11f12a1 Drivers: hv: Mana... |
280 281 282 283 284 285 |
if (hv_context.event_dpc[cpu] == NULL) { pr_err("Unable to allocate event dpc "); goto cleanup; } tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu); |
6a0aaa185 staging: hv: Conv... |
286 287 |
hv_context.synic_message_page[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); |
3e7ee4902 Staging: hv: add ... |
288 |
|
6a0aaa185 staging: hv: Conv... |
289 |
if (hv_context.synic_message_page[cpu] == NULL) { |
0a46618d5 staging: hv: Repl... |
290 291 |
pr_err("Unable to allocate SYNIC message page "); |
44939d37c Staging: hv: Chan... |
292 |
goto cleanup; |
a73e6b7c5 Staging: hv: Remo... |
293 |
} |
3e7ee4902 Staging: hv: add ... |
294 |
|
6a0aaa185 staging: hv: Conv... |
295 296 |
hv_context.synic_event_page[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); |
3e7ee4902 Staging: hv: add ... |
297 |
|
6a0aaa185 staging: hv: Conv... |
298 |
if (hv_context.synic_event_page[cpu] == NULL) { |
0a46618d5 staging: hv: Repl... |
299 300 |
pr_err("Unable to allocate SYNIC event page "); |
44939d37c Staging: hv: Chan... |
301 |
goto cleanup; |
a73e6b7c5 Staging: hv: Remo... |
302 |
} |
3e7ee4902 Staging: hv: add ... |
303 |
|
a73e6b7c5 Staging: hv: Remo... |
304 |
/* Setup the Synic's message page */ |
f6feebe07 staging: hv: Conv... |
305 306 |
rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64); simp.simp_enabled = 1; |
6a0aaa185 staging: hv: Conv... |
307 |
simp.base_simp_gpa = virt_to_phys(hv_context.synic_message_page[cpu]) |
a73e6b7c5 Staging: hv: Remo... |
308 |
>> PAGE_SHIFT; |
3e7ee4902 Staging: hv: add ... |
309 |
|
f6feebe07 staging: hv: Conv... |
310 |
wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64); |
3e7ee4902 Staging: hv: add ... |
311 |
|
a73e6b7c5 Staging: hv: Remo... |
312 |
/* Setup the Synic's event page */ |
f6feebe07 staging: hv: Conv... |
313 314 |
rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); siefp.siefp_enabled = 1; |
6a0aaa185 staging: hv: Conv... |
315 |
siefp.base_siefp_gpa = virt_to_phys(hv_context.synic_event_page[cpu]) |
a73e6b7c5 Staging: hv: Remo... |
316 |
>> PAGE_SHIFT; |
f6feebe07 staging: hv: Conv... |
317 |
wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); |
0831ad041 Staging: hv: fix ... |
318 |
|
0831ad041 Staging: hv: fix ... |
319 |
/* Setup the shared SINT. */ |
b8dfb264f staging: hv: Conv... |
320 |
rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); |
3e7ee4902 Staging: hv: add ... |
321 |
|
b8dfb264f staging: hv: Conv... |
322 |
shared_sint.as_uint64 = 0; |
302a3c0f2 Drivers: hv: vmbu... |
323 |
shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR; |
b8dfb264f staging: hv: Conv... |
324 |
shared_sint.masked = false; |
b0209501d Drivers: hv: Hand... |
325 |
shared_sint.auto_eoi = true; |
3e7ee4902 Staging: hv: add ... |
326 |
|
b8dfb264f staging: hv: Conv... |
327 |
wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); |
3e7ee4902 Staging: hv: add ... |
328 |
|
454f18a96 Staging: hv: Remo... |
329 |
/* Enable the global synic bit */ |
f6feebe07 staging: hv: Conv... |
330 331 |
rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64); sctrl.enable = 1; |
3e7ee4902 Staging: hv: add ... |
332 |
|
f6feebe07 staging: hv: Conv... |
333 |
wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64); |
3e7ee4902 Staging: hv: add ... |
334 |
|
6a0aaa185 staging: hv: Conv... |
335 |
hv_context.synic_initialized = true; |
917ea427c Drivers: hv: Setu... |
336 337 338 339 340 341 342 343 |
/* * Setup the mapping between Hyper-V's notion * of cpuid and Linux' notion of cpuid. * This array will be indexed using Linux cpuid. */ rdmsrl(HV_X64_MSR_VP_INDEX, vp_index); hv_context.vp_index[cpu] = (u32)vp_index; |
7692fd4d4 Staging: hv: fix ... |
344 |
return; |
3e7ee4902 Staging: hv: add ... |
345 |
|
44939d37c Staging: hv: Chan... |
346 |
cleanup: |
6a0aaa185 staging: hv: Conv... |
347 |
if (hv_context.synic_event_page[cpu]) |
df3493e0b Staging: hv: Use ... |
348 |
free_page((unsigned long)hv_context.synic_event_page[cpu]); |
3e7ee4902 Staging: hv: add ... |
349 |
|
6a0aaa185 staging: hv: Conv... |
350 |
if (hv_context.synic_message_page[cpu]) |
df3493e0b Staging: hv: Use ... |
351 |
free_page((unsigned long)hv_context.synic_message_page[cpu]); |
7692fd4d4 Staging: hv: fix ... |
352 |
return; |
3e7ee4902 Staging: hv: add ... |
353 |
} |
3e1895195 staging: hv: Corr... |
354 |
/* |
d44890c8d staging: hv: Conv... |
355 |
* hv_synic_cleanup - Cleanup routine for hv_synic_init(). |
0831ad041 Staging: hv: fix ... |
356 |
*/ |
d44890c8d staging: hv: Conv... |
357 |
void hv_synic_cleanup(void *arg) |
3e7ee4902 Staging: hv: add ... |
358 |
{ |
b8dfb264f staging: hv: Conv... |
359 |
union hv_synic_sint shared_sint; |
eacb1b4d2 Staging: hv: typd... |
360 361 |
union hv_synic_simp simp; union hv_synic_siefp siefp; |
7692fd4d4 Staging: hv: fix ... |
362 |
int cpu = smp_processor_id(); |
3e7ee4902 Staging: hv: add ... |
363 |
|
6a0aaa185 staging: hv: Conv... |
364 |
if (!hv_context.synic_initialized) |
3e7ee4902 Staging: hv: add ... |
365 |
return; |
3e7ee4902 Staging: hv: add ... |
366 |
|
b8dfb264f staging: hv: Conv... |
367 |
rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); |
3e7ee4902 Staging: hv: add ... |
368 |
|
b8dfb264f staging: hv: Conv... |
369 |
shared_sint.masked = 1; |
3e7ee4902 Staging: hv: add ... |
370 |
|
7692fd4d4 Staging: hv: fix ... |
371 |
/* Need to correctly cleanup in the case of SMP!!! */ |
454f18a96 Staging: hv: Remo... |
372 |
/* Disable the interrupt */ |
b8dfb264f staging: hv: Conv... |
373 |
wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); |
3e7ee4902 Staging: hv: add ... |
374 |
|
f6feebe07 staging: hv: Conv... |
375 376 377 |
rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64); simp.simp_enabled = 0; simp.base_simp_gpa = 0; |
3e7ee4902 Staging: hv: add ... |
378 |
|
f6feebe07 staging: hv: Conv... |
379 |
wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64); |
3e7ee4902 Staging: hv: add ... |
380 |
|
f6feebe07 staging: hv: Conv... |
381 382 383 |
rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); siefp.siefp_enabled = 0; siefp.base_siefp_gpa = 0; |
3e7ee4902 Staging: hv: add ... |
384 |
|
f6feebe07 staging: hv: Conv... |
385 |
wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); |
3e7ee4902 Staging: hv: add ... |
386 |
|
df3493e0b Staging: hv: Use ... |
387 388 |
free_page((unsigned long)hv_context.synic_message_page[cpu]); free_page((unsigned long)hv_context.synic_event_page[cpu]); |
3e7ee4902 Staging: hv: add ... |
389 |
} |