Re: [PATCH 0/2] PSCI system off and reset for KVM ARM/ARM64

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 25 November 2013 21:19, Anup Patel <anup.patel@xxxxxxxxxx> wrote:
> The Power State and Coordination Interface (PSCI) specification defines
> SYSTEM_OFF and SYSTEM_RESET functions for system poweroff and reboot.
>
> This patchset adds emulation of PSCI SYSTEM_OFF and SYSTEM_RESET functions
> in KVM ARM/ARM64 by forwarding them to user space (QEMU or KVMTOOL) using
> KVM_EXIT_SHUTDOWN and KVM_EXIT_RESET exit reasons.
>
> To try this patch from guest kernel, we will need PSCI-based restart and
> poweroff support in the guest kenel for both ARM and ARM64.
>
> Rob Herring has already submitted patches for PSCI-based restart and
> poweroff in ARM kernel but these are not merged yet due unstable device
> tree bindings of kernel PSCI support. We will be having similar patches
> for PSCI-based restart and poweroff in ARM64 kernel.
> (Refer http://www.spinics.net/lists/arm-kernel/msg262217.html)
> (Refer http://www.spinics.net/lists/devicetree/msg05348.html)
>
> Anup Patel (2):
>   KVM: Add KVM_EXIT_RESET to user space API header
>   ARM/ARM64: KVM: Forward PSCI SYSTEM_OFF and SYSTEM_RESET to user
>     space
>
>  arch/arm/include/asm/kvm_psci.h   |    2 +-
>  arch/arm/include/uapi/asm/kvm.h   |    2 ++
>  arch/arm/kvm/handle_exit.c        |    7 ++++++-
>  arch/arm/kvm/psci.c               |   38 +++++++++++++++++++++++++++++--------
>  arch/arm64/include/asm/kvm_psci.h |    2 +-
>  arch/arm64/include/uapi/asm/kvm.h |    2 ++
>  arch/arm64/kvm/handle_exit.c      |   10 ++++++----
>  include/uapi/linux/kvm.h          |    1 +
>  8 files changed, 49 insertions(+), 15 deletions(-)
>
> --
> 1.7.9.5
>

Hi All,

If anyone wants to try this patches using KVMTOOL then they
can find guest kernel side PSCI patches and KVMTOOL patch
attached here.

Regards,
Anup
From 1b16bef992194e20d6999d9f18086e8e832fce4b Mon Sep 17 00:00:00 2001
From: Anup Patel <anup.patel@xxxxxxxxxx>
Date: Mon, 25 Nov 2013 17:05:06 +0530
Subject: [PATCH 6/7] ARM: psci: Add support for system reboot and poweroff

We have PSCI SYSTEM_OFF and SYSTEM_RESET function call emulation
available when running as Guest using KVM ARM.

This patch implements system reboot and poweroff using PSCI
SYSTEM_OFF and SYSTEM_RESET.

Signed-off-by: Anup Patel <anup.patel@xxxxxxxxxx>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@xxxxxxxxxx>
---
 arch/arm/kernel/psci.c |   36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c
index 4693188..30d9d65 100644
--- a/arch/arm/kernel/psci.c
+++ b/arch/arm/kernel/psci.c
@@ -17,11 +17,13 @@
 
 #include <linux/init.h>
 #include <linux/of.h>
+#include <linux/pm.h>
 
 #include <asm/compiler.h>
 #include <asm/errno.h>
 #include <asm/opcodes-sec.h>
 #include <asm/opcodes-virt.h>
+#include <asm/system_misc.h>
 #include <asm/psci.h>
 
 struct psci_operations psci_ops;
@@ -33,6 +35,8 @@ enum psci_function {
 	PSCI_FN_CPU_ON,
 	PSCI_FN_CPU_OFF,
 	PSCI_FN_MIGRATE,
+	PSCI_FN_SYSTEM_OFF,
+	PSCI_FN_SYSTEM_RESET,
 	PSCI_FN_MAX,
 };
 
@@ -153,6 +157,28 @@ static int psci_migrate(unsigned long cpuid)
 	return psci_to_linux_errno(err);
 }
 
+static void psci_power_off(void)
+{
+	int err;
+	u32 fn;
+
+	fn = psci_function_id[PSCI_FN_SYSTEM_OFF];
+	err = invoke_psci_fn(fn, 0, 0, 0);
+	if (err)
+		pr_warning("%s: failed\n", __func__);
+}
+
+static void psci_restart(enum reboot_mode reboot_mode, const char *cmd)
+{
+	int err;
+	u32 fn;
+
+	fn = psci_function_id[PSCI_FN_SYSTEM_RESET];
+	err = invoke_psci_fn(fn, 0, 0, 0);
+	if (err)
+		pr_warning("%s: failed\n", __func__);
+}
+
 static const struct of_device_id psci_of_match[] __initconst = {
 	{ .compatible = "arm,psci",	},
 	{},
@@ -204,6 +230,16 @@ void __init psci_init(void)
 		psci_ops.migrate = psci_migrate;
 	}
 
+	if (!of_property_read_u32(np, "system_off", &id)) {
+		psci_function_id[PSCI_FN_SYSTEM_OFF] = id;
+		pm_power_off = psci_power_off;
+	}
+
+	if (!of_property_read_u32(np, "system_reset", &id)) {
+		psci_function_id[PSCI_FN_SYSTEM_RESET] = id;
+		arm_pm_restart = psci_restart;
+	}
+
 out_put_node:
 	of_node_put(np);
 	return;
-- 
1.7.9.5

From 1f7299ce20ecc6dc6905dc5ec8c47d3944a4425d Mon Sep 17 00:00:00 2001
From: Anup Patel <anup.patel@xxxxxxxxxx>
Date: Mon, 25 Nov 2013 17:05:51 +0530
Subject: [PATCH 7/7] ARM64: psci: Add support for system reboot and poweroff

We have PSCI SYSTEM_OFF and SYSTEM_RESET function call emulation
available when running as Guest using KVM ARM64.

This patch implements system reboot and poweroff using PSCI
SYSTEM_OFF and SYSTEM_RESET.

Signed-off-by: Anup Patel <anup.patel@xxxxxxxxxx>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@xxxxxxxxxx>
---
 arch/arm64/kernel/psci.c |   36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 4f97db3..9469ffa 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -17,12 +17,14 @@
 
 #include <linux/init.h>
 #include <linux/of.h>
+#include <linux/pm.h>
 #include <linux/smp.h>
 
 #include <asm/compiler.h>
 #include <asm/cpu_ops.h>
 #include <asm/errno.h>
 #include <asm/psci.h>
+#include <asm/system_misc.h>
 #include <asm/smp_plat.h>
 
 #define PSCI_POWER_STATE_TYPE_STANDBY		0
@@ -51,6 +53,8 @@ enum psci_function {
 	PSCI_FN_CPU_ON,
 	PSCI_FN_CPU_OFF,
 	PSCI_FN_MIGRATE,
+	PSCI_FN_SYSTEM_OFF,
+	PSCI_FN_SYSTEM_RESET,
 	PSCI_FN_MAX,
 };
 
@@ -171,6 +175,28 @@ static int psci_migrate(unsigned long cpuid)
 	return psci_to_linux_errno(err);
 }
 
