All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] KVM: PPC: epapr: Factor out the epapr init
@ 2012-01-05  9:06 ` Liu Yu
  0 siblings, 0 replies; 15+ messages in thread
From: Liu Yu @ 2012-01-05  9:06 UTC (permalink / raw)
  To: agraf, kvm-ppc, kvm; +Cc: linuxppc-dev, galak, scottwood, timur, Liu Yu

from the kvm guest paravirt init code.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
 arch/powerpc/include/asm/epapr_hcalls.h |    8 +++++
 arch/powerpc/kernel/Makefile            |    1 +
 arch/powerpc/kernel/epapr_para.c        |   45 +++++++++++++++++++++++++++++++
 arch/powerpc/kernel/kvm.c               |    9 +++++-
 4 files changed, 62 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/kernel/epapr_para.c

diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
index f3b0c2c..c4b86e4 100644
--- a/arch/powerpc/include/asm/epapr_hcalls.h
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -148,6 +148,14 @@
 #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
 #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
 
+extern u32 *epapr_hcall_insts;
+extern int epapr_hcall_insts_len;
+
+static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
+{
+	*instp = epapr_hcall_insts;
+	*lenp = epapr_hcall_insts_len;
+}
 
 /*
  * 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 ce4f7f1..1052bbc 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -134,6 +134,7 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
 obj-y				+= ppc_save_regs.o
 endif
 
+obj-$(CONFIG_BOOKE)		+= epapr_para.o
 obj-$(CONFIG_KVM_GUEST)		+= kvm.o kvm_emul.o
 
 # Disable GCOV in odd or sensitive code
diff --git a/arch/powerpc/kernel/epapr_para.c b/arch/powerpc/kernel/epapr_para.c
new file mode 100644
index 0000000..714dcb3
--- /dev/null
+++ b/arch/powerpc/kernel/epapr_para.c
@@ -0,0 +1,45 @@
+/*
+ * 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>
+
+u32 *epapr_hcall_insts;
+int epapr_hcall_insts_len;
+
+static int __init epapr_para_init(void)
+{
+	struct device_node *hyper_node;
+	u32 *insts;
+	int len;
+
+	hyper_node = of_find_node_by_path("/hypervisor");
+	if (!hyper_node)
+		return -ENODEV;
+
+	insts = (u32*)of_get_property(hyper_node, "hcall-instructions", &len);
+	if (!(len % 4) && (len >= (4 * 4))) {
+		epapr_hcall_insts = insts;
+		epapr_hcall_insts_len = len;
+	}
+
+	return 0;
+}
+
+early_initcall(epapr_para_init);
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index b06bdae..82a9137 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -28,6 +28,7 @@
 #include <asm/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/disassemble.h>
+#include <asm/epapr_hcalls.h>
 
 #define KVM_MAGIC_PAGE		(-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
@@ -535,9 +536,10 @@ 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;
+#ifndef CONFIG_BOOKE
+	struct device_node *hyper_node;
 
 	hyper_node = of_find_node_by_path("/hypervisor");
 	if (!hyper_node)
@@ -548,6 +550,11 @@ static int kvm_para_setup(void)
 		return -1;
 	if (len > (4 * 4))
 		return -1;
+#else
+	epapr_get_hcall_insts(&insts, &len);
+	if (insts = NULL)
+		return -1;
+#endif	/* !BOOKE */
 
 	for (i = 0; i < (len / 4); i++)
 		kvm_patch_ins(&(&kvm_hypercall_start)[i], insts[i]);
-- 
1.6.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 1/3] KVM: PPC: epapr: Factor out the epapr init
@ 2012-01-05  9:06 ` Liu Yu
  0 siblings, 0 replies; 15+ messages in thread
From: Liu Yu @ 2012-01-05  9:06 UTC (permalink / raw)
  To: agraf, kvm-ppc, kvm; +Cc: scottwood, linuxppc-dev, Liu Yu, timur

from the kvm guest paravirt init code.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
 arch/powerpc/include/asm/epapr_hcalls.h |    8 +++++
 arch/powerpc/kernel/Makefile            |    1 +
 arch/powerpc/kernel/epapr_para.c        |   45 +++++++++++++++++++++++++++++++
 arch/powerpc/kernel/kvm.c               |    9 +++++-
 4 files changed, 62 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/kernel/epapr_para.c

diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
index f3b0c2c..c4b86e4 100644
--- a/arch/powerpc/include/asm/epapr_hcalls.h
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -148,6 +148,14 @@
 #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
 #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
 
+extern u32 *epapr_hcall_insts;
+extern int epapr_hcall_insts_len;
+
+static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
+{
+	*instp = epapr_hcall_insts;
+	*lenp = epapr_hcall_insts_len;
+}
 
 /*
  * 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 ce4f7f1..1052bbc 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -134,6 +134,7 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
 obj-y				+= ppc_save_regs.o
 endif
 
+obj-$(CONFIG_BOOKE)		+= epapr_para.o
 obj-$(CONFIG_KVM_GUEST)		+= kvm.o kvm_emul.o
 
 # Disable GCOV in odd or sensitive code
diff --git a/arch/powerpc/kernel/epapr_para.c b/arch/powerpc/kernel/epapr_para.c
new file mode 100644
index 0000000..714dcb3
--- /dev/null
+++ b/arch/powerpc/kernel/epapr_para.c
@@ -0,0 +1,45 @@
+/*
+ * 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>
+
+u32 *epapr_hcall_insts;
+int epapr_hcall_insts_len;
+
+static int __init epapr_para_init(void)
+{
+	struct device_node *hyper_node;
+	u32 *insts;
+	int len;
+
+	hyper_node = of_find_node_by_path("/hypervisor");
+	if (!hyper_node)
+		return -ENODEV;
+
+	insts = (u32*)of_get_property(hyper_node, "hcall-instructions", &len);
+	if (!(len % 4) && (len >= (4 * 4))) {
+		epapr_hcall_insts = insts;
+		epapr_hcall_insts_len = len;
+	}
+
+	return 0;
+}
+
+early_initcall(epapr_para_init);
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index b06bdae..82a9137 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -28,6 +28,7 @@
 #include <asm/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/disassemble.h>
+#include <asm/epapr_hcalls.h>
 
 #define KVM_MAGIC_PAGE		(-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
@@ -535,9 +536,10 @@ 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;
+#ifndef CONFIG_BOOKE
+	struct device_node *hyper_node;
 
 	hyper_node = of_find_node_by_path("/hypervisor");
 	if (!hyper_node)
@@ -548,6 +550,11 @@ static int kvm_para_setup(void)
 		return -1;
 	if (len > (4 * 4))
 		return -1;
+#else
+	epapr_get_hcall_insts(&insts, &len);
+	if (insts == NULL)
+		return -1;
+#endif	/* !BOOKE */
 
 	for (i = 0; i < (len / 4); i++)
 		kvm_patch_ins(&(&kvm_hypercall_start)[i], insts[i]);
