瀏覽代碼

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>
Liu Yu-B13201 13 年之前
父節點
當前提交
2e1ae9c07d

+ 2 - 0
arch/powerpc/include/asm/epapr_hcalls.h

@@ -153,6 +153,8 @@
 #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
 #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
 #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
 #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
 
 
+extern bool epapr_paravirt_enabled;
+extern u32 epapr_hypercall_start[];
 
 
 /*
 /*
  * We use "uintptr_t" to define a register because it's guaranteed to be a
  * We use "uintptr_t" to define a register because it's guaranteed to be a

+ 1 - 0
arch/powerpc/kernel/Makefile

@@ -128,6 +128,7 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
 obj-y				+= ppc_save_regs.o
 obj-y				+= ppc_save_regs.o
 endif
 endif
 
 
+obj-$(CONFIG_EPAPR_PARAVIRT)	+= epapr_paravirt.o epapr_hcalls.o
 obj-$(CONFIG_KVM_GUEST)		+= kvm.o kvm_emul.o
 obj-$(CONFIG_KVM_GUEST)		+= kvm.o kvm_emul.o
 
 
 # Disable GCOV in odd or sensitive code
 # Disable GCOV in odd or sensitive code

+ 25 - 0
arch/powerpc/kernel/epapr_hcalls.S

@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/threads.h>
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+/* Hypercall entry point. Will be patched with device tree instructions. */
+.global epapr_hypercall_start
+epapr_hypercall_start:
+	li	r3, -1
+	nop
+	nop
+	nop
+	blr

+ 52 - 0
arch/powerpc/kernel/epapr_paravirt.c

@@ -0,0 +1,52 @@
+/*
+ * ePAPR para-virtualization support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ */
+
+#include <linux/of.h>
+#include <asm/epapr_hcalls.h>
+#include <asm/cacheflush.h>
+#include <asm/code-patching.h>
+
+bool epapr_paravirt_enabled;
+
+static int __init epapr_paravirt_init(void)
+{
+	struct device_node *hyper_node;
+	const u32 *insts;
+	int len, i;
+
+	hyper_node = of_find_node_by_path("/hypervisor");
+	if (!hyper_node)
+		return -ENODEV;
+
+	insts = of_get_property(hyper_node, "hcall-instructions", &len);
+	if (!insts)
+		return -ENODEV;
+
+	if (len % 4 || len > (4 * 4))
+		return -ENODEV;
+
+	for (i = 0; i < (len / 4); i++)
+		patch_instruction(epapr_hypercall_start + i, insts[i]);
+
+	epapr_paravirt_enabled = true;
+
+	return 0;
+}
+
+early_initcall(epapr_paravirt_init);

+ 3 - 25
arch/powerpc/kernel/kvm.c

@@ -31,6 +31,7 @@
 #include <asm/cacheflush.h>
 #include <asm/cacheflush.h>
 #include <asm/disassemble.h>
 #include <asm/disassemble.h>
 #include <asm/ppc-opcode.h>
 #include <asm/ppc-opcode.h>
+#include <asm/epapr_hcalls.h>
 
 
 #define KVM_MAGIC_PAGE		(-4096L)
 #define KVM_MAGIC_PAGE		(-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
 #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,
 	unsigned long register r11 asm("r11") = nr;
 	unsigned long register r11 asm("r11") = nr;
 	unsigned long register r12 asm("r12");
 	unsigned long register r12 asm("r12");
 
 
-	asm volatile("bl	kvm_hypercall_start"
+	asm volatile("bl	epapr_hypercall_start"
 		     : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6),
 		     : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6),
 		       "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11),
 		       "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11),
 		       "=r"(r12)
 		       "=r"(r12)
@@ -747,29 +748,6 @@ unsigned long kvm_hypercall(unsigned long *in,
 }
 }
 EXPORT_SYMBOL_GPL(kvm_hypercall);
 EXPORT_SYMBOL_GPL(kvm_hypercall);
 
 
-static int kvm_para_setup(void)
-{
-	extern u32 kvm_hypercall_start;
-	struct device_node *hyper_node;
-	u32 *insts;
-	int len, i;
-
-	hyper_node = of_find_node_by_path("/hypervisor");
-	if (!hyper_node)
-		return -1;
-
-	insts = (u32*)of_get_property(hyper_node, "hcall-instructions", &len);
-	if (len % 4)
-		return -1;
-	if (len > (4 * 4))
-		return -1;
-
-	for (i = 0; i < (len / 4); i++)
-		kvm_patch_ins(&(&kvm_hypercall_start)[i], insts[i]);
-
-	return 0;
-}
-
 static __init void kvm_free_tmp(void)
 static __init void kvm_free_tmp(void)
 {
 {
 	unsigned long start, end;
 	unsigned long start, end;
@@ -791,7 +769,7 @@ static int __init kvm_guest_init(void)
 	if (!kvm_para_available())
 	if (!kvm_para_available())
 		goto free_tmp;
 		goto free_tmp;
 
 
-	if (kvm_para_setup())
+	if (!epapr_paravirt_enabled)
 		goto free_tmp;
 		goto free_tmp;
 
 
 	if (kvm_para_has_feature(KVM_FEATURE_MAGIC_PAGE))
 	if (kvm_para_has_feature(KVM_FEATURE_MAGIC_PAGE))

+ 0 - 10
arch/powerpc/kernel/kvm_emul.S

@@ -24,16 +24,6 @@
 #include <asm/page.h>
 #include <asm/page.h>
 #include <asm/asm-offsets.h>
 #include <asm/asm-offsets.h>
 
 
-/* Hypercall entry point. Will be patched with device tree instructions. */
-
-.global kvm_hypercall_start
-kvm_hypercall_start:
-	li	r3, -1
-	nop
-	nop
-	nop
-	blr
-
 #define KVM_MAGIC_PAGE		(-4096)
 #define KVM_MAGIC_PAGE		(-4096)
 
 
 #ifdef CONFIG_64BIT
 #ifdef CONFIG_64BIT

+ 9 - 0
arch/powerpc/platforms/Kconfig

@@ -25,6 +25,7 @@ source "arch/powerpc/platforms/wsp/Kconfig"
 config KVM_GUEST
 config KVM_GUEST
 	bool "KVM Guest support"
 	bool "KVM Guest support"
 	default n
 	default n
+	select EPAPR_PARAVIRT
 	---help---
 	---help---
 	  This option enables various optimizations for running under the KVM
 	  This option enables various optimizations for running under the KVM
 	  hypervisor. Overhead for the kernel when not running inside KVM should
 	  hypervisor. Overhead for the kernel when not running inside KVM should
@@ -32,6 +33,14 @@ config KVM_GUEST
 
 
 	  In case of doubt, say Y
 	  In case of doubt, say Y
 
 
+config EPAPR_PARAVIRT
+	bool "ePAPR para-virtualization support"
+	default n
+	help
+	  Enables ePAPR para-virtualization support for guests.
+
+	  In case of doubt, say Y
+
 config PPC_NATIVE
 config PPC_NATIVE
 	bool
 	bool
 	depends on 6xx || PPC64
 	depends on 6xx || PPC64