diff mbox

[2/2] KVM: PPC: epapr: Install ev_idle hcall for paravirt guest linux

Message ID 1325312176-17697-2-git-send-email-yu.liu@freescale.com
State New, archived
Headers show

Commit Message

Liu Yu-B13201 Dec. 31, 2011, 6:16 a.m. UTC
If the guest hypervisor node contains "has-idle" property.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
 arch/powerpc/kernel/kvm.c |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)

Comments

Scott Wood Jan. 2, 2012, 6:23 p.m. UTC | #1
On 12/31/2011 12:16 AM, Liu Yu wrote:
> If the guest hypervisor node contains "has-idle" property.
> 
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> ---
>  arch/powerpc/kernel/kvm.c |   29 +++++++++++++++++++++++++++++
>  1 files changed, 29 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
> index b06bdae..258f129 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/machdep.h>
>  
>  #define KVM_MAGIC_PAGE		(-4096L)
>  #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
> @@ -571,6 +572,30 @@ static __init void kvm_free_tmp(void)
>  	}
>  }
>  
> +static void kvm_hcall_ev_idle(void)
> +{
> +	ulong in[8];
> +	ulong out[8];
> +
> +	current_thread_info()->local_flags |= _TLF_NAPPING;
> +	local_irq_enable();
> +	kvm_hypercall(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE);
> +}

I think this has to be done in assembly -- otherwise it's not safe for
the interrupt handler to return directly to LR.

> +static int kvm_para_ev_has_idle(void)
> +{
> +	struct device_node *hyper_node;
> +
> +	hyper_node = of_find_node_by_path("/hypervisor");
> +	if (!hyper_node)
> +		return 0;
> +
> +	if (of_get_property(hyper_node, "has-idle", NULL))
> +		return 1;
> +
> +	return 0;
> +}

Since this is standardized in ePAPR, can we move it out of kvm.c an into
generic code to work with any hypervisor that sets has-idle?  Likewise
with kvm_para_setup().

-Scott

--
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
Scott Wood Jan. 4, 2012, 7:21 p.m. UTC | #2
On 01/04/2012 03:23 AM, Liu Yu-B13201 wrote:
> 
> 
>> -----Original Message-----
>> From: Wood Scott-B07421
>> Sent: Tuesday, January 03, 2012 2:23 AM
>> To: Liu Yu-B13201
>> Cc: agraf@suse.de; kvm-ppc@vger.kernel.org; kvm@vger.kernel.org
>> Subject: Re: [PATCH 2/2] KVM: PPC: epapr: Install ev_idle hcall for
>> paravirt guest linux
>>
>> Since this is standardized in ePAPR, can we move it out of kvm.c an into
>> generic code to work with any hypervisor that sets has-idle?  Likewise
>> with kvm_para_setup().
>>
> 
> Do you mean we scan and parse hypervisor node in early_init_devtree()?

No, just have a separate initcall for enabling ePAPR paravirt features.

-Scott

--
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
diff mbox

Patch

diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index b06bdae..258f129 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/machdep.h>
 
 #define KVM_MAGIC_PAGE		(-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
@@ -571,6 +572,30 @@  static __init void kvm_free_tmp(void)
 	}
 }
 
+static void kvm_hcall_ev_idle(void)
+{
+	ulong in[8];
+	ulong out[8];
+
+	current_thread_info()->local_flags |= _TLF_NAPPING;
+	local_irq_enable();
+	kvm_hypercall(in, out, HC_VENDOR_EPAPR | HC_EV_IDLE);
+}
+
+static int kvm_para_ev_has_idle(void)
+{
+	struct device_node *hyper_node;
+
+	hyper_node = of_find_node_by_path("/hypervisor");
+	if (!hyper_node)
+		return 0;
+
+	if (of_get_property(hyper_node, "has-idle", NULL))
+		return 1;
+
+	return 0;
+}
+
 static int __init kvm_guest_init(void)
 {
 	if (!kvm_para_available())
@@ -587,6 +612,10 @@  static int __init kvm_guest_init(void)
 	powersave_nap = 1;
 #endif
 
+	/* Install hcall EV_IDLE based power_save for guest kernel */
+	if (kvm_para_ev_has_idle())
+		ppc_md.power_save = kvm_hcall_ev_idle;
+
 free_tmp:
 	kvm_free_tmp();