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