-- 
1.6.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 1/3] KVM: PPC: epapr: Factor out the epapr init
@ 2012-01-05  9:06 ` Liu Yu
  0 siblings, 0 replies; 15+ messages in thread
From: Liu Yu @ 2012-01-05  9:06 UTC (permalink / raw)
  To: agraf, kvm-ppc, kvm; +Cc: linuxppc-dev, galak, scottwood, timur, Liu Yu

from the kvm guest paravirt init code.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
 arch/powerpc/include/asm/epapr_hcalls.h |    8 +++++
 arch/powerpc/kernel/Makefile            |    1 +
 arch/powerpc/kernel/epapr_para.c        |   45 +++++++++++++++++++++++++++++++
 arch/powerpc/kernel/kvm.c               |    9 +++++-
 4 files changed, 62 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/kernel/epapr_para.c

diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
index f3b0c2c..c4b86e4 100644
--- a/arch/powerpc/include/asm/epapr_hcalls.h
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -148,6 +148,14 @@
 #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
 #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
 
+extern u32 *epapr_hcall_insts;
+extern int epapr_hcall_insts_len;
+
+static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
+{
+	*instp = epapr_hcall_insts;
+	*lenp = epapr_hcall_insts_len;
+}
 
 /*
  * 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 ce4f7f1..1052bbc 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -134,6 +134,7 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
 obj-y				+= ppc_save_regs.o
 endif
 
+obj-$(CONFIG_BOOKE)		+= epapr_para.o
 obj-$(CONFIG_KVM_GUEST)		+= kvm.o kvm_emul.o
 
 # Disable GCOV in odd or sensitive code
diff --git a/arch/powerpc/kernel/epapr_para.c b/arch/powerpc/kernel/epapr_para.c
new file mode 100644
index 0000000..714dcb3
--- /dev/null
+++ b/arch/powerpc/kernel/epapr_para.c
@@ -0,0 +1,45 @@
+/*
+ * 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>
+
+u32 *epapr_hcall_insts;
+int epapr_hcall_insts_len;
+
+static int __init epapr_para_init(void)
+{
+	struct device_node *hyper_node;
+	u32 *insts;
+	int len;
+
+	hyper_node = of_find_node_by_path("/hypervisor");
+	if (!hyper_node)
+		return -ENODEV;
+
+	insts = (u32*)of_get_property(hyper_node, "hcall-instructions", &len);
+	if (!(len % 4) && (len >= (4 * 4))) {
+		epapr_hcall_insts = insts;
+		epapr_hcall_insts_len = len;
+	}
+
+	return 0;
+}
+
+early_initcall(epapr_para_init);
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index b06bdae..82a9137 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -28,6 +28,7 @@
 #include <asm/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/disassemble.h>
+#include <asm/epapr_hcalls.h>
 
 #define KVM_MAGIC_PAGE		(-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
@@ -535,9 +536,10 @@ 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;
+#ifndef CONFIG_BOOKE
+	struct device_node *hyper_node;
 
 	hyper_node = of_find_node_by_path("/hypervisor");
 	if (!hyper_node)
@@ -548,6 +550,11 @@ static int kvm_para_setup(void)
 		return -1;
 	if (len > (4 * 4))
 		return -1;
+#else
+	epapr_get_hcall_insts(&insts, &len);
+	if (insts == NULL)
+		return -1;
+#endif	/* !BOOKE */
 
 	for (i = 0; i < (len / 4); i++)
 		kvm_patch_ins(&(&kvm_hypercall_start)[i], insts[i]);
-- 
1.6.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 guest
  2012-01-05  9:06 ` Liu Yu
  (?)
@ 2012-01-05  9:06   ` Liu Yu
  -1 siblings, 0 replies; 15+ messages in thread
From: Liu Yu @ 2012-01-05  9:06 UTC (permalink / raw)
  To: agraf, kvm-ppc, kvm; +Cc: linuxppc-dev, galak, scottwood, timur, Liu Yu

If the guest hypervisor node contains "has-idle" property.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
v2:
1. move the idle code into assembly.
2. move the part that check "has-idle" into epapr code.

 arch/powerpc/include/asm/epapr_hcalls.h |    1 +
 arch/powerpc/include/asm/machdep.h      |    5 +++++
 arch/powerpc/kernel/epapr_para.c        |    4 ++++
 arch/powerpc/kernel/idle_e500.S         |   17 +++++++++++++++++
 arch/powerpc/kernel/kvm.c               |   24 ++++++++++++++++++++++++
 5 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
index c4b86e4..566805e 100644
--- a/arch/powerpc/include/asm/epapr_hcalls.h
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -150,6 +150,7 @@
 
 extern u32 *epapr_hcall_insts;
 extern int epapr_hcall_insts_len;
+extern bool epapr_hcall_has_idle;
 
 static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
 {
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 47cacdd..7e56abf 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -255,6 +255,11 @@ extern void power4_idle(void);
 extern void power7_idle(void);
 extern void ppc6xx_idle(void);
 extern void book3e_idle(void);
+#ifdef CONFIG_KVM_GUEST
+extern void e500_ev_idle(unsigned long *, unsigned long *, unsigned long,
+                         unsigned long (*)(unsigned long *, unsigned long *,
+                                          unsigned long));
+#endif
 
 /*
  * ppc_md contains a copy of the machine description structure for the
diff --git a/arch/powerpc/kernel/epapr_para.c b/arch/powerpc/kernel/epapr_para.c
index 714dcb3..1f37ddf 100644
--- a/arch/powerpc/kernel/epapr_para.c
+++ b/arch/powerpc/kernel/epapr_para.c
@@ -22,6 +22,7 @@
 
 u32 *epapr_hcall_insts;
 int epapr_hcall_insts_len;
+bool epapr_hcall_has_idle;
 
 static int __init epapr_para_init(void)
 {
@@ -39,6 +40,9 @@ static int __init epapr_para_init(void)
 		epapr_hcall_insts_len = len;
 	}
 
+	if (of_get_property(hyper_node, "has-idle", NULL))
+		epapr_hcall_has_idle = true;
+
 	return 0;
 }
 
diff --git a/arch/powerpc/kernel/idle_e500.S b/arch/powerpc/kernel/idle_e500.S
index 3e2b95c..6ea95f0 100644
--- a/arch/powerpc/kernel/idle_e500.S
+++ b/arch/powerpc/kernel/idle_e500.S
@@ -85,6 +85,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
 2:	b	2b
 #endif /* !E500MC */
 
+#ifdef CONFIG_KVM_GUEST
+/*
+ * r3 contains the pointer to in[8]
+ * r4 contains the pointer to out[8]
+ * r5 contains the hcall vendor and nr
+ * r6 contains the handler which send hcall
+ */
+_GLOBAL(e500_ev_idle)
+	rlwinm	r7,r1,0,0,31-THREAD_SHIFT	/* current thread_info */
+	lwz	r8,TI_LOCAL_FLAGS(r7)	/* set napping bit */
+	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception */
+	stw	r8,TI_LOCAL_FLAGS(r7)	/* it will return to our caller */
+	wrteei	1
+	mtctr	r6
+	bctr
+#endif /* KVM_GUEST */
+
 /*
  * Return from NAP/DOZE mode, restore some CPU specific registers,
  * r2 containing physical address of current.
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 82a9137..8952e12 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -29,6 +29,7 @@
 #include <asm/cacheflush.h>
 #include <asm/disassemble.h>
 #include <asm/epapr_hcalls.h>
+#include <asm/machdep.h>
 
 #define KVM_MAGIC_PAGE		(-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
@@ -578,6 +579,25 @@ static __init void kvm_free_tmp(void)
 	}
 }
 
+static void kvm_hcall_idle(void)
+{
+#ifdef CONFIG_KVM_E500
+	ulong in[8];
+	ulong out[8];
+
+	e500_ev_idle(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE, kvm_hypercall);
+#endif
+}
+
+static bool kvm_para_has_idle(void)
+{
+#ifdef CONFIG_BOOKE
+	return epapr_hcall_has_idle;
+#else
+	return false;
+#endif
+}
+
 static int __init kvm_guest_init(void)
 {
 	if (!kvm_para_available())
@@ -594,6 +614,10 @@ static int __init kvm_guest_init(void)
 	powersave_nap = 1;
 #endif
 
+	/* Install hcall based power_save for guest kernel */
+	if (kvm_para_has_idle())
+		ppc_md.power_save = kvm_hcall_idle;
+
 free_tmp:
 	kvm_free_tmp();
 
-- 
1.6.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 guest
@ 2012-01-05  9:06   ` Liu Yu
  0 siblings, 0 replies; 15+ messages in thread
From: Liu Yu @ 2012-01-05  9:06 UTC (permalink / raw)
  To: agraf, kvm-ppc, kvm; +Cc: scottwood, linuxppc-dev, Liu Yu, timur

If the guest hypervisor node contains "has-idle" property.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
v2:
1. move the idle code into assembly.
2. move the part that check "has-idle" into epapr code.

 arch/powerpc/include/asm/epapr_hcalls.h |    1 +
 arch/powerpc/include/asm/machdep.h      |    5 +++++
 arch/powerpc/kernel/epapr_para.c        |    4 ++++
 arch/powerpc/kernel/idle_e500.S         |   17 +++++++++++++++++
 arch/powerpc/kernel/kvm.c               |   24 ++++++++++++++++++++++++
 5 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
index c4b86e4..566805e 100644
--- a/arch/powerpc/include/asm/epapr_hcalls.h
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -150,6 +150,7 @@
 
 extern u32 *epapr_hcall_insts;
 extern int epapr_hcall_insts_len;