+static void psci_power_off(void)
+{
+	int err;
+	u32 fn;
+
+	fn = psci_function_id[PSCI_FN_SYSTEM_OFF];
+	err = invoke_psci_fn(fn, 0, 0, 0);
+	if (err)
+		pr_warning("%s: failed\n", __func__);
+}
+
+static void psci_restart(enum reboot_mode reboot_mode, const char *cmd)
+{
+	int err;
+	u32 fn;
+
+	fn = psci_function_id[PSCI_FN_SYSTEM_RESET];
+	err = invoke_psci_fn(fn, 0, 0, 0);
+	if (err)
+		pr_warning("%s: failed\n", __func__);
+}
+
 static const struct of_device_id psci_of_match[] __initconst = {
 	{ .compatible = "arm,psci",	},
 	{},
@@ -225,6 +251,16 @@ int __init psci_init(void)
 		psci_ops.migrate = psci_migrate;
 	}
 
+	if (!of_property_read_u32(np, "system_off", &id)) {
+		psci_function_id[PSCI_FN_SYSTEM_OFF] = id;
+		pm_power_off = psci_power_off;
+	}
+
+	if (!of_property_read_u32(np, "system_reset", &id)) {
+		psci_function_id[PSCI_FN_SYSTEM_RESET] = id;
+		arm_pm_restart = psci_restart;
+	}
+
 out_put_node:
 	of_node_put(np);
 	return err;
-- 
1.7.9.5

diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index 5df358d..e288731 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -178,7 +178,7 @@ ifeq ($(ARCH), arm64)
 	OBJS		+= arm/aarch64/kvm-cpu.o
 	ARCH_INCLUDE	:= $(HDRS_ARM_COMMON)
 	ARCH_INCLUDE	+= -Iarm/aarch64/include
-
+	CFLAGS		+= -static
 	ARCH_WANT_LIBFDT := y
 endif
 
diff --git a/tools/kvm/arm/aarch64/cortex-a57.c b/tools/kvm/arm/aarch64/cortex-a57.c
index 0c340fb..d079fd4 100644
--- a/tools/kvm/arm/aarch64/cortex-a57.c
+++ b/tools/kvm/arm/aarch64/cortex-a57.c
@@ -71,10 +71,17 @@ static struct kvm_arm_target target_cortex_a57 = {
 	.init		= cortex_a57__vcpu_init,
 };
 
