diff options
author | K. Y. Srinivasan <kys@microsoft.com> | 2017-01-18 18:45:02 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-01-19 05:42:07 -0500 |
commit | 8730046c1498e8fb8c9a124789893944e8ce8220 (patch) | |
tree | 0028573415d5e137e05a461338891eb6b21a4945 | |
parent | 352c9624242d5836ad8a960826183011367871a4 (diff) |
Drivers: hv vmbus: Move Hypercall page setup out of common code
As part of the effort to separate out architecture specific code, move the
hypercall page setup to an architecture specific file.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | arch/x86/Kbuild | 3 | ||||
-rw-r--r-- | arch/x86/hyperv/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/hyperv/hv_init.c | 62 | ||||
-rw-r--r-- | arch/x86/include/asm/mshyperv.h | 5 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mshyperv.c | 7 | ||||
-rw-r--r-- | drivers/hv/hv.c | 45 |
7 files changed, 82 insertions, 42 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index c36976d3bd1a..be8de24fd6dd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5962,6 +5962,7 @@ S: Maintained | |||
5962 | F: arch/x86/include/asm/mshyperv.h | 5962 | F: arch/x86/include/asm/mshyperv.h |
5963 | F: arch/x86/include/uapi/asm/hyperv.h | 5963 | F: arch/x86/include/uapi/asm/hyperv.h |
5964 | F: arch/x86/kernel/cpu/mshyperv.c | 5964 | F: arch/x86/kernel/cpu/mshyperv.c |
5965 | F: arch/x86/hyperv | ||
5965 | F: drivers/hid/hid-hyperv.c | 5966 | F: drivers/hid/hid-hyperv.c |
5966 | F: drivers/hv/ | 5967 | F: drivers/hv/ |
5967 | F: drivers/input/serio/hyperv-keyboard.c | 5968 | F: drivers/input/serio/hyperv-keyboard.c |
diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild index eb3abf8ac44e..586b786b3edf 100644 --- a/arch/x86/Kbuild +++ b/arch/x86/Kbuild | |||
@@ -7,6 +7,9 @@ obj-$(CONFIG_KVM) += kvm/ | |||
7 | # Xen paravirtualization support | 7 | # Xen paravirtualization support |
8 | obj-$(CONFIG_XEN) += xen/ | 8 | obj-$(CONFIG_XEN) += xen/ |
9 | 9 | ||
10 | # Hyper-V paravirtualization support | ||
11 | obj-$(CONFIG_HYPERVISOR_GUEST) += hyperv/ | ||
12 | |||
10 | # lguest paravirtualization support | 13 | # lguest paravirtualization support |
11 | obj-$(CONFIG_LGUEST_GUEST) += lguest/ | 14 | obj-$(CONFIG_LGUEST_GUEST) += lguest/ |
12 | 15 | ||
diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile new file mode 100644 index 000000000000..171ae09864d7 --- /dev/null +++ b/arch/x86/hyperv/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-y := hv_init.o | |||
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c new file mode 100644 index 000000000000..3206bfda586d --- /dev/null +++ b/arch/x86/hyperv/hv_init.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * X86 specific Hyper-V initialization code. | ||
3 | * | ||
4 | * Copyright (C) 2016, Microsoft, Inc. | ||
5 | * | ||
6 | * Author : K. Y. Srinivasan <kys@microsoft.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published | ||
10 | * by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
15 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
16 | * details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/types.h> | ||
21 | #include <asm/hypervisor.h> | ||
22 | #include <asm/hyperv.h> | ||
23 | #include <asm/mshyperv.h> | ||
24 | #include <linux/version.h> | ||
25 | #include <linux/vmalloc.h> | ||
26 | #include <linux/mm.h> | ||
27 | |||
28 | void *hv_hypercall_pg; | ||
29 | /* | ||
30 | * This function is to be invoked early in the boot sequence after the | ||
31 | * hypervisor has been detected. | ||
32 | * | ||
33 | * 1. Setup the hypercall page. | ||
34 | */ | ||
35 | void hyperv_init(void) | ||
36 | { | ||
37 | u64 guest_id; | ||
38 | union hv_x64_msr_hypercall_contents hypercall_msr; | ||
39 | |||
40 | if (x86_hyper != &x86_hyper_ms_hyperv) | ||
41 | return; | ||
42 | |||
43 | /* | ||
44 | * Setup the hypercall page and enable hypercalls. | ||
45 | * 1. Register the guest ID | ||
46 | * 2. Enable the hypercall and register the hypercall page | ||
47 | */ | ||
48 | guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0); | ||
49 | wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id); | ||
50 | |||
51 | hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC); | ||
52 | if (hv_hypercall_pg == NULL) { | ||
53 | wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); | ||
54 | return; | ||
55 | } | ||
56 | |||
57 | rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); | ||
58 | hypercall_msr.enable = 1; | ||
59 | hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); | ||
60 | wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); | ||
61 | } | ||
62 | EXPORT_SYMBOL_GPL(hv_hypercall_pg); | ||
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 15a0c275c82e..e5f57e15a507 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h | |||
@@ -80,4 +80,9 @@ void hv_setup_kexec_handler(void (*handler)(void)); | |||
80 | void hv_remove_kexec_handler(void); | 80 | void hv_remove_kexec_handler(void); |
81 | void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); | 81 | void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); |
82 | void hv_remove_crash_handler(void); | 82 | void hv_remove_crash_handler(void); |
83 | |||
84 | #if IS_ENABLED(CONFIG_HYPERV) | ||
85 | void hyperv_init(void); | ||
86 | extern void *hv_hypercall_pg; | ||
87 | #endif | ||
83 | #endif | 88 | #endif |
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 65e20c97e04b..c5a1e9ba9ae0 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c | |||
@@ -227,6 +227,13 @@ static void __init ms_hyperv_init_platform(void) | |||
227 | */ | 227 | */ |
228 | if (efi_enabled(EFI_BOOT)) | 228 | if (efi_enabled(EFI_BOOT)) |
229 | x86_platform.get_nmi_reason = hv_get_nmi_reason; | 229 | x86_platform.get_nmi_reason = hv_get_nmi_reason; |
230 | |||
231 | #if IS_ENABLED(CONFIG_HYPERV) | ||
232 | /* | ||
233 | * Setup the hook to get control post apic initialization. | ||
234 | */ | ||
235 | x86_platform.apic_post_init = hyperv_init; | ||
236 | #endif | ||
230 | } | 237 | } |
231 | 238 | ||
232 | const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { | 239 | const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { |
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 714e1ebc834c..d8d41542d93c 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c | |||
@@ -193,7 +193,6 @@ int hv_init(void) | |||
193 | { | 193 | { |
194 | int max_leaf; | 194 | int max_leaf; |
195 | union hv_x64_msr_hypercall_contents hypercall_msr; | 195 | union hv_x64_msr_hypercall_contents hypercall_msr; |
196 | void *virtaddr = NULL; | ||
197 | 196 | ||
198 | memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS); | 197 | memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS); |
199 | memset(hv_context.synic_message_page, 0, | 198 | memset(hv_context.synic_message_page, 0, |
@@ -211,33 +210,15 @@ int hv_init(void) | |||
211 | 210 | ||
212 | max_leaf = query_hypervisor_info(); | 211 | max_leaf = query_hypervisor_info(); |
213 | 212 | ||
214 | /* | ||
215 | * Write our OS ID. | ||
216 | */ | ||
217 | hv_context.guestid = generate_guest_id(0, LINUX_VERSION_CODE, 0); | ||
218 | wrmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid); | ||
219 | 213 | ||
220 | /* See if the hypercall page is already set */ | 214 | /* See if the hypercall page is already set */ |
221 | rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); | ||
222 | |||
223 | virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC); | ||
224 | |||
225 | if (!virtaddr) | ||
226 | goto cleanup; | ||
227 | |||
228 | hypercall_msr.enable = 1; | ||
229 | |||
230 | hypercall_msr.guest_physical_address = vmalloc_to_pfn(virtaddr); | ||
231 | wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); | ||
232 | |||
233 | /* Confirm that hypercall page did get setup. */ | ||
234 | hypercall_msr.as_uint64 = 0; | 215 | hypercall_msr.as_uint64 = 0; |
235 | rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); | 216 | rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); |
236 | 217 | ||
237 | if (!hypercall_msr.enable) | 218 | if (!hypercall_msr.enable) |
238 | goto cleanup; | 219 | return -ENOTSUPP; |
239 | 220 | ||
240 | hv_context.hypercall_page = virtaddr; | 221 | hv_context.hypercall_page = hv_hypercall_pg; |
241 | 222 | ||
242 | #ifdef CONFIG_X86_64 | 223 | #ifdef CONFIG_X86_64 |
243 | if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) { | 224 | if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) { |
@@ -261,15 +242,6 @@ int hv_init(void) | |||
261 | return 0; | 242 | return 0; |
262 | 243 | ||
263 | cleanup: | 244 | cleanup: |
264 | if (virtaddr) { | ||
265 | if (hypercall_msr.enable) { | ||
266 | hypercall_msr.as_uint64 = 0; | ||
267 | wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); | ||
268 | } | ||
269 | |||
270 | vfree(virtaddr); | ||
271 | } | ||
272 | |||
273 | return -ENOTSUPP; | 245 | return -ENOTSUPP; |
274 | } | 246 | } |
275 | 247 | ||
@@ -280,20 +252,9 @@ cleanup: | |||
280 | */ | 252 | */ |
281 | void hv_cleanup(bool crash) | 253 | void hv_cleanup(bool crash) |
282 | { | 254 | { |
283 | union hv_x64_msr_hypercall_contents hypercall_msr; | ||
284 | |||
285 | /* Reset our OS id */ | ||
286 | wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); | ||
287 | |||
288 | if (hv_context.hypercall_page) { | ||
289 | hypercall_msr.as_uint64 = 0; | ||
290 | wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); | ||
291 | if (!crash) | ||
292 | vfree(hv_context.hypercall_page); | ||
293 | hv_context.hypercall_page = NULL; | ||
294 | } | ||
295 | 255 | ||
296 | #ifdef CONFIG_X86_64 | 256 | #ifdef CONFIG_X86_64 |
257 | union hv_x64_msr_hypercall_contents hypercall_msr; | ||
297 | /* | 258 | /* |
298 | * Cleanup the TSC page based CS. | 259 | * Cleanup the TSC page based CS. |
299 | */ | 260 | */ |