+extern bool epapr_hcall_has_idle;
 
 static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
 {
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 47cacdd..7e56abf 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -255,6 +255,11 @@ extern void power4_idle(void);
 extern void power7_idle(void);
 extern void ppc6xx_idle(void);
 extern void book3e_idle(void);
+#ifdef CONFIG_KVM_GUEST
+extern void e500_ev_idle(unsigned long *, unsigned long *, unsigned long,
+                         unsigned long (*)(unsigned long *, unsigned long *,
+                                          unsigned long));
+#endif
 
 /*
  * ppc_md contains a copy of the machine description structure for the
diff --git a/arch/powerpc/kernel/epapr_para.c b/arch/powerpc/kernel/epapr_para.c
index 714dcb3..1f37ddf 100644
--- a/arch/powerpc/kernel/epapr_para.c
+++ b/arch/powerpc/kernel/epapr_para.c
@@ -22,6 +22,7 @@
 
 u32 *epapr_hcall_insts;
 int epapr_hcall_insts_len;
+bool epapr_hcall_has_idle;
 
 static int __init epapr_para_init(void)
 {
@@ -39,6 +40,9 @@ static int __init epapr_para_init(void)
 		epapr_hcall_insts_len = len;
 	}
 
+	if (of_get_property(hyper_node, "has-idle", NULL))
+		epapr_hcall_has_idle = true;
+
 	return 0;
 }
 
diff --git a/arch/powerpc/kernel/idle_e500.S b/arch/powerpc/kernel/idle_e500.S
index 3e2b95c..6ea95f0 100644
--- a/arch/powerpc/kernel/idle_e500.S
+++ b/arch/powerpc/kernel/idle_e500.S
@@ -85,6 +85,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
 2:	b	2b
 #endif /* !E500MC */
 
+#ifdef CONFIG_KVM_GUEST
+/*
+ * r3 contains the pointer to in[8]
+ * r4 contains the pointer to out[8]
+ * r5 contains the hcall vendor and nr
+ * r6 contains the handler which send hcall
+ */
+_GLOBAL(e500_ev_idle)
+	rlwinm	r7,r1,0,0,31-THREAD_SHIFT	/* current thread_info */
+	lwz	r8,TI_LOCAL_FLAGS(r7)	/* set napping bit */
+	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception */
+	stw	r8,TI_LOCAL_FLAGS(r7)	/* it will return to our caller */
+	wrteei	1
+	mtctr	r6
+	bctr
+#endif /* KVM_GUEST */
+
 /*
  * Return from NAP/DOZE mode, restore some CPU specific registers,
  * r2 containing physical address of current.
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 82a9137..8952e12 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -29,6 +29,7 @@
 #include <asm/cacheflush.h>
 #include <asm/disassemble.h>
 #include <asm/epapr_hcalls.h>
+#include <asm/machdep.h>
 
 #define KVM_MAGIC_PAGE		(-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
@@ -578,6 +579,25 @@ static __init void kvm_free_tmp(void)
 	}
 }
 
+static void kvm_hcall_idle(void)
+{
+#ifdef CONFIG_KVM_E500
+	ulong in[8];
+	ulong out[8];
+
+	e500_ev_idle(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE, kvm_hypercall);
+#endif
+}
+
+static bool kvm_para_has_idle(void)
+{
+#ifdef CONFIG_BOOKE
+	return epapr_hcall_has_idle;
+#else
+	return false;
+#endif
+}
+
 static int __init kvm_guest_init(void)
 {
 	if (!kvm_para_available())
@@ -594,6 +614,10 @@ static int __init kvm_guest_init(void)
 	powersave_nap = 1;
 #endif
 
+	/* Install hcall based power_save for guest kernel */
+	if (kvm_para_has_idle())
+		ppc_md.power_save = kvm_hcall_idle;
+
 free_tmp:
 	kvm_free_tmp();
 
-- 
1.6.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 guest
@ 2012-01-05  9:06   ` Liu Yu
  0 siblings, 0 replies; 15+ messages in thread
From: Liu Yu @ 2012-01-05  9:06 UTC (permalink / raw)
  To: agraf, kvm-ppc, kvm; +Cc: linuxppc-dev, galak, scottwood, timur, Liu Yu

If the guest hypervisor node contains "has-idle" property.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
v2:
1. move the idle code into assembly.
2. move the part that check "has-idle" into epapr code.

 arch/powerpc/include/asm/epapr_hcalls.h |    1 +
 arch/powerpc/include/asm/machdep.h      |    5 +++++
 arch/powerpc/kernel/epapr_para.c        |    4 ++++
 arch/powerpc/kernel/idle_e500.S         |   17 +++++++++++++++++
 arch/powerpc/kernel/kvm.c               |   24 ++++++++++++++++++++++++
 5 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
index c4b86e4..566805e 100644
--- a/arch/powerpc/include/asm/epapr_hcalls.h
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -150,6 +150,7 @@
 
 extern u32 *epapr_hcall_insts;
 extern int epapr_hcall_insts_len;
+extern bool epapr_hcall_has_idle;
 
 static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
 {
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 47cacdd..7e56abf 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -255,6 +255,11 @@ extern void power4_idle(void);
 extern void power7_idle(void);
 extern void ppc6xx_idle(void);
 extern void book3e_idle(void);
+#ifdef CONFIG_KVM_GUEST
+extern void e500_ev_idle(unsigned long *, unsigned long *, unsigned long,
+                         unsigned long (*)(unsigned long *, unsigned long *,
+                                          unsigned long));
+#endif
 
 /*
  * ppc_md contains a copy of the machine description structure for the
diff --git a/arch/powerpc/kernel/epapr_para.c b/arch/powerpc/kernel/epapr_para.c
index 714dcb3..1f37ddf 100644
--- a/arch/powerpc/kernel/epapr_para.c
+++ b/arch/powerpc/kernel/epapr_para.c
@@ -22,6 +22,7 @@
 
 u32 *epapr_hcall_insts;
 int epapr_hcall_insts_len;
+bool epapr_hcall_has_idle;
 
 static int __init epapr_para_init(void)
 {
@@ -39,6 +40,9 @@ static int __init epapr_para_init(void)
 		epapr_hcall_insts_len = len;
 	}
 
+	if (of_get_property(hyper_node, "has-idle", NULL))
+		epapr_hcall_has_idle = true;
+
 	return 0;
 }
 
diff --git a/arch/powerpc/kernel/idle_e500.S b/arch/powerpc/kernel/idle_e500.S
index 3e2b95c..6ea95f0 100644
--- a/arch/powerpc/kernel/idle_e500.S
+++ b/arch/powerpc/kernel/idle_e500.S
@@ -85,6 +85,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
 2:	b	2b
 #endif /* !E500MC */
 
+#ifdef CONFIG_KVM_GUEST
+/*
+ * r3 contains the pointer to in[8]
+ * r4 contains the pointer to out[8]
+ * r5 contains the hcall vendor and nr
+ * r6 contains the handler which send hcall
+ */
+_GLOBAL(e500_ev_idle)
+	rlwinm	r7,r1,0,0,31-THREAD_SHIFT	/* current thread_info */
+	lwz	r8,TI_LOCAL_FLAGS(r7)	/* set napping bit */
+	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception */
+	stw	r8,TI_LOCAL_FLAGS(r7)	/* it will return to our caller */
+	wrteei	1
+	mtctr	r6
+	bctr
+#endif /* KVM_GUEST */
+
 /*
  * Return from NAP/DOZE mode, restore some CPU specific registers,
  * r2 containing physical address of current.
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 82a9137..8952e12 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -29,6 +29,7 @@
 #include <asm/cacheflush.h>
 #include <asm/disassemble.h>
 #include <asm/epapr_hcalls.h>
+#include <asm/machdep.h>
 
 #define KVM_MAGIC_PAGE		(-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
@@ -578,6 +579,25 @@ static __init void kvm_free_tmp(void)
 	}
 }
 
+static void kvm_hcall_idle(void)
+{
+#ifdef CONFIG_KVM_E500
+	ulong in[8];
+	ulong out[8];
+
+	e500_ev_idle(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE, kvm_hypercall);
+#endif
+}
+
+static bool kvm_para_has_idle(void)
+{
+#ifdef CONFIG_BOOKE
+	return epapr_hcall_has_idle;
+#else
+	return false;
+#endif
+}
+
 static int __init kvm_guest_init(void)
 {
 	if (!kvm_para_available())
@@ -594,6 +614,10 @@ static int __init kvm_guest_init(void)
 	powersave_nap = 1;
 #endif
 
+	/* Install hcall based power_save for guest kernel */
+	if (kvm_para_has_idle())
+		ppc_md.power_save = kvm_hcall_idle;
+
 free_tmp:
 	kvm_free_tmp();
 
-- 
1.6.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/3] KVM: PPC: epapr: Factor out the epapr init
  2012-01-05  9:06 ` Liu Yu
  (?)
@ 2012-01-09 13:50   ` Alexander Graf
  -1 siblings, 0 replies; 15+ messages in thread
From: Alexander Graf @ 2012-01-09 13:50 UTC (permalink / raw)
  To: Liu Yu; +Cc: kvm-ppc, kvm, linuxppc-dev, galak, scottwood, timur


On 05.01.2012, at 10:06, Liu Yu wrote:

> from the kvm guest paravirt init code.

Your patch description could be slightly more ... verbose :)

> 
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> ---
> arch/powerpc/include/asm/epapr_hcalls.h |    8 +++++
> arch/powerpc/kernel/Makefile            |    1 +
> arch/powerpc/kernel/epapr_para.c        |   45 +++++++++++++++++++++++++++++++
> arch/powerpc/kernel/kvm.c               |    9 +++++-
> 4 files changed, 62 insertions(+), 1 deletions(-)
> create mode 100644 arch/powerpc/kernel/epapr_para.c
> 
> diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
> index f3b0c2c..c4b86e4 100644
> --- a/arch/powerpc/include/asm/epapr_hcalls.h
> +++ b/arch/powerpc/include/asm/epapr_hcalls.h
> @@ -148,6 +148,14 @@
> #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
> #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
> 
> +extern u32 *epapr_hcall_insts;
> +extern int epapr_hcall_insts_len;
> +
> +static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
> +{
> +	*instp = epapr_hcall_insts;
> +	*lenp = epapr_hcall_insts_len;

Why do we need this? Can't we just directly access the variables?

> +}
> 
> /*
>  * 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 ce4f7f1..1052bbc 100644
> --- a/arch/powerpc/kernel/Makefile
> +++ b/arch/powerpc/kernel/Makefile
> @@ -134,6 +134,7 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
> obj-y				+= ppc_save_regs.o
> endif
> 
> +obj-$(CONFIG_BOOKE)		+= epapr_para.o
> obj-$(CONFIG_KVM_GUEST)		+= kvm.o kvm_emul.o
> 
> # Disable GCOV in odd or sensitive code
> diff --git a/arch/powerpc/kernel/epapr_para.c b/arch/powerpc/kernel/epapr_para.c
> new file mode 100644
> index 0000000..714dcb3
> --- /dev/null
> +++ b/arch/powerpc/kernel/epapr_para.c
> @@ -0,0 +1,45 @@
> +/*
> + * 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>
> +
> +u32 *epapr_hcall_insts;
> +int epapr_hcall_insts_len;
> +
> +static int __init epapr_para_init(void)
> +{
> +	struct device_node *hyper_node;
> +	u32 *insts;
> +	int len;
> +
> +	hyper_node = of_find_node_by_path("/hypervisor");
> +	if (!hyper_node)
> +		return -ENODEV;
> +
> +	insts = (u32*)of_get_property(hyper_node, "hcall-instructions", &len);
> +	if (!(len % 4) && (len >= (4 * 4))) {
> +		epapr_hcall_insts = insts;
> +		epapr_hcall_insts_len = len;
> +	}

else error()?

> +
> +	return 0;
> +}
> +
> +early_initcall(epapr_para_init);
> diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
> index b06bdae..82a9137 100644
> --- a/arch/powerpc/kernel/kvm.c
> +++ b/arch/powerpc/kernel/kvm.c
> @@ -28,6 +28,7 @@
> #include <asm/sections.h>
> #include <asm/cacheflush.h>
> #include <asm/disassemble.h>
> +#include <asm/epapr_hcalls.h>
> 
> #define KVM_MAGIC_PAGE		(-4096L)
> #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
> @@ -535,9 +536,10 @@ 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;
> +#ifndef CONFIG_BOOKE

Ugh - now you're duplicating even more code. Why not completely unify it and always call epapr_get_hcall_insts() on all ppc platforms?


> +	struct device_node *hyper_node;
> 
> 	hyper_node = of_find_node_by_path("/hypervisor");
> 	if (!hyper_node)
> @@ -548,6 +550,11 @@ static int kvm_para_setup(void)
> 		return -1;
> 	if (len > (4 * 4))
> 		return -1;
> +#else
> +	epapr_get_hcall_insts(&insts, &len);
> +	if (insts = NULL)
> +		return -1;
> +#endif	/* !BOOKE */
> 
> 	for (i = 0; i < (len / 4); i++)
> 		kvm_patch_ins(&(&kvm_hypercall_start)[i], insts[i]);
> -- 
> 1.6.4
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/3] KVM: PPC: epapr: Factor out the epapr init
@ 2012-01-09 13:50   ` Alexander Graf
  0 siblings, 0 replies; 15+ messages in thread
From: Alexander Graf @ 2012-01-09 13:50 UTC (permalink / raw)
  To: Liu Yu; +Cc: kvm, kvm-ppc, linuxppc-dev, scottwood, timur


On 05.01.2012, at 10:06, Liu Yu wrote:

> from the kvm guest paravirt init code.

Your patch description could be slightly more ... verbose :)