+static struct kvm_arm_target target_xgene_potenza = {
+	.id		= KVM_ARM_TARGET_XGENE_POTENZA,
+	.compatible	= "arm,arm-v8",
+	.init		= cortex_a57__vcpu_init,
+};
+
 static int cortex_a57__core_init(struct kvm *kvm)
 {
 	return (kvm_cpu__register_kvm_arm_target(&target_aem_v8) ||
 		kvm_cpu__register_kvm_arm_target(&target_foundation_v8) ||
-		kvm_cpu__register_kvm_arm_target(&target_cortex_a57));
+		kvm_cpu__register_kvm_arm_target(&target_cortex_a57) ||
+		kvm_cpu__register_kvm_arm_target(&target_xgene_potenza));
 }
 core_init(cortex_a57__core_init);
diff --git a/tools/kvm/arm/fdt.c b/tools/kvm/arm/fdt.c
index 5e18c11..4433829 100644
--- a/tools/kvm/arm/fdt.c
+++ b/tools/kvm/arm/fdt.c
@@ -160,6 +160,8 @@ static int setup_fdt(struct kvm *kvm)
 	_FDT(fdt_property_cell(fdt, "cpu_off", KVM_PSCI_FN_CPU_OFF));
 	_FDT(fdt_property_cell(fdt, "cpu_on", KVM_PSCI_FN_CPU_ON));
 	_FDT(fdt_property_cell(fdt, "migrate", KVM_PSCI_FN_MIGRATE));
+	_FDT(fdt_property_cell(fdt, "system_off", KVM_PSCI_FN_SYSTEM_OFF));
+	_FDT(fdt_property_cell(fdt, "system_reset", KVM_PSCI_FN_SYSTEM_RESET));
 	_FDT(fdt_end_node(fdt));
 
 	/* Finalise. */
diff --git a/tools/kvm/arm/kvm-cpu.c b/tools/kvm/arm/kvm-cpu.c
index d31e7b1..2297b04 100644
--- a/tools/kvm/arm/kvm-cpu.c
+++ b/tools/kvm/arm/kvm-cpu.c
@@ -33,7 +33,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	struct kvm_arm_target *target;
 	struct kvm_cpu *vcpu;
 	int coalesced_offset, mmap_size, err = -1;
-	unsigned int i;
+	struct kvm_vcpu_init pinit = { 0 };
 	struct kvm_vcpu_init vcpu_init = {
 		.features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id)
 	};
@@ -55,19 +55,32 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	if (vcpu->kvm_run == MAP_FAILED)
 		die("unable to mmap vcpu fd");
 
-	/* Find an appropriate target CPU type. */
-	for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
-		if (!kvm_arm_targets[i])
-			continue;
-		target = kvm_arm_targets[i];
-		vcpu_init.target = target->id;
-		err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init);
-		if (!err)
-			break;
-	}
+	/* Find an preferred target CPU type. */
+	err = ioctl(kvm->vm_fd, KVM_ARM_PREFERRED_TARGET, &pinit);
+	if (err)
+		die("KVM_ARM_PREFERRED_TARGET ioctl failed (err %d)\n", err);
+
+	/* Sanity check on target type returned by KVM */
+	if (ARRAY_SIZE(kvm_arm_targets) <= pinit.target)
+		die("Unknown vcpu target type %d from KVM\n", pinit.target);
+
+	/* Get a registerd target type */
+	target = kvm_arm_targets[pinit.target];
+	if (!target)
+		die("Target type %d not registered\n", pinit.target);
+
+	/* Prepare VCPU init target */
+	vcpu_init.target = pinit.target;
+	vcpu_init.features[0] |= pinit.features[0];
+
+	/* Call VCPU init ioctl */
+	err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init);
+	if (err)
+		die("KVM_ARM_VCPU_INIT ioctl failed (err %d)\n", err);
 
-	if (err || target->init(vcpu))
-		die("Unable to initialise ARM vcpu");
+	/* Do target specific init */
+	if (target->init(vcpu))
+		die("Unable to initialise ARM vcpu\n");
 
 	coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION,
 				 KVM_CAP_COALESCED_MMIO);
diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
index be05c49..de33a0a 100644
--- a/tools/kvm/kvm-cpu.c
+++ b/tools/kvm/kvm-cpu.c
@@ -153,6 +153,10 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
 				break;
 			goto exit_kvm;
 		case KVM_EXIT_SHUTDOWN:
+			printf("KVMTOOL: got shutdown exit\n");
+			goto exit_kvm;
+		case KVM_EXIT_RESET:
+			printf("KVMTOOL: got reset exit\n");
 			goto exit_kvm;
 		default: {
 			bool ret;
diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
index cfd30dd..6965fd4 100644
--- a/tools/kvm/kvm.c
+++ b/tools/kvm/kvm.c
@@ -55,6 +55,7 @@ const char *kvm_exit_reasons[] = {
 #ifdef CONFIG_PPC64
 	DEFINE_KVM_EXIT_REASON(KVM_EXIT_PAPR_HCALL),
 #endif
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_RESET),
 };
 
 static int pause_event;
_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm

[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux