diff options
author | Liu Yu-B13201 <Yu.Liu@freescale.com> | 2012-03-15 06:52:13 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2012-05-30 05:43:10 -0400 |
commit | 2e1ae9c07df5956ebab19144aa0da58ea37c9f69 (patch) | |
tree | 5ec9b74d22b72af3691897921ca6bce76ea7d4aa /arch/powerpc | |
parent | b48b2c3e50433ff6f7e46186daa7f986bd960215 (diff) |
KVM: PPC: Factor out guest epapr initialization
epapr paravirtualization support is now a Kconfig
selectable option
Signed-off-by: Liu Yu <yu.liu@freescale.com>
[stuart.yoder@freescale.com: misc minor fixes, description update]
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/epapr_hcalls.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/epapr_hcalls.S | 25 | ||||
-rw-r--r-- | arch/powerpc/kernel/epapr_paravirt.c | 52 | ||||
-rw-r--r-- | arch/powerpc/kernel/kvm.c | 28 | ||||
-rw-r--r-- | arch/powerpc/kernel/kvm_emul.S | 10 | ||||
-rw-r--r-- | arch/powerpc/platforms/Kconfig | 9 |
7 files changed, 92 insertions, 35 deletions
diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h index 976835d8f22e..bf2c06c33871 100644 --- a/arch/powerpc/include/asm/epapr_hcalls.h +++ b/arch/powerpc/include/asm/epapr_hcalls.h | |||
@@ -153,6 +153,8 @@ | |||
153 | #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5" | 153 | #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5" |
154 | #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4" | 154 | #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4" |
155 | 155 | ||
156 | extern bool epapr_paravirt_enabled; | ||
157 | extern u32 epapr_hypercall_start[]; | ||
156 | 158 | ||
157 | /* | 159 | /* |
158 | * We use "uintptr_t" to define a register because it's guaranteed to be a | 160 | * We use "uintptr_t" to define a register because it's guaranteed to be a |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 83afacd3ba7b..bb282dd81612 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -128,6 +128,7 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),) | |||
128 | obj-y += ppc_save_regs.o | 128 | obj-y += ppc_save_regs.o |
129 | endif | 129 | endif |
130 | 130 | ||
131 | obj-$(CONFIG_EPAPR_PARAVIRT) += epapr_paravirt.o epapr_hcalls.o | ||
131 | obj-$(CONFIG_KVM_GUEST) += kvm.o kvm_emul.o | 132 | obj-$(CONFIG_KVM_GUEST) += kvm.o kvm_emul.o |
132 | 133 | ||
133 | # Disable GCOV in odd or sensitive code | 134 | # Disable GCOV in odd or sensitive code |
diff --git a/arch/powerpc/kernel/epapr_hcalls.S b/arch/powerpc/kernel/epapr_hcalls.S new file mode 100644 index 000000000000..697b390ebfd8 --- /dev/null +++ b/arch/powerpc/kernel/epapr_hcalls.S | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/threads.h> | ||
11 | #include <asm/reg.h> | ||
12 | #include <asm/page.h> | ||
13 | #include <asm/cputable.h> | ||
14 | #include <asm/thread_info.h> | ||
15 | #include <asm/ppc_asm.h> | ||
16 | #include <asm/asm-offsets.h> | ||
17 | |||
18 | /* Hypercall entry point. Will be patched with device tree instructions. */ | ||
19 | .global epapr_hypercall_start | ||
20 | epapr_hypercall_start: | ||
21 | li r3, -1 | ||
22 | nop | ||
23 | nop | ||
24 | nop | ||
25 | blr | ||
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c new file mode 100644 index 000000000000..028aeae370b6 --- /dev/null +++ b/arch/powerpc/kernel/epapr_paravirt.c | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * ePAPR para-virtualization support. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License, version 2, as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | * | ||
17 | * Copyright (C) 2012 Freescale Semiconductor, Inc. | ||
18 | */ | ||
19 | |||
20 | #include <linux/of.h> | ||
21 | #include <asm/epapr_hcalls.h> | ||
22 | #include <asm/cacheflush.h> | ||
23 | #include <asm/code-patching.h> | ||
24 | |||
25 | bool epapr_paravirt_enabled; | ||
26 | |||
27 | static int __init epapr_paravirt_init(void) | ||
28 | { | ||
29 | struct device_node *hyper_node; | ||
30 | const u32 *insts; | ||
31 | int len, i; | ||
32 | |||
33 | hyper_node = of_find_node_by_path("/hypervisor"); | ||
34 | if (!hyper_node) | ||
35 | return -ENODEV; | ||
36 | |||
37 | insts = of_get_property(hyper_node, "hcall-instructions", &len); | ||
38 | if (!insts) | ||
39 | return -ENODEV; | ||
40 | |||
41 | if (len % 4 || len > (4 * 4)) | ||
42 | return -ENODEV; | ||
43 | |||
44 | for (i = 0; i < (len / 4); i++) | ||
45 | patch_instruction(epapr_hypercall_start + i, insts[i]); | ||
46 | |||
47 | epapr_paravirt_enabled = true; | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | early_initcall(epapr_paravirt_init); | ||
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c index 62bdf2389669..1c13307e0308 100644 --- a/arch/powerpc/kernel/kvm.c +++ b/arch/powerpc/kernel/kvm.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/cacheflush.h> | 31 | #include <asm/cacheflush.h> |
32 | #include <asm/disassemble.h> | 32 | #include <asm/disassemble.h> |
33 | #include <asm/ppc-opcode.h> | 33 | #include <asm/ppc-opcode.h> |
34 | #include <asm/epapr_hcalls.h> | ||
34 | 35 | ||
35 | #define KVM_MAGIC_PAGE (-4096L) | 36 | #define KVM_MAGIC_PAGE (-4096L) |
36 | #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x) | 37 | #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x) |
@@ -726,7 +727,7 @@ unsigned long kvm_hypercall(unsigned long *in, | |||
726 | unsigned long register r11 asm("r11") = nr; | 727 | unsigned long register r11 asm("r11") = nr; |
727 | unsigned long register r12 asm("r12"); | 728 | unsigned long register r12 asm("r12"); |
728 | 729 | ||
729 | asm volatile("bl kvm_hypercall_start" | 730 | asm volatile("bl epapr_hypercall_start" |
730 | : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6), | 731 | : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6), |
731 | "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11), | 732 | "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11), |
732 | "=r"(r12) | 733 | "=r"(r12) |
@@ -747,29 +748,6 @@ unsigned long kvm_hypercall(unsigned long *in, | |||
747 | } | 748 | } |
748 | EXPORT_SYMBOL_GPL(kvm_hypercall); | 749 | EXPORT_SYMBOL_GPL(kvm_hypercall); |
749 | 750 | ||
750 | static int kvm_para_setup(void) | ||
751 | { | ||
752 | extern u32 kvm_hypercall_start; | ||
753 | struct device_node *hyper_node; | ||
754 | u32 *insts; | ||
755 | int len, i; | ||
756 | |||
757 | hyper_node = of_find_node_by_path("/hypervisor"); | ||
758 | if (!hyper_node) | ||
759 | return -1; | ||
760 | |||
761 | insts = (u32*)of_get_property(hyper_node, "hcall-instructions", &len); | ||
762 | if (len % 4) | ||
763 | return -1; | ||
764 | if (len > (4 * 4)) | ||
765 | return -1; | ||
766 | |||
767 | for (i = 0; i < (len / 4); i++) | ||
768 | kvm_patch_ins(&(&kvm_hypercall_start)[i], insts[i]); | ||
769 | |||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | static __init void kvm_free_tmp(void) | 751 | static __init void kvm_free_tmp(void) |
774 | { | 752 | { |
775 | unsigned long start, end; | 753 | unsigned long start, end; |
@@ -791,7 +769,7 @@ static int __init kvm_guest_init(void) | |||
791 | if (!kvm_para_available()) | 769 | if (!kvm_para_available()) |
792 | goto free_tmp; | 770 | goto free_tmp; |
793 | 771 | ||
794 | if (kvm_para_setup()) | 772 | if (!epapr_paravirt_enabled) |
795 | goto free_tmp; | 773 | goto free_tmp; |
796 | 774 | ||
797 | if (kvm_para_has_feature(KVM_FEATURE_MAGIC_PAGE)) | 775 | if (kvm_para_has_feature(KVM_FEATURE_MAGIC_PAGE)) |
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S index e291cf3cf954..62ceb2ac82cf 100644 --- a/arch/powerpc/kernel/kvm_emul.S +++ b/arch/powerpc/kernel/kvm_emul.S | |||
@@ -24,16 +24,6 @@ | |||
24 | #include <asm/page.h> | 24 | #include <asm/page.h> |
25 | #include <asm/asm-offsets.h> | 25 | #include <asm/asm-offsets.h> |
26 | 26 | ||
27 | /* Hypercall entry point. Will be patched with device tree instructions. */ | ||
28 | |||
29 | .global kvm_hypercall_start | ||
30 | kvm_hypercall_start: | ||
31 | li r3, -1 | ||
32 | nop | ||
33 | nop | ||
34 | nop | ||
35 | blr | ||
36 | |||
37 | #define KVM_MAGIC_PAGE (-4096) | 27 | #define KVM_MAGIC_PAGE (-4096) |
38 | 28 | ||
39 | #ifdef CONFIG_64BIT | 29 | #ifdef CONFIG_64BIT |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index a35ca44ade66..e7a896acd982 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -25,6 +25,7 @@ source "arch/powerpc/platforms/wsp/Kconfig" | |||
25 | config KVM_GUEST | 25 | config KVM_GUEST |
26 | bool "KVM Guest support" | 26 | bool "KVM Guest support" |
27 | default n | 27 | default n |
28 | select EPAPR_PARAVIRT | ||
28 | ---help--- | 29 | ---help--- |
29 | This option enables various optimizations for running under the KVM | 30 | This option enables various optimizations for running under the KVM |
30 | hypervisor. Overhead for the kernel when not running inside KVM should | 31 | hypervisor. Overhead for the kernel when not running inside KVM should |
@@ -32,6 +33,14 @@ config KVM_GUEST | |||
32 | 33 | ||
33 | In case of doubt, say Y | 34 | In case of doubt, say Y |
34 | 35 | ||
36 | config EPAPR_PARAVIRT | ||
37 | bool "ePAPR para-virtualization support" | ||
38 | default n | ||
39 | help | ||
40 | Enables ePAPR para-virtualization support for guests. | ||
41 | |||
42 | In case of doubt, say Y | ||
43 | |||
35 | config PPC_NATIVE | 44 | config PPC_NATIVE |
36 | bool | 45 | bool |
37 | depends on 6xx || PPC64 | 46 | depends on 6xx || PPC64 |