>=20
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> ---
> arch/powerpc/include/asm/epapr_hcalls.h |    8 +++++
> arch/powerpc/kernel/Makefile            |    1 +
> arch/powerpc/kernel/epapr_para.c        |   45 =
+++++++++++++++++++++++++++++++
> arch/powerpc/kernel/kvm.c               |    9 +++++-
> 4 files changed, 62 insertions(+), 1 deletions(-)
> create mode 100644 arch/powerpc/kernel/epapr_para.c
>=20
> diff --git a/arch/powerpc/include/asm/epapr_hcalls.h =
b/arch/powerpc/include/asm/epapr_hcalls.h
> index f3b0c2c..c4b86e4 100644
> --- a/arch/powerpc/include/asm/epapr_hcalls.h
> +++ b/arch/powerpc/include/asm/epapr_hcalls.h
> @@ -148,6 +148,14 @@
> #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
> #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
>=20
> +extern u32 *epapr_hcall_insts;
> +extern int epapr_hcall_insts_len;
> +
> +static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
> +{
> +	*instp =3D epapr_hcall_insts;
> +	*lenp =3D epapr_hcall_insts_len;

Why do we need this? Can't we just directly access the variables?

> +}
>=20
> /*
>  * 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 ce4f7f1..1052bbc 100644
> --- a/arch/powerpc/kernel/Makefile
> +++ b/arch/powerpc/kernel/Makefile
> @@ -134,6 +134,7 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
> obj-y				+=3D ppc_save_regs.o
> endif
>=20
> +obj-$(CONFIG_BOOKE)		+=3D epapr_para.o
> obj-$(CONFIG_KVM_GUEST)		+=3D kvm.o kvm_emul.o
>=20
> # Disable GCOV in odd or sensitive code
> diff --git a/arch/powerpc/kernel/epapr_para.c =
b/arch/powerpc/kernel/epapr_para.c
> new file mode 100644
> index 0000000..714dcb3
> --- /dev/null
> +++ b/arch/powerpc/kernel/epapr_para.c
> @@ -0,0 +1,45 @@
> +/*
> + * 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>
> +
> +u32 *epapr_hcall_insts;
> +int epapr_hcall_insts_len;
> +
> +static int __init epapr_para_init(void)
> +{
> +	struct device_node *hyper_node;
> +	u32 *insts;
> +	int len;
> +
> +	hyper_node =3D of_find_node_by_path("/hypervisor");
> +	if (!hyper_node)
> +		return -ENODEV;
> +
> +	insts =3D (u32*)of_get_property(hyper_node, =
"hcall-instructions", &len);
> +	if (!(len % 4) && (len >=3D (4 * 4))) {
> +		epapr_hcall_insts =3D insts;
> +		epapr_hcall_insts_len =3D len;
> +	}

else error()?

> +
> +	return 0;
> +}
> +
> +early_initcall(epapr_para_init);
> diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
> index b06bdae..82a9137 100644
> --- a/arch/powerpc/kernel/kvm.c
> +++ b/arch/powerpc/kernel/kvm.c
> @@ -28,6 +28,7 @@
> #include <asm/sections.h>
> #include <asm/cacheflush.h>
> #include <asm/disassemble.h>
> +#include <asm/epapr_hcalls.h>
>=20
> #define KVM_MAGIC_PAGE		(-4096L)
> #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct =
kvm_vcpu_arch_shared, x)
> @@ -535,9 +536,10 @@ 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;
> +#ifndef CONFIG_BOOKE

Ugh - now you're duplicating even more code. Why not completely unify it =
and always call epapr_get_hcall_insts() on all ppc platforms?


> +	struct device_node *hyper_node;
>=20
> 	hyper_node =3D of_find_node_by_path("/hypervisor");
> 	if (!hyper_node)
> @@ -548,6 +550,11 @@ static int kvm_para_setup(void)
> 		return -1;
> 	if (len > (4 * 4))
> 		return -1;
> +#else
> +	epapr_get_hcall_insts(&insts, &len);
> +	if (insts =3D=3D NULL)
> +		return -1;
> +#endif	/* !BOOKE */
>=20
> 	for (i =3D 0; i < (len / 4); i++)
> 		kvm_patch_ins(&(&kvm_hypercall_start)[i], insts[i]);
> --=20
> 1.6.4
>=20
>=20
> --
> To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/3] KVM: PPC: epapr: Factor out the epapr init
@ 2012-01-09 13:50   ` Alexander Graf
  0 siblings, 0 replies; 15+ messages in thread
From: Alexander Graf @ 2012-01-09 13:50 UTC (permalink / raw)
  To: Liu Yu; +Cc: kvm-ppc, kvm, linuxppc-dev, galak, scottwood, timur


On 05.01.2012, at 10:06, Liu Yu wrote:

> from the kvm guest paravirt init code.

Your patch description could be slightly more ... verbose :)

> 
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> ---
> arch/powerpc/include/asm/epapr_hcalls.h |    8 +++++
> arch/powerpc/kernel/Makefile            |    1 +
> arch/powerpc/kernel/epapr_para.c        |   45 +++++++++++++++++++++++++++++++
> arch/powerpc/kernel/kvm.c               |    9 +++++-
> 4 files changed, 62 insertions(+), 1 deletions(-)
> create mode 100644 arch/powerpc/kernel/epapr_para.c
> 
> diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
> index f3b0c2c..c4b86e4 100644
> --- a/arch/powerpc/include/asm/epapr_hcalls.h
> +++ b/arch/powerpc/include/asm/epapr_hcalls.h
> @@ -148,6 +148,14 @@
> #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
> #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
> 
> +extern u32 *epapr_hcall_insts;
> +extern int epapr_hcall_insts_len;
> +
> +static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
> +{
> +	*instp = epapr_hcall_insts;
> +	*lenp = epapr_hcall_insts_len;

Why do we need this? Can't we just directly access the variables?

> +}
> 
> /*
>  * 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 ce4f7f1..1052bbc 100644
> --- a/arch/powerpc/kernel/Makefile
> +++ b/arch/powerpc/kernel/Makefile
> @@ -134,6 +134,7 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
> obj-y				+= ppc_save_regs.o
> endif
> 
> +obj-$(CONFIG_BOOKE)		+= epapr_para.o
> obj-$(CONFIG_KVM_GUEST)		+= kvm.o kvm_emul.o
> 
> # Disable GCOV in odd or sensitive code
> diff --git a/arch/powerpc/kernel/epapr_para.c b/arch/powerpc/kernel/epapr_para.c
> new file mode 100644
> index 0000000..714dcb3
> --- /dev/null
> +++ b/arch/powerpc/kernel/epapr_para.c
> @@ -0,0 +1,45 @@
> +/*
> + * 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>
> +
> +u32 *epapr_hcall_insts;
> +int epapr_hcall_insts_len;
> +
> +static int __init epapr_para_init(void)
> +{
> +	struct device_node *hyper_node;
> +	u32 *insts;
> +	int len;
> +
> +	hyper_node = of_find_node_by_path("/hypervisor");
> +	if (!hyper_node)
> +		return -ENODEV;
> +
> +	insts = (u32*)of_get_property(hyper_node, "hcall-instructions", &len);
> +	if (!(len % 4) && (len >= (4 * 4))) {
> +		epapr_hcall_insts = insts;
> +		epapr_hcall_insts_len = len;
> +	}

else error()?

> +
> +	return 0;
> +}
> +
> +early_initcall(epapr_para_init);
> diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
> index b06bdae..82a9137 100644
> --- a/arch/powerpc/kernel/kvm.c
> +++ b/arch/powerpc/kernel/kvm.c
> @@ -28,6 +28,7 @@
> #include <asm/sections.h>
> #include <asm/cacheflush.h>
> #include <asm/disassemble.h>
> +#include <asm/epapr_hcalls.h>
> 
> #define KVM_MAGIC_PAGE		(-4096L)
> #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
> @@ -535,9 +536,10 @@ 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;
> +#ifndef CONFIG_BOOKE

Ugh - now you're duplicating even more code. Why not completely unify it and always call epapr_get_hcall_insts() on all ppc platforms?


> +	struct device_node *hyper_node;
> 
> 	hyper_node = of_find_node_by_path("/hypervisor");
> 	if (!hyper_node)
> @@ -548,6 +550,11 @@ static int kvm_para_setup(void)
> 		return -1;
> 	if (len > (4 * 4))
> 		return -1;
> +#else
> +	epapr_get_hcall_insts(&insts, &len);
> +	if (insts == NULL)
> +		return -1;
> +#endif	/* !BOOKE */
> 
> 	for (i = 0; i < (len / 4); i++)
> 		kvm_patch_ins(&(&kvm_hypercall_start)[i], insts[i]);
> -- 
> 1.6.4
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 guest
  2012-01-05  9:06   ` Liu Yu
  (?)
@ 2012-01-09 14:05     ` Alexander Graf
  -1 siblings, 0 replies; 15+ messages in thread
From: Alexander Graf @ 2012-01-09 14:05 UTC (permalink / raw)
  To: Liu Yu; +Cc: kvm-ppc, kvm, linuxppc-dev, galak, scottwood, timur


On 05.01.2012, at 10:06, Liu Yu wrote:

> If the guest hypervisor node contains "has-idle" property.
> 
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> ---
> v2:
> 1. move the idle code into assembly.
> 2. move the part that check "has-idle" into epapr code.
> 
> arch/powerpc/include/asm/epapr_hcalls.h |    1 +
> arch/powerpc/include/asm/machdep.h      |    5 +++++
> arch/powerpc/kernel/epapr_para.c        |    4 ++++
> arch/powerpc/kernel/idle_e500.S         |   17 +++++++++++++++++
> arch/powerpc/kernel/kvm.c               |   24 ++++++++++++++++++++++++
> 5 files changed, 51 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
> index c4b86e4..566805e 100644
> --- a/arch/powerpc/include/asm/epapr_hcalls.h
> +++ b/arch/powerpc/include/asm/epapr_hcalls.h
> @@ -150,6 +150,7 @@
> 
> extern u32 *epapr_hcall_insts;
> extern int epapr_hcall_insts_len;
> +extern bool epapr_hcall_has_idle;
> 
> static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
> {
> diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
> index 47cacdd..7e56abf 100644
> --- a/arch/powerpc/include/asm/machdep.h
> +++ b/arch/powerpc/include/asm/machdep.h
> @@ -255,6 +255,11 @@ extern void power4_idle(void);
> extern void power7_idle(void);
> extern void ppc6xx_idle(void);
> extern void book3e_idle(void);
> +#ifdef CONFIG_KVM_GUEST
> +extern void e500_ev_idle(unsigned long *, unsigned long *, unsigned long,
> +                         unsigned long (*)(unsigned long *, unsigned long *,
> +                                          unsigned long));
> +#endif
> 
> /*
>  * ppc_md contains a copy of the machine description structure for the
> diff --git a/arch/powerpc/kernel/epapr_para.c b/arch/powerpc/kernel/epapr_para.c
> index 714dcb3..1f37ddf 100644
> --- a/arch/powerpc/kernel/epapr_para.c
> +++ b/arch/powerpc/kernel/epapr_para.c
> @@ -22,6 +22,7 @@
> 
> u32 *epapr_hcall_insts;
> int epapr_hcall_insts_len;
> +bool epapr_hcall_has_idle;
> 
> static int __init epapr_para_init(void)
> {
> @@ -39,6 +40,9 @@ static int __init epapr_para_init(void)
> 		epapr_hcall_insts_len = len;
> 	}
> 
> +	if (of_get_property(hyper_node, "has-idle", NULL))
> +		epapr_hcall_has_idle = true;
> +
> 	return 0;
> }
> 
> diff --git a/arch/powerpc/kernel/idle_e500.S b/arch/powerpc/kernel/idle_e500.S
> index 3e2b95c..6ea95f0 100644
> --- a/arch/powerpc/kernel/idle_e500.S
> +++ b/arch/powerpc/kernel/idle_e500.S
> @@ -85,6 +85,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
> 2:	b	2b
> #endif /* !E500MC */
> 
> +#ifdef CONFIG_KVM_GUEST
> +/*
> + * r3 contains the pointer to in[8]
> + * r4 contains the pointer to out[8]
> + * r5 contains the hcall vendor and nr
> + * r6 contains the handler which send hcall
> + */
> +_GLOBAL(e500_ev_idle)

How is that specific to e500? Isn't it just the generic epapr implementation?

> +	rlwinm	r7,r1,0,0,31-THREAD_SHIFT	/* current thread_info */
> +	lwz	r8,TI_LOCAL_FLAGS(r7)	/* set napping bit */
> +	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception */
> +	stw	r8,TI_LOCAL_FLAGS(r7)	/* it will return to our caller */
> +	wrteei	1

Except for this part of course :). But I'm sure we can generalize this.

> +	mtctr	r6
> +	bctr
> +#endif /* KVM_GUEST */
> +
> /*
>  * Return from NAP/DOZE mode, restore some CPU specific registers,
>  * r2 containing physical address of current.
> diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
> index 82a9137..8952e12 100644
> --- a/arch/powerpc/kernel/kvm.c
> +++ b/arch/powerpc/kernel/kvm.c
> @@ -29,6 +29,7 @@
> #include <asm/cacheflush.h>
> #include <asm/disassemble.h>
> #include <asm/epapr_hcalls.h>
> +#include <asm/machdep.h>
> 
> #define KVM_MAGIC_PAGE		(-4096L)
> #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
> @@ -578,6 +579,25 @@ static __init void kvm_free_tmp(void)
> 	}
> }
> 
> +static void kvm_hcall_idle(void)
> +{
> +#ifdef CONFIG_KVM_E500
> +	ulong in[8];
> +	ulong out[8];
> +
> +	e500_ev_idle(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE, kvm_hypercall);
> +#endif

... because then the ifdef goes away here too

> +}
> +
> +static bool kvm_para_has_idle(void)
> +{
> +#ifdef CONFIG_BOOKE
> +	return epapr_hcall_has_idle;
> +#else
> +	return false;
> +#endif

... this also shouldn't be an ifdef

> +}
> +
> static int __init kvm_guest_init(void)
> {
> 	if (!kvm_para_available())
> @@ -594,6 +614,10 @@ static int __init kvm_guest_init(void)
> 	powersave_nap = 1;
> #endif
> 
> +	/* Install hcall based power_save for guest kernel */
> +	if (kvm_para_has_idle())
> +		ppc_md.power_save = kvm_hcall_idle;

The way it's now it would break kernels with this patch if we ever choose to implement hcall_idle for non-e500. Please make the code generic :)


Alex


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 guest
@ 2012-01-09 14:05     ` Alexander Graf
  0 siblings, 0 replies; 15+ messages in thread
From: Alexander Graf @ 2012-01-09 14:05 UTC (permalink / raw)
  To: Liu Yu; +Cc: kvm, kvm-ppc, linuxppc-dev, scottwood, timur


On 05.01.2012, at 10:06, Liu Yu wrote:

> If the guest hypervisor node contains "has-idle" property.
>=20
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> ---
> v2:
> 1. move the idle code into assembly.
> 2. move the part that check "has-idle" into epapr code.
>=20
> arch/powerpc/include/asm/epapr_hcalls.h |    1 +
> arch/powerpc/include/asm/machdep.h      |    5 +++++
> arch/powerpc/kernel/epapr_para.c        |    4 ++++
> arch/powerpc/kernel/idle_e500.S         |   17 +++++++++++++++++
> arch/powerpc/kernel/kvm.c               |   24 =
++++++++++++++++++++++++
> 5 files changed, 51 insertions(+), 0 deletions(-)
>=20
> diff --git a/arch/powerpc/include/asm/epapr_hcalls.h =
b/arch/powerpc/include/asm/epapr_hcalls.h
> index c4b86e4..566805e 100644
> --- a/arch/powerpc/include/asm/epapr_hcalls.h
> +++ b/arch/powerpc/include/asm/epapr_hcalls.h
> @@ -150,6 +150,7 @@
>=20
> extern u32 *epapr_hcall_insts;
> extern int epapr_hcall_insts_len;
> +extern bool epapr_hcall_has_idle;
>=20
> static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
> {
> diff --git a/arch/powerpc/include/asm/machdep.h =
b/arch/powerpc/include/asm/machdep.h
> index 47cacdd..7e56abf 100644
> --- a/arch/powerpc/include/asm/machdep.h
> +++ b/arch/powerpc/include/asm/machdep.h
> @@ -255,6 +255,11 @@ extern void power4_idle(void);
> extern void power7_idle(void);
> extern void ppc6xx_idle(void);
> extern void book3e_idle(void);
> +#ifdef CONFIG_KVM_GUEST
> +extern void e500_ev_idle(unsigned long *, unsigned long *, unsigned =
long,
> +                         unsigned long (*)(unsigned long *, unsigned =
long *,
> +                                          unsigned long));
> +#endif
>=20
> /*
>  * ppc_md contains a copy of the machine description structure for the
> diff --git a/arch/powerpc/kernel/epapr_para.c =
b/arch/powerpc/kernel/epapr_para.c
> index 714dcb3..1f37ddf 100644
> --- a/arch/powerpc/kernel/epapr_para.c
> +++ b/arch/powerpc/kernel/epapr_para.c
> @@ -22,6 +22,7 @@
>=20
> u32 *epapr_hcall_insts;
> int epapr_hcall_insts_len;
> +bool epapr_hcall_has_idle;
>=20
> static int __init epapr_para_init(void)
> {
> @@ -39,6 +40,9 @@ static int __init epapr_para_init(void)
> 		epapr_hcall_insts_len =3D len;
> 	}
>=20
> +	if (of_get_property(hyper_node, "has-idle", NULL))
> +		epapr_hcall_has_idle =3D true;
> +
> 	return 0;
> }
>=20
> diff --git a/arch/powerpc/kernel/idle_e500.S =
b/arch/powerpc/kernel/idle_e500.S
> index 3e2b95c..6ea95f0 100644
> --- a/arch/powerpc/kernel/idle_e500.S
> +++ b/arch/powerpc/kernel/idle_e500.S
> @@ -85,6 +85,23 @@ =
END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
> 2:	b	2b
> #endif /* !E500MC */
>=20
> +#ifdef CONFIG_KVM_GUEST
> +/*
> + * r3 contains the pointer to in[8]
> + * r4 contains the pointer to out[8]
> + * r5 contains the hcall vendor and nr
> + * r6 contains the handler which send hcall
> + */
> +_GLOBAL(e500_ev_idle)

How is that specific to e500? Isn't it just the generic epapr =
implementation?

> +	rlwinm	r7,r1,0,0,31-THREAD_SHIFT	/* current thread_info =
*/
> +	lwz	r8,TI_LOCAL_FLAGS(r7)	/* set napping bit */
> +	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception =
*/
> +	stw	r8,TI_LOCAL_FLAGS(r7)	/* it will return to our caller =
*/
> +	wrteei	1

Except for this part of course :). But I'm sure we can generalize this.

> +	mtctr	r6
> +	bctr
> +#endif /* KVM_GUEST */
> +
> /*
>  * Return from NAP/DOZE mode, restore some CPU specific registers,
>  * r2 containing physical address of current.
> diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
> index 82a9137..8952e12 100644
> --- a/arch/powerpc/kernel/kvm.c
> +++ b/arch/powerpc/kernel/kvm.c
> @@ -29,6 +29,7 @@
> #include <asm/cacheflush.h>
> #include <asm/disassemble.h>
> #include <asm/epapr_hcalls.h>
> +#include <asm/machdep.h>
>=20
> #define KVM_MAGIC_PAGE		(-4096L)
> #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct =
kvm_vcpu_arch_shared, x)
> @@ -578,6 +579,25 @@ static __init void kvm_free_tmp(void)
> 	}
> }
>=20
> +static void kvm_hcall_idle(void)
> +{
> +#ifdef CONFIG_KVM_E500
> +	ulong in[8];
> +	ulong out[8];
> +
> +	e500_ev_idle(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE, =
kvm_hypercall);
> +#endif

... because then the ifdef goes away here too

> +}
> +
> +static bool kvm_para_has_idle(void)
> +{
> +#ifdef CONFIG_BOOKE
> +	return epapr_hcall_has_idle;
> +#else
> +	return false;
> +#endif

... this also shouldn't be an ifdef

> +}
> +
> static int __init kvm_guest_init(void)
> {
> 	if (!kvm_para_available())
> @@ -594,6 +614,10 @@ static int __init kvm_guest_init(void)
> 	powersave_nap =3D 1;
> #endif
>=20
> +	/* Install hcall based power_save for guest kernel */
> +	if (kvm_para_has_idle())
> +		ppc_md.power_save =3D kvm_hcall_idle;

The way it's now it would break kernels with this patch if we ever =
choose to implement hcall_idle for non-e500. Please make the code =
generic :)


Alex

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 guest
@ 2012-01-09 14:05     ` Alexander Graf
  0 siblings, 0 replies; 15+ messages in thread
From: Alexander Graf @ 2012-01-09 14:05 UTC (permalink / raw)
  To: Liu Yu; +Cc: kvm-ppc, kvm, linuxppc-dev, galak, scottwood, timur


On 05.01.2012, at 10:06, Liu Yu wrote:

> If the guest hypervisor node contains "has-idle" property.
> 
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> ---
> v2:
> 1. move the idle code into assembly.
> 2. move the part that check "has-idle" into epapr code.
> 
> arch/powerpc/include/asm/epapr_hcalls.h |    1 +
> arch/powerpc/include/asm/machdep.h      |    5 +++++
> arch/powerpc/kernel/epapr_para.c        |    4 ++++
> arch/powerpc/kernel/idle_e500.S         |   17 +++++++++++++++++
> arch/powerpc/kernel/kvm.c               |   24 ++++++++++++++++++++++++
> 5 files changed, 51 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
> index c4b86e4..566805e 100644
> --- a/arch/powerpc/include/asm/epapr_hcalls.h
> +++ b/arch/powerpc/include/asm/epapr_hcalls.h
> @@ -150,6 +150,7 @@
> 
> extern u32 *epapr_hcall_insts;
> extern int epapr_hcall_insts_len;
> +extern bool epapr_hcall_has_idle;
> 
> static inline void epapr_get_hcall_insts(u32 **instp, int *lenp)
> {
> diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
> index 47cacdd..7e56abf 100644
> --- a/arch/powerpc/include/asm/machdep.h
> +++ b/arch/powerpc/include/asm/machdep.h
> @@ -255,6 +255,11 @@ extern void power4_idle(void);
> extern void power7_idle(void);
> extern void ppc6xx_idle(void);
> extern void book3e_idle(void);
> +#ifdef CONFIG_KVM_GUEST
> +extern void e500_ev_idle(unsigned long *, unsigned long *, unsigned long,
> +                         unsigned long (*)(unsigned long *, unsigned long *,
> +                                          unsigned long));
> +#endif
> 
> /*
>  * ppc_md contains a copy of the machine description structure for the
> diff --git a/arch/powerpc/kernel/epapr_para.c b/arch/powerpc/kernel/epapr_para.c
> index 714dcb3..1f37ddf 100644
> --- a/arch/powerpc/kernel/epapr_para.c
> +++ b/arch/powerpc/kernel/epapr_para.c
> @@ -22,6 +22,7 @@
> 
> u32 *epapr_hcall_insts;
> int epapr_hcall_insts_len;
> +bool epapr_hcall_has_idle;
> 
> static int __init epapr_para_init(void)
> {
> @@ -39,6 +40,9 @@ static int __init epapr_para_init(void)
> 		epapr_hcall_insts_len = len;
> 	}
> 
> +	if (of_get_property(hyper_node, "has-idle", NULL))
> +		epapr_hcall_has_idle = true;
> +
> 	return 0;
> }
> 
> diff --git a/arch/powerpc/kernel/idle_e500.S b/arch/powerpc/kernel/idle_e500.S
> index 3e2b95c..6ea95f0 100644
> --- a/arch/powerpc/kernel/idle_e500.S
> +++ b/arch/powerpc/kernel/idle_e500.S
> @@ -85,6 +85,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
> 2:	b	2b
> #endif /* !E500MC */
> 
> +#ifdef CONFIG_KVM_GUEST
> +/*
> + * r3 contains the pointer to in[8]
> + * r4 contains the pointer to out[8]
> + * r5 contains the hcall vendor and nr
> + * r6 contains the handler which send hcall
> + */
> +_GLOBAL(e500_ev_idle)

How is that specific to e500? Isn't it just the generic epapr implementation?

> +	rlwinm	r7,r1,0,0,31-THREAD_SHIFT	/* current thread_info */
> +	lwz	r8,TI_LOCAL_FLAGS(r7)	/* set napping bit */
> +	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception */
> +	stw	r8,TI_LOCAL_FLAGS(r7)	/* it will return to our caller */
> +	wrteei	1

Except for this part of course :). But I'm sure we can generalize this.

> +	mtctr	r6
> +	bctr
> +#endif /* KVM_GUEST */
> +
> /*
>  * Return from NAP/DOZE mode, restore some CPU specific registers,
>  * r2 containing physical address of current.
> diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
> index 82a9137..8952e12 100644
> --- a/arch/powerpc/kernel/kvm.c
> +++ b/arch/powerpc/kernel/kvm.c
> @@ -29,6 +29,7 @@
> #include <asm/cacheflush.h>
> #include <asm/disassemble.h>
> #include <asm/epapr_hcalls.h>
> +#include <asm/machdep.h>
> 
> #define KVM_MAGIC_PAGE		(-4096L)
> #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
> @@ -578,6 +579,25 @@ static __init void kvm_free_tmp(void)
> 	}
> }
> 
> +static void kvm_hcall_idle(void)
> +{
> +#ifdef CONFIG_KVM_E500
> +	ulong in[8];
> +	ulong out[8];
> +
> +	e500_ev_idle(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE, kvm_hypercall);
> +#endif

... because then the ifdef goes away here too

> +}
> +
> +static bool kvm_para_has_idle(void)
> +{
> +#ifdef CONFIG_BOOKE
> +	return epapr_hcall_has_idle;
> +#else
> +	return false;
> +#endif

... this also shouldn't be an ifdef

> +}
> +
> static int __init kvm_guest_init(void)
> {
> 	if (!kvm_para_available())
> @@ -594,6 +614,10 @@ static int __init kvm_guest_init(void)
> 	powersave_nap = 1;
> #endif
> 
> +	/* Install hcall based power_save for guest kernel */
> +	if (kvm_para_has_idle())
> +		ppc_md.power_save = kvm_hcall_idle;

The way it's now it would break kernels with this patch if we ever choose to implement hcall_idle for non-e500. Please make the code generic :)


Alex

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500
  2012-01-05  9:06   ` Liu Yu
  (?)
@ 2012-01-09 21:15     ` Scott Wood
  -1 siblings, 0 replies; 15+ messages in thread
From: Scott Wood @ 2012-01-09 21:15 UTC (permalink / raw)
  To: Liu Yu; +Cc: agraf, kvm-ppc, kvm, linuxppc-dev, galak, timur

On 01/05/2012 03:06 AM, Liu Yu wrote:
> diff --git a/arch/powerpc/kernel/idle_e500.S b/arch/powerpc/kernel/idle_e500.S
> index 3e2b95c..6ea95f0 100644
> --- a/arch/powerpc/kernel/idle_e500.S
> +++ b/arch/powerpc/kernel/idle_e500.S
> @@ -85,6 +85,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
>  2:	b	2b
>  #endif /* !E500MC */
>  
> +#ifdef CONFIG_KVM_GUEST
> +/*
> + * r3 contains the pointer to in[8]
> + * r4 contains the pointer to out[8]
> + * r5 contains the hcall vendor and nr
> + * r6 contains the handler which send hcall
> + */
> +_GLOBAL(e500_ev_idle)
> +	rlwinm	r7,r1,0,0,31-THREAD_SHIFT	/* current thread_info */
> +	lwz	r8,TI_LOCAL_FLAGS(r7)	/* set napping bit */
> +	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception */
> +	stw	r8,TI_LOCAL_FLAGS(r7)	/* it will return to our caller */
> +	wrteei	1
> +	mtctr	r6
> +	bctr
> +#endif /* KVM_GUEST */

You'll need to branch back to the hcall invocation in an infinite loop
-- the only way we should leave is via an interrupt.

> +static void kvm_hcall_idle(void)
> +{
> +#ifdef CONFIG_KVM_E500
> +	ulong in[8];
> +	ulong out[8];
> +
> +	e500_ev_idle(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE, kvm_hypercall);
> +#endif
> +}

kvm_hypercall is C code.  As stated before, you cannot use C code while
_TLF_NAPPING is set.

> +static bool kvm_para_has_idle(void)
> +{
> +#ifdef CONFIG_BOOKE
> +	return epapr_hcall_has_idle;
> +#else
> +	return false;
> +#endif
> +}
> +
>  static int __init kvm_guest_init(void)
>  {
>  	if (!kvm_para_available())
> @@ -594,6 +614,10 @@ static int __init kvm_guest_init(void)
>  	powersave_nap = 1;
>  #endif
>  
> +	/* Install hcall based power_save for guest kernel */
> +	if (kvm_para_has_idle())
> +		ppc_md.power_save = kvm_hcall_idle;

Why did you only move it halfway out of KVM code?  ePAPR features such
as idle hcall should work on any ePAPR hypervisor, even with all KVM
code disabled.

Plus everything Alex said. :-)

-Scott


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 guest
@ 2012-01-09 21:15     ` Scott Wood
  0 siblings, 0 replies; 15+ messages in thread
From: Scott Wood @ 2012-01-09 21:15 UTC (permalink / raw)
  To: Liu Yu; +Cc: kvm, kvm-ppc, agraf, linuxppc-dev, timur

On 01/05/2012 03:06 AM, Liu Yu wrote:
> diff --git a/arch/powerpc/kernel/idle_e500.S b/arch/powerpc/kernel/idle_e500.S
> index 3e2b95c..6ea95f0 100644
> --- a/arch/powerpc/kernel/idle_e500.S
> +++ b/arch/powerpc/kernel/idle_e500.S
> @@ -85,6 +85,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
>  2:	b	2b
>  #endif /* !E500MC */
>  
> +#ifdef CONFIG_KVM_GUEST
> +/*
> + * r3 contains the pointer to in[8]
> + * r4 contains the pointer to out[8]
> + * r5 contains the hcall vendor and nr
> + * r6 contains the handler which send hcall
> + */
> +_GLOBAL(e500_ev_idle)
> +	rlwinm	r7,r1,0,0,31-THREAD_SHIFT	/* current thread_info */
> +	lwz	r8,TI_LOCAL_FLAGS(r7)	/* set napping bit */
> +	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception */
> +	stw	r8,TI_LOCAL_FLAGS(r7)	/* it will return to our caller */
> +	wrteei	1
> +	mtctr	r6
> +	bctr
> +#endif /* KVM_GUEST */

You'll need to branch back to the hcall invocation in an infinite loop
-- the only way we should leave is via an interrupt.

> +static void kvm_hcall_idle(void)
> +{
> +#ifdef CONFIG_KVM_E500
> +	ulong in[8];
> +	ulong out[8];
> +
> +	e500_ev_idle(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE, kvm_hypercall);
> +#endif
> +}

kvm_hypercall is C code.  As stated before, you cannot use C code while
_TLF_NAPPING is set.

> +static bool kvm_para_has_idle(void)
> +{
> +#ifdef CONFIG_BOOKE
> +	return epapr_hcall_has_idle;
> +#else
> +	return false;
> +#endif
> +}
> +
>  static int __init kvm_guest_init(void)
>  {
>  	if (!kvm_para_available())
> @@ -594,6 +614,10 @@ static int __init kvm_guest_init(void)
>  	powersave_nap = 1;
>  #endif
>  
> +	/* Install hcall based power_save for guest kernel */
> +	if (kvm_para_has_idle())
> +		ppc_md.power_save = kvm_hcall_idle;

Why did you only move it halfway out of KVM code?  ePAPR features such
as idle hcall should work on any ePAPR hypervisor, even with all KVM
code disabled.

Plus everything Alex said. :-)

-Scott

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 guest
@ 2012-01-09 21:15     ` Scott Wood
  0 siblings, 0 replies; 15+ messages in thread
From: Scott Wood @ 2012-01-09 21:15 UTC (permalink / raw)
  To: Liu Yu; +Cc: agraf, kvm-ppc, kvm, linuxppc-dev, galak, timur

On 01/05/2012 03:06 AM, Liu Yu wrote:
> diff --git a/arch/powerpc/kernel/idle_e500.S b/arch/powerpc/kernel/idle_e500.S
> index 3e2b95c..6ea95f0 100644
> --- a/arch/powerpc/kernel/idle_e500.S
> +++ b/arch/powerpc/kernel/idle_e500.S
> @@ -85,6 +85,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
>  2:	b	2b
>  #endif /* !E500MC */
>  
> +#ifdef CONFIG_KVM_GUEST
> +/*
> + * r3 contains the pointer to in[8]
> + * r4 contains the pointer to out[8]
> + * r5 contains the hcall vendor and nr
> + * r6 contains the handler which send hcall
> + */
> +_GLOBAL(e500_ev_idle)
> +	rlwinm	r7,r1,0,0,31-THREAD_SHIFT	/* current thread_info */
> +	lwz	r8,TI_LOCAL_FLAGS(r7)	/* set napping bit */
> +	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception */
> +	stw	r8,TI_LOCAL_FLAGS(r7)	/* it will return to our caller */
> +	wrteei	1
> +	mtctr	r6
> +	bctr
> +#endif /* KVM_GUEST */

You'll need to branch back to the hcall invocation in an infinite loop
-- the only way we should leave is via an interrupt.

> +static void kvm_hcall_idle(void)
> +{
> +#ifdef CONFIG_KVM_E500
> +	ulong in[8];
> +	ulong out[8];
> +
> +	e500_ev_idle(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE, kvm_hypercall);
> +#endif
> +}

kvm_hypercall is C code.  As stated before, you cannot use C code while
_TLF_NAPPING is set.

> +static bool kvm_para_has_idle(void)
> +{
> +#ifdef CONFIG_BOOKE
> +	return epapr_hcall_has_idle;
> +#else
> +	return false;
> +#endif
> +}
> +
>  static int __init kvm_guest_init(void)
>  {
>  	if (!kvm_para_available())
> @@ -594,6 +614,10 @@ static int __init kvm_guest_init(void)
>  	powersave_nap = 1;
>  #endif
>  
> +	/* Install hcall based power_save for guest kernel */
> +	if (kvm_para_has_idle())
> +		ppc_md.power_save = kvm_hcall_idle;

Why did you only move it halfway out of KVM code?  ePAPR features such
as idle hcall should work on any ePAPR hypervisor, even with all KVM
code disabled.

Plus everything Alex said. :-)

-Scott

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2012-01-09 21:15 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-05  9:06 [PATCH 1/3] KVM: PPC: epapr: Factor out the epapr init Liu Yu
2012-01-05  9:06 ` Liu Yu
2012-01-05  9:06 ` Liu Yu
2012-01-05  9:06 ` [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 guest Liu Yu
2012-01-05  9:06   ` Liu Yu
2012-01-05  9:06   ` Liu Yu
2012-01-09 14:05   ` Alexander Graf
2012-01-09 14:05     ` Alexander Graf
2012-01-09 14:05     ` Alexander Graf
2012-01-09 21:15   ` [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 Scott Wood
2012-01-09 21:15     ` [PATCH v2 3/3] KVM: PPC: epapr: install ev_idle hcall for e500 guest Scott Wood
2012-01-09 21:15     ` Scott Wood
2012-01-09 13:50 ` [PATCH 1/3] KVM: PPC: epapr: Factor out the epapr init Alexander Graf
2012-01-09 13:50   ` Alexander Graf
2012-01-09 13:50   ` Alexander Graf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.