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

Message ID CALrVBktOaQz5zbv2xRr8YbfvmRToK-kg3kJMFpNHSVeyuYutAA@mail.gmail.com
State New
Headers show

Commit Message

Anup Patel Nov. 25, 2013, 3:57 p.m.
On 25 November 2013 21:19, Anup Patel <anup.patel@linaro.org> 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

Patch

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;