Currently, KVM ARM/ARM64 only provides in-kernel emulation of Power State and Coordination Interface (PSCI) v0.1.
This patchset aims at providing newer PSCI v0.2 for KVM ARM/ARM64 VCPUs such that it does not break current KVM ARM/ARM64 ABI. Also, the patchset provides emulation of only few PSCI v0.2 functions such as PSCI_VERSION, CPU_ON, and CPU_OFF. Emulation of other PSCI v0.2 functions will be added later.
The user space tools (i.e. QEMU or KVMTOOL) will have to explicitly enable KVM_ARM_VCPU_PSCI_0_2 feature using KVM_ARM_VCPU_INIT ioctl for providing PSCI v0.2 to VCPUs.
Changlog:
V4: - Implement all mandatory functions required by PSCI v0.2
V3: - Make KVM_ARM_VCPU_PSCI_0_2 feature experiementatl for now so that it fails for user space till all mandatory PSCI v0.2 functions are emulated by KVM ARM/ARM64 - Have separate patch for making KVM_ARM_VCPU_PSCI_0_2 feature available to user space. This patch can be defferred for now
V2: - Don't rename PSCI return values KVM_PSCI_RET_NI and KVM_PSCI_RET_INVAL - Added kvm_psci_version() to get PSCI version available to VCPU - Fixed grammer in Documentation/virtual/kvm/api.txt
V1: - Initial RFC PATCH
Anup Patel (10): KVM: Add capability to advertise PSCI v0.2 support ARM/ARM64: KVM: Add base for PSCI v0.2 emulation KVM: Documentation: Add info regarding KVM_ARM_VCPU_PSCI_0_2 feature ARM/ARM64: KVM: Make kvm_psci_call() return convention more flexible KVM: Add KVM_EXIT_SYSTEM_EVENT to user space API header ARM/ARM64: KVM: Emulate PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET ARM/ARM64: KVM: Emulate PSCI v0.2 AFFINITY_INFO ARM/ARM64: KVM: Emulate PSCI v0.2 MIGRATE_INFO_TYPE and related functions ARM/ARM64: KVM: Fix CPU_ON emulation for PSCI v0.2 ARM/ARM64: KVM: Emulate PSCI v0.2 CPU_SUSPEND
Documentation/virtual/kvm/api.txt | 17 +++ arch/arm/include/asm/kvm_host.h | 7 +- arch/arm/include/asm/kvm_psci.h | 7 +- arch/arm/include/uapi/asm/kvm.h | 35 ++++- arch/arm/kvm/arm.c | 1 + arch/arm/kvm/handle_exit.c | 10 +- arch/arm/kvm/psci.c | 270 ++++++++++++++++++++++++++++++++++--- arch/arm/kvm/reset.c | 4 + arch/arm64/include/asm/kvm_host.h | 7 +- arch/arm64/include/asm/kvm_psci.h | 7 +- arch/arm64/include/uapi/asm/kvm.h | 35 ++++- arch/arm64/kvm/handle_exit.c | 10 +- arch/arm64/kvm/reset.c | 4 + include/uapi/linux/kvm.h | 9 ++ 14 files changed, 395 insertions(+), 28 deletions(-)
User space (i.e. QEMU or KVMTOOL) should be able to check whether KVM ARM/ARM64 supports in-kernel PSCI v0.2 emulation. For this purpose, we define KVM_CAP_ARM_PSCI_0_2 in KVM user space interface header.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org --- include/uapi/linux/kvm.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 932d7f2..fb3c3f3 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -675,6 +675,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_SPAPR_MULTITCE 94 #define KVM_CAP_EXT_EMUL_CPUID 95 #define KVM_CAP_HYPERV_TIME 96 +#define KVM_CAP_ARM_PSCI_0_2 97
#ifdef KVM_CAP_IRQ_ROUTING
On Thu, Feb 06, 2014 at 05:01:33PM +0530, Anup Patel wrote:
User space (i.e. QEMU or KVMTOOL) should be able to check whether KVM ARM/ARM64 supports in-kernel PSCI v0.2 emulation. For this purpose, we define KVM_CAP_ARM_PSCI_0_2 in KVM user space interface header.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
include/uapi/linux/kvm.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 932d7f2..fb3c3f3 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -675,6 +675,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_SPAPR_MULTITCE 94 #define KVM_CAP_EXT_EMUL_CPUID 95 #define KVM_CAP_HYPERV_TIME 96 +#define KVM_CAP_ARM_PSCI_0_2 97 #ifdef KVM_CAP_IRQ_ROUTING -- 1.7.9.5
Acked-by: Christoffer Dall christoffer.dall@linaro.org
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to VCPUs. This patch extends current in-kernel PSCI emulation to provide PSCI v0.2 interface to VCPUs.
By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for keeping the ABI backward-compatible.
To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU init using KVM_ARM_VCPU_INIT ioctl.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org --- arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/include/asm/kvm_psci.h | 4 ++ arch/arm/include/uapi/asm/kvm.h | 35 ++++++++++++++- arch/arm/kvm/arm.c | 1 + arch/arm/kvm/psci.c | 85 +++++++++++++++++++++++++++++++------ arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_psci.h | 4 ++ arch/arm64/include/uapi/asm/kvm.h | 35 ++++++++++++++- 8 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 09af149..193ceaf 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -36,7 +36,7 @@ #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HAVE_ONE_REG
-#define KVM_VCPU_MAX_FEATURES 1 +#define KVM_VCPU_MAX_FEATURES 2
#include <kvm/arm_vgic.h>
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 9a83d98..4c0e3e1 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM_KVM_PSCI_H__ #define __ARM_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2 + +int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ef0c878..9c922d9 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -83,6 +83,7 @@ struct kvm_regs { #define KVM_VGIC_V2_CPU_SIZE 0x2000
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ +#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -192,7 +193,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -201,9 +202,41 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n)) + +#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \ + KVM_PSCI_0_2_FN(6) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \ + KVM_PSCI_0_2_FN(7) +#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9) + +#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \ + KVM_PSCI_0_2_FN64(7) + +/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif /* __ARM_KVM_H__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248e..c8a71df 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: case KVM_CAP_ONE_REG: case KVM_CAP_ARM_PSCI: + case KVM_CAP_ARM_PSCI_0_2: r = 1; break; case KVM_CAP_COALESCED_MMIO: diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 448f60e..e4ec4af 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,17 +85,57 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; }
-/** - * kvm_psci_call - handle PSCI call if r0 value is in range - * @vcpu: Pointer to the VCPU struct - * - * Handle PSCI calls from guests through traps from HVC instructions. - * The calling convention is similar to SMC calls to the secure world where - * the function number is placed in r0 and this function returns true if the - * function number specified in r0 is withing the PSCI range, and false - * otherwise. - */ -bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_version(struct kvm_vcpu *vcpu) +{ + if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) + return KVM_ARM_PSCI_0_2; + + return KVM_ARM_PSCI_0_1; +} + +static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) +{ + unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); + unsigned long val; + + switch (psci_fn) { + case KVM_PSCI_0_2_FN_PSCI_VERSION: + /* + * Bits[31:16] = Major Version = 0 + * Bits[15:0] = Minor Version = 2 + */ + val = 2; + break; + case KVM_PSCI_0_2_FN_CPU_OFF: + kvm_psci_vcpu_off(vcpu); + val = KVM_PSCI_RET_SUCCESS; + break; + case KVM_PSCI_0_2_FN_CPU_ON: + case KVM_PSCI_0_2_FN64_CPU_ON: + val = kvm_psci_vcpu_on(vcpu); + break; + case KVM_PSCI_0_2_FN_CPU_SUSPEND: + case KVM_PSCI_0_2_FN_AFFINITY_INFO: + case KVM_PSCI_0_2_FN_MIGRATE: + case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE: + case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: + case KVM_PSCI_0_2_FN_SYSTEM_OFF: + case KVM_PSCI_0_2_FN_SYSTEM_RESET: + case KVM_PSCI_0_2_FN64_CPU_SUSPEND: + case KVM_PSCI_0_2_FN64_AFFINITY_INFO: + case KVM_PSCI_0_2_FN64_MIGRATE: + case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: + val = KVM_PSCI_RET_NI; + break; + default: + return false; + } + + *vcpu_reg(vcpu, 0) = val; + return true; +} + +static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -112,7 +152,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_PSCI_FN_MIGRATE: val = KVM_PSCI_RET_NI; break; - default: return false; } @@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) *vcpu_reg(vcpu, 0) = val; return true; } + +/** + * kvm_psci_call - handle PSCI call if r0 value is in range + * @vcpu: Pointer to the VCPU struct + * + * Handle PSCI calls from guests through traps from HVC instructions. + * The calling convention is similar to SMC calls to the secure world where + * the function number is placed in r0 and this function returns true if the + * function number specified in r0 is withing the PSCI range, and false + * otherwise. + */ +bool kvm_psci_call(struct kvm_vcpu *vcpu) +{ + switch (kvm_psci_version(vcpu)) { + case KVM_ARM_PSCI_0_2: + return kvm_psci_0_2_call(vcpu); + case KVM_ARM_PSCI_0_1: + return kvm_psci_0_1_call(vcpu); + default: + return false; + }; +} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0a1d697..92242ce 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h>
-#define KVM_VCPU_MAX_FEATURES 2 +#define KVM_VCPU_MAX_FEATURES 3
struct kvm_vcpu; int kvm_target_cpu(void); diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e301a48..e25c658 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM64_KVM_PSCI_H__ #define __ARM64_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2 + +int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index eaf54a3..cadc318 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -77,6 +77,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ +#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -177,7 +178,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -186,10 +187,42 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n)) + +#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \ + KVM_PSCI_0_2_FN(6) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \ + KVM_PSCI_0_2_FN(7) +#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9) + +#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \ + KVM_PSCI_0_2_FN64(7) + +/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif
On Thursday, February 06, 2014 8:32 PM, Anup Patel wrote:
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to VCPUs. This patch extends current in-kernel PSCI emulation to provide PSCI v0.2 interface to VCPUs.
By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for keeping the ABI backward- compatible.
To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU init using KVM_ARM_VCPU_INIT ioctl.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/include/asm/kvm_psci.h | 4 ++ arch/arm/include/uapi/asm/kvm.h | 35 ++++++++++++++- arch/arm/kvm/arm.c | 1 + arch/arm/kvm/psci.c | 85 +++++++++++++++++++++++++++++++------ arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_psci.h | 4 ++ arch/arm64/include/uapi/asm/kvm.h | 35 ++++++++++++++- 8 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 09af149..193ceaf 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -36,7 +36,7 @@ #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HAVE_ONE_REG
-#define KVM_VCPU_MAX_FEATURES 1 +#define KVM_VCPU_MAX_FEATURES 2
#include <kvm/arm_vgic.h>
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 9a83d98..4c0e3e1 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM_KVM_PSCI_H__ #define __ARM_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ef0c878..9c922d9 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -83,6 +83,7 @@ struct kvm_regs { #define KVM_VGIC_V2_CPU_SIZE 0x2000
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ +#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -192,7 +193,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -201,9 +202,41 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
Hi
This patch describes PSCI v0.2 specification well. Instead, I have a question on interface types, not implementation.
According to PSCI v0.2 document, it does not cover DVFS. Could I get an idea why DVFS is not supported?
Best Regards Jungseok Lee
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif /* __ARM_KVM_H__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248e..c8a71df 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: case KVM_CAP_ONE_REG: case KVM_CAP_ARM_PSCI:
- case KVM_CAP_ARM_PSCI_0_2: r = 1; break; case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 448f60e..e4ec4af 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,17 +85,57 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; }
-/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure world where
- the function number is placed in r0 and this function returns true if the
- function number specified in r0 is withing the PSCI range, and false
- otherwise.
- */
-bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_version(struct kvm_vcpu *vcpu) {
- if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
return KVM_ARM_PSCI_0_2;
- return KVM_ARM_PSCI_0_1;
+}
+static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) {
- unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
- unsigned long val;
- switch (psci_fn) {
- case KVM_PSCI_0_2_FN_PSCI_VERSION:
/*
* Bits[31:16] = Major Version = 0
* Bits[15:0] = Minor Version = 2
*/
val = 2;
break;
- case KVM_PSCI_0_2_FN_CPU_OFF:
kvm_psci_vcpu_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
break;
- case KVM_PSCI_0_2_FN_CPU_ON:
- case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break;
- case KVM_PSCI_0_2_FN_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN_AFFINITY_INFO:
- case KVM_PSCI_0_2_FN_MIGRATE:
- case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
- case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
- case KVM_PSCI_0_2_FN_SYSTEM_OFF:
- case KVM_PSCI_0_2_FN_SYSTEM_RESET:
- case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
- case KVM_PSCI_0_2_FN64_MIGRATE:
- case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
break;
- default:
return false;
- }
- *vcpu_reg(vcpu, 0) = val;
- return true;
+}
+static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -112,7 +152,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_PSCI_FN_MIGRATE: val = KVM_PSCI_RET_NI; break;
- default: return false; }
@@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) *vcpu_reg(vcpu, 0) = val; return true; }
+/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure world
+where
- the function number is placed in r0 and this function returns true
+if the
- function number specified in r0 is withing the PSCI range, and false
- otherwise.
- */
+bool kvm_psci_call(struct kvm_vcpu *vcpu) {
- switch (kvm_psci_version(vcpu)) {
- case KVM_ARM_PSCI_0_2:
return kvm_psci_0_2_call(vcpu);
- case KVM_ARM_PSCI_0_1:
return kvm_psci_0_1_call(vcpu);
- default:
return false;
- };
+} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0a1d697..92242ce 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h>
-#define KVM_VCPU_MAX_FEATURES 2 +#define KVM_VCPU_MAX_FEATURES 3
struct kvm_vcpu; int kvm_target_cpu(void); diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e301a48..e25c658 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM64_KVM_PSCI_H__ #define __ARM64_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index eaf54a3..cadc318 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -77,6 +77,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ +#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -177,7 +178,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -186,10 +187,42 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif
-- 1.7.9.5
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
On Fri, Feb 7, 2014 at 1:58 PM, Jungseok Lee jays.lee@samsung.com wrote:
On Thursday, February 06, 2014 8:32 PM, Anup Patel wrote:
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to VCPUs. This patch extends current in-kernel PSCI emulation to provide PSCI v0.2 interface to VCPUs.
By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for keeping the ABI backward- compatible.
To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU init using KVM_ARM_VCPU_INIT ioctl.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/include/asm/kvm_psci.h | 4 ++ arch/arm/include/uapi/asm/kvm.h | 35 ++++++++++++++- arch/arm/kvm/arm.c | 1 + arch/arm/kvm/psci.c | 85 +++++++++++++++++++++++++++++++------ arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_psci.h | 4 ++ arch/arm64/include/uapi/asm/kvm.h | 35 ++++++++++++++- 8 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 09af149..193ceaf 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -36,7 +36,7 @@ #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HAVE_ONE_REG
-#define KVM_VCPU_MAX_FEATURES 1 +#define KVM_VCPU_MAX_FEATURES 2
#include <kvm/arm_vgic.h>
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 9a83d98..4c0e3e1 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM_KVM_PSCI_H__ #define __ARM_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ef0c878..9c922d9 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -83,6 +83,7 @@ struct kvm_regs { #define KVM_VGIC_V2_CPU_SIZE 0x2000
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ +#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -192,7 +193,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -201,9 +202,41 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
Hi
This patch describes PSCI v0.2 specification well. Instead, I have a question on interface types, not implementation.
According to PSCI v0.2 document, it does not cover DVFS. Could I get an idea why DVFS is not supported?
PSCI v0.2 only describes few mandatory functions required for being PSCI v0.2 compliant. For rest of the stuff such as DVFS you will need to define your own platform specific PSCI function. (Marc/Mark correct me if I am wrong here?)
Mab be in future some PSCI vX.Y will define standardized PSCI function for DVFS too.
Regards, Anup
Best Regards Jungseok Lee
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif /* __ARM_KVM_H__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248e..c8a71df 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: case KVM_CAP_ONE_REG: case KVM_CAP_ARM_PSCI:
case KVM_CAP_ARM_PSCI_0_2: r = 1; break; case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 448f60e..e4ec4af 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,17 +85,57 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; }
-/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure world where
- the function number is placed in r0 and this function returns true if the
- function number specified in r0 is withing the PSCI range, and false
- otherwise.
- */
-bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_version(struct kvm_vcpu *vcpu) {
if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
return KVM_ARM_PSCI_0_2;
return KVM_ARM_PSCI_0_1;
+}
+static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) {
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
switch (psci_fn) {
case KVM_PSCI_0_2_FN_PSCI_VERSION:
/*
* Bits[31:16] = Major Version = 0
* Bits[15:0] = Minor Version = 2
*/
val = 2;
break;
case KVM_PSCI_0_2_FN_CPU_OFF:
kvm_psci_vcpu_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
break;
case KVM_PSCI_0_2_FN_CPU_ON:
case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
case KVM_PSCI_0_2_FN_AFFINITY_INFO:
case KVM_PSCI_0_2_FN_MIGRATE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
case KVM_PSCI_0_2_FN_SYSTEM_OFF:
case KVM_PSCI_0_2_FN_SYSTEM_RESET:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
case KVM_PSCI_0_2_FN64_MIGRATE:
case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
break;
default:
return false;
}
*vcpu_reg(vcpu, 0) = val;
return true;
+}
+static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -112,7 +152,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_PSCI_FN_MIGRATE: val = KVM_PSCI_RET_NI; break;
default: return false; }
@@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) *vcpu_reg(vcpu, 0) = val; return true; }
+/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure world
+where
- the function number is placed in r0 and this function returns true
+if the
- function number specified in r0 is withing the PSCI range, and false
- otherwise.
- */
+bool kvm_psci_call(struct kvm_vcpu *vcpu) {
switch (kvm_psci_version(vcpu)) {
case KVM_ARM_PSCI_0_2:
return kvm_psci_0_2_call(vcpu);
case KVM_ARM_PSCI_0_1:
return kvm_psci_0_1_call(vcpu);
default:
return false;
};
+} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0a1d697..92242ce 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h>
-#define KVM_VCPU_MAX_FEATURES 2 +#define KVM_VCPU_MAX_FEATURES 3
struct kvm_vcpu; int kvm_target_cpu(void); diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e301a48..e25c658 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM64_KVM_PSCI_H__ #define __ARM64_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index eaf54a3..cadc318 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -77,6 +77,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ +#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -177,7 +178,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -186,10 +187,42 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif
-- 1.7.9.5
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
On Friday, February 07, 2014 5:36 PM, Anup Patel wrote:
On Fri, Feb 7, 2014 at 1:58 PM, Jungseok Lee jays.lee@samsung.com wrote:
On Thursday, February 06, 2014 8:32 PM, Anup Patel wrote:
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to VCPUs. This patch extends current in-kernel PSCI emulation to provide PSCI v0.2 interface to
VCPUs.
By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for keeping the ABI backward- compatible.
To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU init using KVM_ARM_VCPU_INIT ioctl.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/include/asm/kvm_psci.h | 4 ++ arch/arm/include/uapi/asm/kvm.h | 35 ++++++++++++++- arch/arm/kvm/arm.c | 1 + arch/arm/kvm/psci.c | 85 +++++++++++++++++++++++++++++++------ arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_psci.h | 4 ++ arch/arm64/include/uapi/asm/kvm.h | 35 ++++++++++++++- 8 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 09af149..193ceaf 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -36,7 +36,7 @@ #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HAVE_ONE_REG
-#define KVM_VCPU_MAX_FEATURES 1 +#define KVM_VCPU_MAX_FEATURES 2
#include <kvm/arm_vgic.h>
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 9a83d98..4c0e3e1 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM_KVM_PSCI_H__ #define __ARM_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ef0c878..9c922d9 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -83,6 +83,7 @@ struct kvm_regs { #define KVM_VGIC_V2_CPU_SIZE 0x2000
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ +#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -192,7 +193,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -201,9 +202,41 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) #define +KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6) #define
+KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
Hi
This patch describes PSCI v0.2 specification well. Instead, I have a question on interface types, not implementation.
According to PSCI v0.2 document, it does not cover DVFS. Could I get an idea why DVFS is not supported?
PSCI v0.2 only describes few mandatory functions required for being PSCI v0.2 compliant. For rest of the stuff such as DVFS you will need to define your own platform specific PSCI function. (Marc/Mark correct me if I am wrong here?)
It seems that I should change architecture codes if I need other interfaces. Under this implementation, I should add my own interface to generic codes, such as, arch/arm/include/asm/kvm_psci.h. However, I think that it is not acceptable to upstream. If so, is there any place to define a platform specific PSCI functions?
Best Regards Jungseok Lee
Mab be in future some PSCI vX.Y will define standardized PSCI function for DVFS too.
Regards, Anup
Best Regards Jungseok Lee
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif /* __ARM_KVM_H__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248e..c8a71df 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: case KVM_CAP_ONE_REG: case KVM_CAP_ARM_PSCI:
case KVM_CAP_ARM_PSCI_0_2: r = 1; break; case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 448f60e..e4ec4af 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,17 +85,57 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; }
-/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure
world where
- the function number is placed in r0 and this function returns
true if the
- function number specified in r0 is withing the PSCI range, and
false
- otherwise.
- */
-bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_version(struct kvm_vcpu *vcpu) {
if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
return KVM_ARM_PSCI_0_2;
return KVM_ARM_PSCI_0_1;
+}
+static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) {
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
switch (psci_fn) {
case KVM_PSCI_0_2_FN_PSCI_VERSION:
/*
* Bits[31:16] = Major Version = 0
* Bits[15:0] = Minor Version = 2
*/
val = 2;
break;
case KVM_PSCI_0_2_FN_CPU_OFF:
kvm_psci_vcpu_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
break;
case KVM_PSCI_0_2_FN_CPU_ON:
case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
case KVM_PSCI_0_2_FN_AFFINITY_INFO:
case KVM_PSCI_0_2_FN_MIGRATE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
case KVM_PSCI_0_2_FN_SYSTEM_OFF:
case KVM_PSCI_0_2_FN_SYSTEM_RESET:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
case KVM_PSCI_0_2_FN64_MIGRATE:
case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
break;
default:
return false;
}
*vcpu_reg(vcpu, 0) = val;
return true;
+}
+static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -112,7 +152,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_PSCI_FN_MIGRATE: val = KVM_PSCI_RET_NI; break;
default: return false; }
@@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) *vcpu_reg(vcpu, 0) = val; return true; }
+/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure
+world where
- the function number is placed in r0 and this function returns
+true if the
- function number specified in r0 is withing the PSCI range, and
+false
- otherwise.
- */
+bool kvm_psci_call(struct kvm_vcpu *vcpu) {
switch (kvm_psci_version(vcpu)) {
case KVM_ARM_PSCI_0_2:
return kvm_psci_0_2_call(vcpu);
case KVM_ARM_PSCI_0_1:
return kvm_psci_0_1_call(vcpu);
default:
return false;
};
+} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0a1d697..92242ce 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h>
-#define KVM_VCPU_MAX_FEATURES 2 +#define KVM_VCPU_MAX_FEATURES 3
struct kvm_vcpu; int kvm_target_cpu(void); diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e301a48..e25c658 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM64_KVM_PSCI_H__ #define __ARM64_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index eaf54a3..cadc318 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -77,6 +77,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ +#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -177,7 +178,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -186,10 +187,42 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) #define +KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6) #define
+KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif
-- 1.7.9.5
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
On Fri, Feb 7, 2014 at 2:37 PM, Jungseok Lee jays.lee@samsung.com wrote:
On Friday, February 07, 2014 5:36 PM, Anup Patel wrote:
On Fri, Feb 7, 2014 at 1:58 PM, Jungseok Lee jays.lee@samsung.com wrote:
On Thursday, February 06, 2014 8:32 PM, Anup Patel wrote:
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to VCPUs. This patch extends current in-kernel PSCI emulation to provide PSCI v0.2 interface to
VCPUs.
By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for keeping the ABI backward- compatible.
To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU init using KVM_ARM_VCPU_INIT ioctl.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/include/asm/kvm_psci.h | 4 ++ arch/arm/include/uapi/asm/kvm.h | 35 ++++++++++++++- arch/arm/kvm/arm.c | 1 + arch/arm/kvm/psci.c | 85 +++++++++++++++++++++++++++++++------ arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_psci.h | 4 ++ arch/arm64/include/uapi/asm/kvm.h | 35 ++++++++++++++- 8 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 09af149..193ceaf 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -36,7 +36,7 @@ #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HAVE_ONE_REG
-#define KVM_VCPU_MAX_FEATURES 1 +#define KVM_VCPU_MAX_FEATURES 2
#include <kvm/arm_vgic.h>
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 9a83d98..4c0e3e1 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM_KVM_PSCI_H__ #define __ARM_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ef0c878..9c922d9 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -83,6 +83,7 @@ struct kvm_regs { #define KVM_VGIC_V2_CPU_SIZE 0x2000
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ +#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -192,7 +193,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -201,9 +202,41 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) #define +KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6) #define
+KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
Hi
This patch describes PSCI v0.2 specification well. Instead, I have a question on interface types, not implementation.
According to PSCI v0.2 document, it does not cover DVFS. Could I get an idea why DVFS is not supported?
PSCI v0.2 only describes few mandatory functions required for being PSCI v0.2 compliant. For rest of the stuff such as DVFS you will need to define your own platform specific PSCI function. (Marc/Mark correct me if I am wrong here?)
It seems that I should change architecture codes if I need other interfaces. Under this implementation, I should add my own interface to generic codes, such as, arch/arm/include/asm/kvm_psci.h. However, I think that it is not acceptable to upstream. If so, is there any place to define a platform specific PSCI functions?
Are you trying to emulate your platform specific DVFS PSCI function for a VM using KVM ARM/ARM64??
If so then arch/arm/kvm/psci.c is not the place for it. All platform specific PSCI function are to be emulated from user space. KVM ARM/ARM64 will only emulate HVC-based mandatory PSCI v0.2 functions.
User space emulation of platform specific PSCI functions are still a TODO item for KVM ARM/ARM64. It will require a mechanism in KVM ARM/ARM64 to route SMC-based PSCI function calls to user space (i.e. QEMU or KVMTOOL).
Regards, Anup
Best Regards Jungseok Lee
Mab be in future some PSCI vX.Y will define standardized PSCI function for DVFS too.
Regards, Anup
Best Regards Jungseok Lee
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif /* __ARM_KVM_H__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248e..c8a71df 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: case KVM_CAP_ONE_REG: case KVM_CAP_ARM_PSCI:
case KVM_CAP_ARM_PSCI_0_2: r = 1; break; case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 448f60e..e4ec4af 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,17 +85,57 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; }
-/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure
world where
- the function number is placed in r0 and this function returns
true if the
- function number specified in r0 is withing the PSCI range, and
false
- otherwise.
- */
-bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_version(struct kvm_vcpu *vcpu) {
if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
return KVM_ARM_PSCI_0_2;
return KVM_ARM_PSCI_0_1;
+}
+static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) {
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
switch (psci_fn) {
case KVM_PSCI_0_2_FN_PSCI_VERSION:
/*
* Bits[31:16] = Major Version = 0
* Bits[15:0] = Minor Version = 2
*/
val = 2;
break;
case KVM_PSCI_0_2_FN_CPU_OFF:
kvm_psci_vcpu_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
break;
case KVM_PSCI_0_2_FN_CPU_ON:
case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
case KVM_PSCI_0_2_FN_AFFINITY_INFO:
case KVM_PSCI_0_2_FN_MIGRATE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
case KVM_PSCI_0_2_FN_SYSTEM_OFF:
case KVM_PSCI_0_2_FN_SYSTEM_RESET:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
case KVM_PSCI_0_2_FN64_MIGRATE:
case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
break;
default:
return false;
}
*vcpu_reg(vcpu, 0) = val;
return true;
+}
+static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -112,7 +152,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_PSCI_FN_MIGRATE: val = KVM_PSCI_RET_NI; break;
default: return false; }
@@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) *vcpu_reg(vcpu, 0) = val; return true; }
+/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure
+world where
- the function number is placed in r0 and this function returns
+true if the
- function number specified in r0 is withing the PSCI range, and
+false
- otherwise.
- */
+bool kvm_psci_call(struct kvm_vcpu *vcpu) {
switch (kvm_psci_version(vcpu)) {
case KVM_ARM_PSCI_0_2:
return kvm_psci_0_2_call(vcpu);
case KVM_ARM_PSCI_0_1:
return kvm_psci_0_1_call(vcpu);
default:
return false;
};
+} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0a1d697..92242ce 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h>
-#define KVM_VCPU_MAX_FEATURES 2 +#define KVM_VCPU_MAX_FEATURES 3
struct kvm_vcpu; int kvm_target_cpu(void); diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e301a48..e25c658 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM64_KVM_PSCI_H__ #define __ARM64_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index eaf54a3..cadc318 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -77,6 +77,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ +#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -177,7 +178,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -186,10 +187,42 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) #define +KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6) #define
+KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif
-- 1.7.9.5
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
-----Original Message----- From: Anup Patel [mailto:anup@brainfault.org] Sent: Friday, February 07, 2014 6:26 PM To: Jungseok Lee Cc: Anup Patel; kvmarm@lists.cs.columbia.edu; Mark Rutland; linaro-kernel@lists.linaro.org; patches@linaro.org; Marc Zyngier; patches; linux-arm-kernel Subject: Re: [PATCH v4 02/10] ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
On Fri, Feb 7, 2014 at 2:37 PM, Jungseok Lee jays.lee@samsung.com wrote:
On Friday, February 07, 2014 5:36 PM, Anup Patel wrote:
On Fri, Feb 7, 2014 at 1:58 PM, Jungseok Lee jays.lee@samsung.com wrote:
On Thursday, February 06, 2014 8:32 PM, Anup Patel wrote:
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to VCPUs. This patch extends current in-kernel PSCI emulation to provide PSCI v0.2 interface to
VCPUs.
By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for keeping the ABI backward- compatible.
To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU init using KVM_ARM_VCPU_INIT ioctl.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/include/asm/kvm_psci.h | 4 ++ arch/arm/include/uapi/asm/kvm.h | 35 ++++++++++++++- arch/arm/kvm/arm.c | 1 + arch/arm/kvm/psci.c | 85 +++++++++++++++++++++++++++++++------ arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_psci.h | 4 ++ arch/arm64/include/uapi/asm/kvm.h | 35 ++++++++++++++- 8 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 09af149..193ceaf 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -36,7 +36,7 @@ #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HAVE_ONE_REG
-#define KVM_VCPU_MAX_FEATURES 1 +#define KVM_VCPU_MAX_FEATURES 2
#include <kvm/arm_vgic.h>
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 9a83d98..4c0e3e1 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM_KVM_PSCI_H__ #define __ARM_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ef0c878..9c922d9 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -83,6 +83,7 @@ struct kvm_regs { #define KVM_VGIC_V2_CPU_SIZE 0x2000
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ +#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -192,7 +193,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -201,9 +202,41 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) #define +KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6) #define
+KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
Hi
This patch describes PSCI v0.2 specification well. Instead, I have a question on interface types, not implementation.
According to PSCI v0.2 document, it does not cover DVFS. Could I get an idea why DVFS is not supported?
PSCI v0.2 only describes few mandatory functions required for being PSCI v0.2 compliant. For rest of the stuff such as DVFS you will need to define your own platform
specific PSCI function.
(Marc/Mark correct me if I am wrong here?)
It seems that I should change architecture codes if I need other interfaces. Under this implementation, I should add my own interface to generic codes, such as, arch/arm/include/asm/kvm_psci.h. However, I think that it is not acceptable to upstream. If so, is there any place to define a platform specific PSCI functions?
Are you trying to emulate your platform specific DVFS PSCI function for a VM using KVM ARM/ARM64??
No, I am not. My original intention is to clarify the interface between KVM and VM if DVFS scheme is applied to VM. Currently, PSIC v0.2 does not define it. Thus, I wonder why this interface is not covered.
If so then arch/arm/kvm/psci.c is not the place for it. All platform specific PSCI function are to be emulated from user space. KVM ARM/ARM64 will only emulate HVC-based mandatory PSCI v0.2 functions.
Okay, clear.
Regards Jungseok Lee
User space emulation of platform specific PSCI functions are still a TODO item for KVM ARM/ARM64. It will require a mechanism in KVM ARM/ARM64 to route SMC-based PSCI function calls to user space (i.e. QEMU or KVMTOOL).
Regards, Anup
Best Regards Jungseok Lee
Mab be in future some PSCI vX.Y will define standardized PSCI function for DVFS too.
Regards, Anup
Best Regards Jungseok Lee
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif /* __ARM_KVM_H__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248e..c8a71df 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: case KVM_CAP_ONE_REG: case KVM_CAP_ARM_PSCI:
case KVM_CAP_ARM_PSCI_0_2: r = 1; break; case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 448f60e..e4ec4af 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,17 +85,57 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; }
-/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure
world where
- the function number is placed in r0 and this function returns
true if the
- function number specified in r0 is withing the PSCI range, and
false
- otherwise.
- */
-bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_version(struct kvm_vcpu *vcpu) {
if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
return KVM_ARM_PSCI_0_2;
return KVM_ARM_PSCI_0_1;
+}
+static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) {
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
switch (psci_fn) {
case KVM_PSCI_0_2_FN_PSCI_VERSION:
/*
* Bits[31:16] = Major Version = 0
* Bits[15:0] = Minor Version = 2
*/
val = 2;
break;
case KVM_PSCI_0_2_FN_CPU_OFF:
kvm_psci_vcpu_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
break;
case KVM_PSCI_0_2_FN_CPU_ON:
case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
case KVM_PSCI_0_2_FN_AFFINITY_INFO:
case KVM_PSCI_0_2_FN_MIGRATE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
case KVM_PSCI_0_2_FN_SYSTEM_OFF:
case KVM_PSCI_0_2_FN_SYSTEM_RESET:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
case KVM_PSCI_0_2_FN64_MIGRATE:
case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
break;
default:
return false;
}
*vcpu_reg(vcpu, 0) = val;
return true;
+}
+static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -112,7 +152,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_PSCI_FN_MIGRATE: val = KVM_PSCI_RET_NI; break;
default: return false; }
@@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) *vcpu_reg(vcpu, 0) = val; return true; }
+/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure
+world where
- the function number is placed in r0 and this function returns
+true if the
- function number specified in r0 is withing the PSCI range, and
+false
- otherwise.
- */
+bool kvm_psci_call(struct kvm_vcpu *vcpu) {
switch (kvm_psci_version(vcpu)) {
case KVM_ARM_PSCI_0_2:
return kvm_psci_0_2_call(vcpu);
case KVM_ARM_PSCI_0_1:
return kvm_psci_0_1_call(vcpu);
default:
return false;
};
+} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0a1d697..92242ce 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h>
-#define KVM_VCPU_MAX_FEATURES 2 +#define KVM_VCPU_MAX_FEATURES 3
struct kvm_vcpu; int kvm_target_cpu(void); diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e301a48..e25c658 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM64_KVM_PSCI_H__ #define __ARM64_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index eaf54a3..cadc318 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -77,6 +77,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ +#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -177,7 +178,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -186,10 +187,42 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) #define +KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6) #define
+KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif
-- 1.7.9.5
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
On Friday, February 07, 2014 6:26 PM, Anup Patel wrote:
On Fri, Feb 7, 2014 at 2:37 PM, Jungseok Lee jays.lee@samsung.com wrote:
On Friday, February 07, 2014 5:36 PM, Anup Patel wrote:
On Fri, Feb 7, 2014 at 1:58 PM, Jungseok Lee jays.lee@samsung.com wrote:
On Thursday, February 06, 2014 8:32 PM, Anup Patel wrote:
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to VCPUs. This patch extends current in-kernel PSCI emulation to provide PSCI v0.2 interface to
VCPUs.
By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for keeping the ABI backward- compatible.
To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU init using KVM_ARM_VCPU_INIT ioctl.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/include/asm/kvm_psci.h | 4 ++ arch/arm/include/uapi/asm/kvm.h | 35 ++++++++++++++- arch/arm/kvm/arm.c | 1 + arch/arm/kvm/psci.c | 85 +++++++++++++++++++++++++++++++------ arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_psci.h | 4 ++ arch/arm64/include/uapi/asm/kvm.h | 35 ++++++++++++++- 8 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 09af149..193ceaf 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -36,7 +36,7 @@ #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HAVE_ONE_REG
-#define KVM_VCPU_MAX_FEATURES 1 +#define KVM_VCPU_MAX_FEATURES 2
#include <kvm/arm_vgic.h>
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 9a83d98..4c0e3e1 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM_KVM_PSCI_H__ #define __ARM_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ef0c878..9c922d9 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -83,6 +83,7 @@ struct kvm_regs { #define KVM_VGIC_V2_CPU_SIZE 0x2000
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ +#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -192,7 +193,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -201,9 +202,41 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) #define +KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6) #define
+KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
Hi
This patch describes PSCI v0.2 specification well. Instead, I have a question on interface types, not implementation.
According to PSCI v0.2 document, it does not cover DVFS. Could I get an idea why DVFS is not supported?
PSCI v0.2 only describes few mandatory functions required for being PSCI v0.2 compliant. For rest of the stuff such as DVFS you will need to define your own platform
specific PSCI function.
(Marc/Mark correct me if I am wrong here?)
It seems that I should change architecture codes if I need other interfaces. Under this implementation, I should add my own interface to generic codes, such as, arch/arm/include/asm/kvm_psci.h. However, I think that it is not acceptable to upstream. If so, is there any place to define a platform specific PSCI functions?
Are you trying to emulate your platform specific DVFS PSCI function for a VM using KVM ARM/ARM64??
[Sorry for noise to mailing-list as violating mailing rule]
No, I am not. My original intention is to clarify the interface between KVM and VM if DVFS scheme is applied to VM. Currently, PSCI v0.2 does not define it. Thus, I wonder why this interface is not covered.
If so then arch/arm/kvm/psci.c is not the place for it. All platform specific PSCI function are to be emulated from user space. KVM ARM/ARM64 will only emulate HVC-based mandatory PSCI v0.2 functions.
Okay, clear.
Regards Jungseok Lee
User space emulation of platform specific PSCI functions are still a TODO item for KVM ARM/ARM64. It will require a mechanism in KVM ARM/ARM64 to route SMC-based PSCI function calls to user space (i.e. QEMU or KVMTOOL).
Regards, Anup
Best Regards Jungseok Lee
Mab be in future some PSCI vX.Y will define standardized PSCI function for DVFS too.
Regards, Anup
Best Regards Jungseok Lee
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif /* __ARM_KVM_H__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248e..c8a71df 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: case KVM_CAP_ONE_REG: case KVM_CAP_ARM_PSCI:
case KVM_CAP_ARM_PSCI_0_2: r = 1; break; case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 448f60e..e4ec4af 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,17 +85,57 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; }
-/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure
world where
- the function number is placed in r0 and this function returns
true if the
- function number specified in r0 is withing the PSCI range, and
false
- otherwise.
- */
-bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_version(struct kvm_vcpu *vcpu) {
if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
return KVM_ARM_PSCI_0_2;
return KVM_ARM_PSCI_0_1;
+}
+static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) {
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
switch (psci_fn) {
case KVM_PSCI_0_2_FN_PSCI_VERSION:
/*
* Bits[31:16] = Major Version = 0
* Bits[15:0] = Minor Version = 2
*/
val = 2;
break;
case KVM_PSCI_0_2_FN_CPU_OFF:
kvm_psci_vcpu_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
break;
case KVM_PSCI_0_2_FN_CPU_ON:
case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
case KVM_PSCI_0_2_FN_AFFINITY_INFO:
case KVM_PSCI_0_2_FN_MIGRATE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
case KVM_PSCI_0_2_FN_SYSTEM_OFF:
case KVM_PSCI_0_2_FN_SYSTEM_RESET:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
case KVM_PSCI_0_2_FN64_MIGRATE:
case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
break;
default:
return false;
}
*vcpu_reg(vcpu, 0) = val;
return true;
+}
+static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -112,7 +152,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_PSCI_FN_MIGRATE: val = KVM_PSCI_RET_NI; break;
default: return false; }
@@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) *vcpu_reg(vcpu, 0) = val; return true; }
+/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure
+world where
- the function number is placed in r0 and this function returns
+true if the
- function number specified in r0 is withing the PSCI range, and
+false
- otherwise.
- */
+bool kvm_psci_call(struct kvm_vcpu *vcpu) {
switch (kvm_psci_version(vcpu)) {
case KVM_ARM_PSCI_0_2:
return kvm_psci_0_2_call(vcpu);
case KVM_ARM_PSCI_0_1:
return kvm_psci_0_1_call(vcpu);
default:
return false;
};
+} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0a1d697..92242ce 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h>
-#define KVM_VCPU_MAX_FEATURES 2 +#define KVM_VCPU_MAX_FEATURES 3
struct kvm_vcpu; int kvm_target_cpu(void); diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e301a48..e25c658 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM64_KVM_PSCI_H__ #define __ARM64_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index eaf54a3..cadc318 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -77,6 +77,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ +#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -177,7 +178,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -186,10 +187,42 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) #define +KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6) #define
+KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif
-- 1.7.9.5
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
On Sat, Feb 08, 2014 at 08:42:09AM +0900, Jungseok Lee wrote:
[...]
No, I am not. My original intention is to clarify the interface between KVM and VM if DVFS scheme is applied to VM. Currently, PSCI v0.2 does not define it. Thus, I wonder why this interface is not covered.
Why would you run DVFS in a VM? When the VCPUs in a VM are idle they consume zero resources. The host would be doing the DVFS for thermal regulation and such.
The only thing I can see being relevant is having some mechanism of informing the host of characteristics of the guest so the host can be more educated when enforcing power policy, but that requires a theoretical discussion and rationale first.
-Christoffer
On Thu, Feb 06, 2014 at 05:01:34PM +0530, Anup Patel wrote:
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to VCPUs. This patch extends current in-kernel PSCI emulation to provide PSCI v0.2 interface to VCPUs.
By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for keeping the ABI backward-compatible.
To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU init using KVM_ARM_VCPU_INIT ioctl.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/include/asm/kvm_psci.h | 4 ++ arch/arm/include/uapi/asm/kvm.h | 35 ++++++++++++++- arch/arm/kvm/arm.c | 1 + arch/arm/kvm/psci.c | 85 +++++++++++++++++++++++++++++++------ arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_psci.h | 4 ++ arch/arm64/include/uapi/asm/kvm.h | 35 ++++++++++++++- 8 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 09af149..193ceaf 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -36,7 +36,7 @@ #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HAVE_ONE_REG -#define KVM_VCPU_MAX_FEATURES 1 +#define KVM_VCPU_MAX_FEATURES 2 #include <kvm/arm_vgic.h> diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 9a83d98..4c0e3e1 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM_KVM_PSCI_H__ #define __ARM_KVM_PSCI_H__ +#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu); #endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ef0c878..9c922d9 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -83,6 +83,7 @@ struct kvm_regs { #define KVM_VGIC_V2_CPU_SIZE 0x2000 #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ +#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */ struct kvm_vcpu_init { __u32 target; @@ -192,7 +193,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127 -/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n)) @@ -201,9 +202,41 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3) +/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8) #endif /* __ARM_KVM_H__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248e..c8a71df 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: case KVM_CAP_ONE_REG: case KVM_CAP_ARM_PSCI:
- case KVM_CAP_ARM_PSCI_0_2: r = 1; break;
I don't think we should advertise this to userspace before being spec compliant. For example, it would break bisecting with a newer user space.
Just do all the internal implementation and add this as the last patch when everything else is in place.
case KVM_CAP_COALESCED_MMIO: diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 448f60e..e4ec4af 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,17 +85,57 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; } -/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure world where
- the function number is placed in r0 and this function returns true if the
- function number specified in r0 is withing the PSCI range, and false
- otherwise.
- */
-bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_version(struct kvm_vcpu *vcpu) +{
- if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
return KVM_ARM_PSCI_0_2;
- return KVM_ARM_PSCI_0_1;
+}
+static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) +{
- unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
- unsigned long val;
- switch (psci_fn) {
- case KVM_PSCI_0_2_FN_PSCI_VERSION:
/*
* Bits[31:16] = Major Version = 0
* Bits[15:0] = Minor Version = 2
*/
val = 2;
break;
- case KVM_PSCI_0_2_FN_CPU_OFF:
kvm_psci_vcpu_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
break;
- case KVM_PSCI_0_2_FN_CPU_ON:
- case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break;
- case KVM_PSCI_0_2_FN_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN_AFFINITY_INFO:
- case KVM_PSCI_0_2_FN_MIGRATE:
- case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
- case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
- case KVM_PSCI_0_2_FN_SYSTEM_OFF:
- case KVM_PSCI_0_2_FN_SYSTEM_RESET:
- case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
- case KVM_PSCI_0_2_FN64_MIGRATE:
- case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
break;
- default:
return false;
- }
- *vcpu_reg(vcpu, 0) = val;
- return true;
+}
+static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -112,7 +152,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_PSCI_FN_MIGRATE: val = KVM_PSCI_RET_NI; break;
- default: return false; }
@@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) *vcpu_reg(vcpu, 0) = val; return true; }
+/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure world where
- the function number is placed in r0 and this function returns true if the
- function number specified in r0 is withing the PSCI range, and false
- otherwise.
- */
+bool kvm_psci_call(struct kvm_vcpu *vcpu) +{
- switch (kvm_psci_version(vcpu)) {
- case KVM_ARM_PSCI_0_2:
return kvm_psci_0_2_call(vcpu);
- case KVM_ARM_PSCI_0_1:
return kvm_psci_0_1_call(vcpu);
- default:
return false;
- };
+} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0a1d697..92242ce 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h> -#define KVM_VCPU_MAX_FEATURES 2 +#define KVM_VCPU_MAX_FEATURES 3 struct kvm_vcpu; int kvm_target_cpu(void); diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e301a48..e25c658 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM64_KVM_PSCI_H__ #define __ARM64_KVM_PSCI_H__ +#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu); #endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index eaf54a3..cadc318 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -77,6 +77,7 @@ struct kvm_regs { #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ +#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */ struct kvm_vcpu_init { __u32 target; @@ -177,7 +178,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127 -/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n)) @@ -186,10 +187,42 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3) +/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8) #endif -- 1.7.9.5
Otherwise, Reviewed-by: Christoffer Dall christoffer.dall@linaro.org
On Mon, Mar 17, 2014 at 9:10 AM, Christoffer Dall christoffer.dall@linaro.org wrote:
On Thu, Feb 06, 2014 at 05:01:34PM +0530, Anup Patel wrote:
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to VCPUs. This patch extends current in-kernel PSCI emulation to provide PSCI v0.2 interface to VCPUs.
By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for keeping the ABI backward-compatible.
To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU init using KVM_ARM_VCPU_INIT ioctl.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/include/asm/kvm_psci.h | 4 ++ arch/arm/include/uapi/asm/kvm.h | 35 ++++++++++++++- arch/arm/kvm/arm.c | 1 + arch/arm/kvm/psci.c | 85 +++++++++++++++++++++++++++++++------ arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_psci.h | 4 ++ arch/arm64/include/uapi/asm/kvm.h | 35 ++++++++++++++- 8 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 09af149..193ceaf 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -36,7 +36,7 @@ #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 #define KVM_HAVE_ONE_REG
-#define KVM_VCPU_MAX_FEATURES 1 +#define KVM_VCPU_MAX_FEATURES 2
#include <kvm/arm_vgic.h>
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 9a83d98..4c0e3e1 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM_KVM_PSCI_H__ #define __ARM_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ef0c878..9c922d9 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -83,6 +83,7 @@ struct kvm_regs { #define KVM_VGIC_V2_CPU_SIZE 0x2000
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ +#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -192,7 +193,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -201,9 +202,41 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif /* __ARM_KVM_H__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248e..c8a71df 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: case KVM_CAP_ONE_REG: case KVM_CAP_ARM_PSCI:
case KVM_CAP_ARM_PSCI_0_2: r = 1; break;
I don't think we should advertise this to userspace before being spec compliant. For example, it would break bisecting with a newer user space.
Just do all the internal implementation and add this as the last patch when everything else is in place.
OK, I will add a separate last patch in this series for enabling PSCI v0.2 capability in kvm_dev_ioctl_check_extension().
-- Anup
case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 448f60e..e4ec4af 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,17 +85,57 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; }
-/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure world where
- the function number is placed in r0 and this function returns true if the
- function number specified in r0 is withing the PSCI range, and false
- otherwise.
- */
-bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_version(struct kvm_vcpu *vcpu) +{
if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
return KVM_ARM_PSCI_0_2;
return KVM_ARM_PSCI_0_1;
+}
+static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) +{
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
switch (psci_fn) {
case KVM_PSCI_0_2_FN_PSCI_VERSION:
/*
* Bits[31:16] = Major Version = 0
* Bits[15:0] = Minor Version = 2
*/
val = 2;
break;
case KVM_PSCI_0_2_FN_CPU_OFF:
kvm_psci_vcpu_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
break;
case KVM_PSCI_0_2_FN_CPU_ON:
case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
case KVM_PSCI_0_2_FN_AFFINITY_INFO:
case KVM_PSCI_0_2_FN_MIGRATE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
case KVM_PSCI_0_2_FN_SYSTEM_OFF:
case KVM_PSCI_0_2_FN_SYSTEM_RESET:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
case KVM_PSCI_0_2_FN64_MIGRATE:
case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
break;
default:
return false;
}
*vcpu_reg(vcpu, 0) = val;
return true;
+}
+static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -112,7 +152,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_PSCI_FN_MIGRATE: val = KVM_PSCI_RET_NI; break;
default: return false; }
@@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) *vcpu_reg(vcpu, 0) = val; return true; }
+/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure world where
- the function number is placed in r0 and this function returns true if the
- function number specified in r0 is withing the PSCI range, and false
- otherwise.
- */
+bool kvm_psci_call(struct kvm_vcpu *vcpu) +{
switch (kvm_psci_version(vcpu)) {
case KVM_ARM_PSCI_0_2:
return kvm_psci_0_2_call(vcpu);
case KVM_ARM_PSCI_0_1:
return kvm_psci_0_1_call(vcpu);
default:
return false;
};
+} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0a1d697..92242ce 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h>
-#define KVM_VCPU_MAX_FEATURES 2 +#define KVM_VCPU_MAX_FEATURES 3
struct kvm_vcpu; int kvm_target_cpu(void); diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e301a48..e25c658 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -18,6 +18,10 @@ #ifndef __ARM64_KVM_PSCI_H__ #define __ARM64_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1 +#define KVM_ARM_PSCI_0_2 2
+int kvm_psci_version(struct kvm_vcpu *vcpu); bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index eaf54a3..cadc318 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -77,6 +77,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ +#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -177,7 +178,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -186,10 +187,42 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif
-- 1.7.9.5
Otherwise, Reviewed-by: Christoffer Dall christoffer.dall@linaro.org _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
On Thu, Feb 6, 2014 at 5:31 AM, Anup Patel anup.patel@linaro.org wrote:
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to VCPUs. This patch extends current in-kernel PSCI emulation to provide PSCI v0.2 interface to VCPUs.
[snip]
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ef0c878..9c922d9 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -83,6 +83,7 @@ struct kvm_regs { #define KVM_VGIC_V2_CPU_SIZE 0x2000
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ +#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init { __u32 target; @@ -192,7 +193,7 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */ +/* PSCI v0.1 interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
While this is really KVM specific since the base can be anything...
@@ -201,9 +202,41 @@ struct kvm_arch_memory_slot { #define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) #define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */ +#define KVM_PSCI_0_2_FN_BASE 0x84000000 +#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n)) +#define KVM_PSCI_0_2_FN64_BASE 0xC4000000 +#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0) +#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1) +#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2) +#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3) +#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4) +#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5) +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8) +#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1) +#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3) +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4) +#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5) +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
KVM_PSCI_0_2_FN64(7)
+/* PSCI return values */ #define KVM_PSCI_RET_SUCCESS 0 #define KVM_PSCI_RET_NI ((unsigned long)-1) #define KVM_PSCI_RET_INVAL ((unsigned long)-2) #define KVM_PSCI_RET_DENIED ((unsigned long)-3) +#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4) +#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5) +#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6) +#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7) +#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
These definitions are common across arm and arm64, baremetal and kvm in the kernel, and the kernel and qemu. Soon they will also be needed in qemu for system emulation support of PSCI. We need these in a common header to share.
Rob
We have in-kernel emulation of PSCI v0.2 in KVM ARM/ARM64. To provide PSCI v0.2 interface to VCPUs, we have to enable KVM_ARM_VCPU_PSCI_0_2 feature when doing KVM_ARM_VCPU_INIT ioctl.
The patch updates documentation of KVM_ARM_VCPU_INIT ioctl to provide info regarding KVM_ARM_VCPU_PSCI_0_2 feature.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org --- Documentation/virtual/kvm/api.txt | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 6cd63a9..73cb211 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -2347,6 +2347,8 @@ Possible features: Depends on KVM_CAP_ARM_PSCI. - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode. Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only). + - KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 for the CPU. + Depends on KVM_CAP_ARM_PSCI_0_2.
4.83 KVM_ARM_PREFERRED_TARGET
On Thu, Feb 06, 2014 at 05:01:35PM +0530, Anup Patel wrote:
We have in-kernel emulation of PSCI v0.2 in KVM ARM/ARM64. To provide PSCI v0.2 interface to VCPUs, we have to enable KVM_ARM_VCPU_PSCI_0_2 feature when doing KVM_ARM_VCPU_INIT ioctl.
The patch updates documentation of KVM_ARM_VCPU_INIT ioctl to provide info regarding KVM_ARM_VCPU_PSCI_0_2 feature.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
Documentation/virtual/kvm/api.txt | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 6cd63a9..73cb211 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -2347,6 +2347,8 @@ Possible features: Depends on KVM_CAP_ARM_PSCI.
- KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode. Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 for the CPU.
Depends on KVM_CAP_ARM_PSCI_0_2.
4.83 KVM_ARM_PREFERRED_TARGET -- 1.7.9.5
Acked-by: Christoffer Dall christoffer.dall@linaro.org
Currently, the kvm_psci_call() returns 'true' or 'false' based on whether the PSCI function call was handled successfully or not. This does not help us emulate system-level PSCI functions where the actual emulation work will be done by user space (QEMU or KVMTOOL). Examples of such system-level PSCI functions are: PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET.
This patch updates kvm_psci_call() to return three types of values: 1) > 0 (success) 2) = 0 (success but exit to user space) 3) < 0 (errors)
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org --- arch/arm/include/asm/kvm_psci.h | 2 +- arch/arm/kvm/handle_exit.c | 10 +++++++--- arch/arm/kvm/psci.c | 28 ++++++++++++++++------------ arch/arm64/include/asm/kvm_psci.h | 2 +- arch/arm64/kvm/handle_exit.c | 10 +++++++--- 5 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 4c0e3e1..6bda945 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -22,6 +22,6 @@ #define KVM_ARM_PSCI_0_2 2
int kvm_psci_version(struct kvm_vcpu *vcpu); -bool kvm_psci_call(struct kvm_vcpu *vcpu); +int kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c index 0de91fc..1270095 100644 --- a/arch/arm/kvm/handle_exit.c +++ b/arch/arm/kvm/handle_exit.c @@ -38,14 +38,18 @@ static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) { + int ret; + trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0), kvm_vcpu_hvc_get_imm(vcpu));
- if (kvm_psci_call(vcpu)) + ret = kvm_psci_call(vcpu); + if (ret == -EINVAL) { + kvm_inject_undefined(vcpu); return 1; + }
- kvm_inject_undefined(vcpu); - return 1; + return ret; }
static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index e4ec4af..252acd0 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -93,7 +93,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu) return KVM_ARM_PSCI_0_1; }
-static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) +static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -128,14 +128,14 @@ static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) val = KVM_PSCI_RET_NI; break; default: - return false; + return -EINVAL; }
*vcpu_reg(vcpu, 0) = val; - return true; + return 1; }
-static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) +static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -153,11 +153,11 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) val = KVM_PSCI_RET_NI; break; default: - return false; + return -EINVAL; }
*vcpu_reg(vcpu, 0) = val; - return true; + return 1; }
/** @@ -165,12 +165,16 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) * @vcpu: Pointer to the VCPU struct * * Handle PSCI calls from guests through traps from HVC instructions. - * The calling convention is similar to SMC calls to the secure world where - * the function number is placed in r0 and this function returns true if the - * function number specified in r0 is withing the PSCI range, and false - * otherwise. + * The calling convention is similar to SMC calls to the secure world + * where the function number is placed in r0. + * + * This function returns: > 0 (success), 0 (success but exit to user + * space), and < 0 (errors) + * + * Errors: + * -EINVAL: Unrecognized PSCI function */ -bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_call(struct kvm_vcpu *vcpu) { switch (kvm_psci_version(vcpu)) { case KVM_ARM_PSCI_0_2: @@ -178,6 +182,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_ARM_PSCI_0_1: return kvm_psci_0_1_call(vcpu); default: - return false; + return -EINVAL; }; } diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e25c658..bc39e55 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -22,6 +22,6 @@ #define KVM_ARM_PSCI_0_2 2
int kvm_psci_version(struct kvm_vcpu *vcpu); -bool kvm_psci_call(struct kvm_vcpu *vcpu); +int kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 7bc41ea..743a74d 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -30,11 +30,15 @@ typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) { - if (kvm_psci_call(vcpu)) + int ret; + + ret = kvm_psci_call(vcpu); + if (ret == -EINVAL) { + kvm_inject_undefined(vcpu); return 1; + }
- kvm_inject_undefined(vcpu); - return 1; + return ret; }
static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
On Thu, Feb 06, 2014 at 05:01:36PM +0530, Anup Patel wrote:
Currently, the kvm_psci_call() returns 'true' or 'false' based on whether the PSCI function call was handled successfully or not. This does not help us emulate system-level PSCI functions where the actual emulation work will be done by user space (QEMU or KVMTOOL). Examples of such system-level PSCI functions are: PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET.
This patch updates kvm_psci_call() to return three types of values:
0 (success)- = 0 (success but exit to user space)
- < 0 (errors)
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_psci.h | 2 +- arch/arm/kvm/handle_exit.c | 10 +++++++--- arch/arm/kvm/psci.c | 28 ++++++++++++++++------------ arch/arm64/include/asm/kvm_psci.h | 2 +- arch/arm64/kvm/handle_exit.c | 10 +++++++--- 5 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 4c0e3e1..6bda945 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -22,6 +22,6 @@ #define KVM_ARM_PSCI_0_2 2 int kvm_psci_version(struct kvm_vcpu *vcpu); -bool kvm_psci_call(struct kvm_vcpu *vcpu); +int kvm_psci_call(struct kvm_vcpu *vcpu); #endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c index 0de91fc..1270095 100644 --- a/arch/arm/kvm/handle_exit.c +++ b/arch/arm/kvm/handle_exit.c @@ -38,14 +38,18 @@ static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run) static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) {
- int ret;
- trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0), kvm_vcpu_hvc_get_imm(vcpu));
- if (kvm_psci_call(vcpu))
- ret = kvm_psci_call(vcpu);
- if (ret == -EINVAL) {
return 1;kvm_inject_undefined(vcpu);
- }
- kvm_inject_undefined(vcpu);
- return 1;
- return ret;
} static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index e4ec4af..252acd0 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -93,7 +93,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu) return KVM_ARM_PSCI_0_1; } -static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) +static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -128,14 +128,14 @@ static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) val = KVM_PSCI_RET_NI; break; default:
return false;
}return -EINVAL;
*vcpu_reg(vcpu, 0) = val;
- return true;
- return 1;
} -static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) +static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val; @@ -153,11 +153,11 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) val = KVM_PSCI_RET_NI; break; default:
return false;
}return -EINVAL;
*vcpu_reg(vcpu, 0) = val;
- return true;
- return 1;
} /** @@ -165,12 +165,16 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
- @vcpu: Pointer to the VCPU struct
- Handle PSCI calls from guests through traps from HVC instructions.
- The calling convention is similar to SMC calls to the secure world where
- the function number is placed in r0 and this function returns true if the
- function number specified in r0 is withing the PSCI range, and false
- otherwise.
- The calling convention is similar to SMC calls to the secure world
- where the function number is placed in r0.
- This function returns: > 0 (success), 0 (success but exit to user
- space), and < 0 (errors)
- Errors:
*/
- -EINVAL: Unrecognized PSCI function
-bool kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_call(struct kvm_vcpu *vcpu) { switch (kvm_psci_version(vcpu)) { case KVM_ARM_PSCI_0_2: @@ -178,6 +182,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu) case KVM_ARM_PSCI_0_1: return kvm_psci_0_1_call(vcpu); default:
return false;
};return -EINVAL;
} diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index e25c658..bc39e55 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -22,6 +22,6 @@ #define KVM_ARM_PSCI_0_2 2 int kvm_psci_version(struct kvm_vcpu *vcpu); -bool kvm_psci_call(struct kvm_vcpu *vcpu); +int kvm_psci_call(struct kvm_vcpu *vcpu); #endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 7bc41ea..743a74d 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -30,11 +30,15 @@ typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *); static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) {
- if (kvm_psci_call(vcpu))
- int ret;
- ret = kvm_psci_call(vcpu);
- if (ret == -EINVAL) {
return 1;kvm_inject_undefined(vcpu);
- }
- kvm_inject_undefined(vcpu);
- return 1;
- return ret;
} static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) -- 1.7.9.5
Reviewed-by: Christoffer Dall christoffer.dall@linaro.org
Currently, we don't have an exit reason to notify user space about a system-level event (for e.g. system reset or shutdown) triggered by the VCPU. This patch adds exit reason KVM_EXIT_SYSTEM_EVENT for this purpose. We can also inform user space about the 'type' and architecture specific 'flags' of a system-level event using the kvm_run structure.
This newly added KVM_EXIT_SYSTEM_EVENT will be used by KVM ARM/ARM64 in-kernel PSCI v0.2 support to reset/shutdown VMs.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org --- Documentation/virtual/kvm/api.txt | 15 +++++++++++++++ include/uapi/linux/kvm.h | 8 ++++++++ 2 files changed, 23 insertions(+)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 73cb211..0f70625 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -2707,6 +2707,21 @@ It gets triggered whenever both KVM_CAP_PPC_EPR are enabled and an external interrupt has just been delivered into the guest. User space should put the acknowledged interrupt vector into the 'epr' field.
+ /* KVM_EXIT_SYSTEM_EVENT */ + struct { +#define KVM_SYSTEM_EVENT_SHUTDOWN 1 +#define KVM_SYSTEM_EVENT_RESET 2 + __u32 type; + __u64 flags; + } system_event; + +If exit_reason is KVM_EXIT_SYSTEM_EVENT then the vcpu has triggered +a system-level event using some architecture specific mechanism (hypercall +or some special instruction). In case of ARM/ARM64, this is triggered using +HVC instruction based PSCI call from the vcpu. The 'type' field describes +the system-level event type. The 'flags' field describes architecture +specific flags for the system-level event. + /* Fix the size of the union. */ char padding[256]; }; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index fb3c3f3..0723853 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -171,6 +171,7 @@ struct kvm_pit_config { #define KVM_EXIT_WATCHDOG 21 #define KVM_EXIT_S390_TSCH 22 #define KVM_EXIT_EPR 23 +#define KVM_EXIT_SYSTEM_EVENT 24
/* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -301,6 +302,13 @@ struct kvm_run { struct { __u32 epr; } epr; + /* KVM_EXIT_SYSTEM_EVENT */ + struct { +#define KVM_SYSTEM_EVENT_SHUTDOWN 1 +#define KVM_SYSTEM_EVENT_RESET 2 + __u32 type; + __u64 flags; + } system_event; /* Fix the size of the union. */ char padding[256]; };
On Thu, Feb 06, 2014 at 05:01:37PM +0530, Anup Patel wrote:
Currently, we don't have an exit reason to notify user space about a system-level event (for e.g. system reset or shutdown) triggered by the VCPU. This patch adds exit reason KVM_EXIT_SYSTEM_EVENT for this purpose. We can also inform user space about the 'type' and architecture specific 'flags' of a system-level event using the kvm_run structure.
This newly added KVM_EXIT_SYSTEM_EVENT will be used by KVM ARM/ARM64 in-kernel PSCI v0.2 support to reset/shutdown VMs.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
Documentation/virtual/kvm/api.txt | 15 +++++++++++++++ include/uapi/linux/kvm.h | 8 ++++++++ 2 files changed, 23 insertions(+)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 73cb211..0f70625 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -2707,6 +2707,21 @@ It gets triggered whenever both KVM_CAP_PPC_EPR are enabled and an external interrupt has just been delivered into the guest. User space should put the acknowledged interrupt vector into the 'epr' field.
/* KVM_EXIT_SYSTEM_EVENT */
struct {
+#define KVM_SYSTEM_EVENT_SHUTDOWN 1 +#define KVM_SYSTEM_EVENT_RESET 2
__u32 type;
__u64 flags;
} system_event;
+If exit_reason is KVM_EXIT_SYSTEM_EVENT then the vcpu has triggered +a system-level event using some architecture specific mechanism (hypercall +or some special instruction). In case of ARM/ARM64, this is triggered using +HVC instruction based PSCI call from the vcpu. The 'type' field describes +the system-level event type. The 'flags' field describes architecture +specific flags for the system-level event.
- /* Fix the size of the union. */ char padding[256]; };
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index fb3c3f3..0723853 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -171,6 +171,7 @@ struct kvm_pit_config { #define KVM_EXIT_WATCHDOG 21 #define KVM_EXIT_S390_TSCH 22 #define KVM_EXIT_EPR 23 +#define KVM_EXIT_SYSTEM_EVENT 24 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -301,6 +302,13 @@ struct kvm_run { struct { __u32 epr; } epr;
/* KVM_EXIT_SYSTEM_EVENT */
struct {
+#define KVM_SYSTEM_EVENT_SHUTDOWN 1 +#define KVM_SYSTEM_EVENT_RESET 2
__u32 type;
__u64 flags;
/* Fix the size of the union. */ char padding[256]; };} system_event;
-- 1.7.9.5
Reviewed-by: Christoffer Dall christoffer.dall@linaro.org
The PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET functions are system-level functions hence cannot be fully emulated by in-kernel PSCI emulation code.
To tackle this, we forward PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET function calls from vcpu to user space (i.e. QEMU or KVMTOOL) via kvm_run structure using KVM_EXIT_SYSTEM_EVENT exit reasons.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org --- arch/arm/kvm/psci.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 252acd0..1f1720a 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,6 +85,23 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; }
+static inline void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type) +{ + memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event)); + vcpu->run->system_event.type = type; + vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT; +} + +static void kvm_psci_system_off(struct kvm_vcpu *vcpu) +{ + kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN); +} + +static void kvm_psci_system_reset(struct kvm_vcpu *vcpu) +{ + kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET); +} + int kvm_psci_version(struct kvm_vcpu *vcpu) { if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) @@ -95,6 +112,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) { + int ret = 1; unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val;
@@ -114,13 +132,21 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) case KVM_PSCI_0_2_FN64_CPU_ON: val = kvm_psci_vcpu_on(vcpu); break; + case KVM_PSCI_0_2_FN_SYSTEM_OFF: + kvm_psci_system_off(vcpu); + val = KVM_PSCI_RET_SUCCESS; + ret = 0; + break; + case KVM_PSCI_0_2_FN_SYSTEM_RESET: + kvm_psci_system_reset(vcpu); + val = KVM_PSCI_RET_SUCCESS; + ret = 0; + break; case KVM_PSCI_0_2_FN_CPU_SUSPEND: case KVM_PSCI_0_2_FN_AFFINITY_INFO: case KVM_PSCI_0_2_FN_MIGRATE: case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE: case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: - case KVM_PSCI_0_2_FN_SYSTEM_OFF: - case KVM_PSCI_0_2_FN_SYSTEM_RESET: case KVM_PSCI_0_2_FN64_CPU_SUSPEND: case KVM_PSCI_0_2_FN64_AFFINITY_INFO: case KVM_PSCI_0_2_FN64_MIGRATE: @@ -132,7 +158,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) }
*vcpu_reg(vcpu, 0) = val; - return 1; + return ret; }
static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
On Thu, Feb 06, 2014 at 05:01:38PM +0530, Anup Patel wrote:
The PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET functions are system-level functions hence cannot be fully emulated by in-kernel PSCI emulation code.
To tackle this, we forward PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET function calls from vcpu to user space (i.e. QEMU or KVMTOOL) via kvm_run structure using KVM_EXIT_SYSTEM_EVENT exit reasons.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/kvm/psci.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 252acd0..1f1720a 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,6 +85,23 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; } +static inline void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type) +{
- memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
- vcpu->run->system_event.type = type;
- vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+}
+static void kvm_psci_system_off(struct kvm_vcpu *vcpu) +{
- kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN);
+}
+static void kvm_psci_system_reset(struct kvm_vcpu *vcpu) +{
- kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET);
+}
int kvm_psci_version(struct kvm_vcpu *vcpu) { if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) @@ -95,6 +112,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu) static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) {
- int ret = 1; unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); unsigned long val;
@@ -114,13 +132,21 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) case KVM_PSCI_0_2_FN64_CPU_ON: val = kvm_psci_vcpu_on(vcpu); break;
- case KVM_PSCI_0_2_FN_SYSTEM_OFF:
kvm_psci_system_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
ret = 0;
break;
- case KVM_PSCI_0_2_FN_SYSTEM_RESET:
kvm_psci_system_reset(vcpu);
val = KVM_PSCI_RET_SUCCESS;
ret = 0;
case KVM_PSCI_0_2_FN_CPU_SUSPEND: case KVM_PSCI_0_2_FN_AFFINITY_INFO: case KVM_PSCI_0_2_FN_MIGRATE: case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE: case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:break;
- case KVM_PSCI_0_2_FN_SYSTEM_OFF:
- case KVM_PSCI_0_2_FN_SYSTEM_RESET: case KVM_PSCI_0_2_FN64_CPU_SUSPEND: case KVM_PSCI_0_2_FN64_AFFINITY_INFO: case KVM_PSCI_0_2_FN64_MIGRATE:
@@ -132,7 +158,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) } *vcpu_reg(vcpu, 0) = val;
- return 1;
- return ret;
} static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) -- 1.7.9.5
Reviewed-by: Christoffer Dall christoffer.dall@linaro.org
This patch adds emulation of PSCI v0.2 AFFINITY_INFO function call for KVM ARM/ARM64. This is a VCPU-level function call which will be used to determine current state of given affinity level.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org --- arch/arm/kvm/psci.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 1f1720a..9890710 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,6 +85,55 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; }
+static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) +{ + int i; + unsigned long mpidr; + unsigned long target_affinity; + unsigned long target_affinity_mask; + unsigned long lowest_affinity_level; + struct kvm *kvm = vcpu->kvm; + struct kvm_vcpu *tmp; + + target_affinity = *vcpu_reg(vcpu, 1); + lowest_affinity_level = *vcpu_reg(vcpu, 2); + + /* Determine target affinity mask */ + target_affinity_mask = MPIDR_HWID_BITMASK; + switch (lowest_affinity_level) { + case 0: /* All affinity levels are valid */ + target_affinity_mask &= ~0x0UL; + break; + case 1: /* Aff0 ignored */ + target_affinity_mask &= ~0xFFUL; + break; + case 2: /* Aff0 and Aff1 ignored */ + target_affinity_mask &= ~0xFFFFUL; + break; + case 3: /* Aff0, Aff1, and Aff2 ignored */ + target_affinity_mask &= ~0xFFFFFFUL; + break; + default: + return KVM_PSCI_RET_INVAL; + }; + + /* Ignore other bits of target affinity */ + target_affinity &= target_affinity_mask; + + /* If one or more VCPU matching target affinity are running + * then return 0 (ON) else return 1 (OFF) + */ + kvm_for_each_vcpu(i, tmp, kvm) { + mpidr = kvm_vcpu_get_mpidr(tmp); + if (((mpidr & target_affinity_mask) == target_affinity) && + !tmp->arch.pause) { + return 0; + } + } + + return 1; +} + static inline void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type) { memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event)); @@ -132,6 +181,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) case KVM_PSCI_0_2_FN64_CPU_ON: val = kvm_psci_vcpu_on(vcpu); break; + case KVM_PSCI_0_2_FN_AFFINITY_INFO: + case KVM_PSCI_0_2_FN64_AFFINITY_INFO: + val = kvm_psci_vcpu_affinity_info(vcpu); + break; case KVM_PSCI_0_2_FN_SYSTEM_OFF: kvm_psci_system_off(vcpu); val = KVM_PSCI_RET_SUCCESS; @@ -143,12 +196,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) ret = 0; break; case KVM_PSCI_0_2_FN_CPU_SUSPEND: - case KVM_PSCI_0_2_FN_AFFINITY_INFO: case KVM_PSCI_0_2_FN_MIGRATE: case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE: case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: case KVM_PSCI_0_2_FN64_CPU_SUSPEND: - case KVM_PSCI_0_2_FN64_AFFINITY_INFO: case KVM_PSCI_0_2_FN64_MIGRATE: case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: val = KVM_PSCI_RET_NI;
On Thu, Feb 06, 2014 at 05:01:39PM +0530, Anup Patel wrote:
This patch adds emulation of PSCI v0.2 AFFINITY_INFO function call for KVM ARM/ARM64. This is a VCPU-level function call which will be used to determine current state of given affinity level.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/kvm/psci.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 1f1720a..9890710 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -85,6 +85,55 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_SUCCESS; } +static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) +{
- int i;
- unsigned long mpidr;
- unsigned long target_affinity;
- unsigned long target_affinity_mask;
- unsigned long lowest_affinity_level;
- struct kvm *kvm = vcpu->kvm;
- struct kvm_vcpu *tmp;
- target_affinity = *vcpu_reg(vcpu, 1);
- lowest_affinity_level = *vcpu_reg(vcpu, 2);
- /* Determine target affinity mask */
- target_affinity_mask = MPIDR_HWID_BITMASK;
- switch (lowest_affinity_level) {
- case 0: /* All affinity levels are valid */
target_affinity_mask &= ~0x0UL;
break;
- case 1: /* Aff0 ignored */
target_affinity_mask &= ~0xFFUL;
break;
- case 2: /* Aff0 and Aff1 ignored */
target_affinity_mask &= ~0xFFFFUL;
break;
- case 3: /* Aff0, Aff1, and Aff2 ignored */
target_affinity_mask &= ~0xFFFFFFUL;
break;
- default:
return KVM_PSCI_RET_INVAL;
- };
- /* Ignore other bits of target affinity */
- target_affinity &= target_affinity_mask;
- /* If one or more VCPU matching target affinity are running
* then return 0 (ON) else return 1 (OFF)
*/
nit: this is not kernel commenting style, checkpatch should complain.
- kvm_for_each_vcpu(i, tmp, kvm) {
mpidr = kvm_vcpu_get_mpidr(tmp);
if (((mpidr & target_affinity_mask) == target_affinity) &&
!tmp->arch.pause) {
return 0;
}
- }
- return 1;
+}
static inline void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type) { memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event)); @@ -132,6 +181,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) case KVM_PSCI_0_2_FN64_CPU_ON: val = kvm_psci_vcpu_on(vcpu); break;
- case KVM_PSCI_0_2_FN_AFFINITY_INFO:
- case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
val = kvm_psci_vcpu_affinity_info(vcpu);
case KVM_PSCI_0_2_FN_SYSTEM_OFF: kvm_psci_system_off(vcpu); val = KVM_PSCI_RET_SUCCESS;break;
@@ -143,12 +196,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) ret = 0; break; case KVM_PSCI_0_2_FN_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN_AFFINITY_INFO: case KVM_PSCI_0_2_FN_MIGRATE: case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE: case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN64_AFFINITY_INFO: case KVM_PSCI_0_2_FN64_MIGRATE: case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: val = KVM_PSCI_RET_NI;
-- 1.7.9.5
Besides the nit: Reviewed-by: Christoffer Dall christoffer.dall@linaro.org
This patch adds emulation of PSCI v0.2 MIGRATE, MIGRATE_INFO_TYPE, and MIGRATE_INFO_UP_CPU function calls for KVM ARM/ARM64.
KVM ARM/ARM64 being a hypervisor (and not a Trusted OS), we cannot provide this functions hence we emulate these functions in following way: 1. MIGRATE - Returns "Not Supported" 2. MIGRATE_INFO_TYPE - Return 2 i.e. Trusted OS is either not present or does not require migration 3. MIGRATE_INFO_UP_CPU - Returns "Not Supported"
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org --- arch/arm/kvm/psci.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 9890710..75447a3 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -120,7 +120,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) /* Ignore other bits of target affinity */ target_affinity &= target_affinity_mask;
- /* If one or more VCPU matching target affinity are running + /* + * If one or more VCPU matching target affinity are running * then return 0 (ON) else return 1 (OFF) */ kvm_for_each_vcpu(i, tmp, kvm) { @@ -185,6 +186,21 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) case KVM_PSCI_0_2_FN64_AFFINITY_INFO: val = kvm_psci_vcpu_affinity_info(vcpu); break; + case KVM_PSCI_0_2_FN_MIGRATE: + case KVM_PSCI_0_2_FN64_MIGRATE: + val = KVM_PSCI_RET_NI; + break; + case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE: + /* + * Trusted OS is either not present or + * does not require migration + */ + val = 2; + break; + case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: + case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: + val = KVM_PSCI_RET_NI; + break; case KVM_PSCI_0_2_FN_SYSTEM_OFF: kvm_psci_system_off(vcpu); val = KVM_PSCI_RET_SUCCESS; @@ -196,12 +212,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) ret = 0; break; case KVM_PSCI_0_2_FN_CPU_SUSPEND: - case KVM_PSCI_0_2_FN_MIGRATE: - case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE: - case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: case KVM_PSCI_0_2_FN64_CPU_SUSPEND: - case KVM_PSCI_0_2_FN64_MIGRATE: - case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: val = KVM_PSCI_RET_NI; break; default:
On Thu, Feb 06, 2014 at 05:01:40PM +0530, Anup Patel wrote:
This patch adds emulation of PSCI v0.2 MIGRATE, MIGRATE_INFO_TYPE, and MIGRATE_INFO_UP_CPU function calls for KVM ARM/ARM64.
KVM ARM/ARM64 being a hypervisor (and not a Trusted OS), we cannot provide this functions hence we emulate these functions in following way:
- MIGRATE - Returns "Not Supported"
- MIGRATE_INFO_TYPE - Return 2 i.e. Trusted OS is either not present or does not require migration
- MIGRATE_INFO_UP_CPU - Returns "Not Supported"
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/kvm/psci.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 9890710..75447a3 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -120,7 +120,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) /* Ignore other bits of target affinity */ target_affinity &= target_affinity_mask;
- /* If one or more VCPU matching target affinity are running
- /*
* If one or more VCPU matching target affinity are running
ah, you fixed it here, please move change to previous patch, thanks.
* then return 0 (ON) else return 1 (OFF) */
kvm_for_each_vcpu(i, tmp, kvm) { @@ -185,6 +186,21 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) case KVM_PSCI_0_2_FN64_AFFINITY_INFO: val = kvm_psci_vcpu_affinity_info(vcpu); break;
- case KVM_PSCI_0_2_FN_MIGRATE:
- case KVM_PSCI_0_2_FN64_MIGRATE:
val = KVM_PSCI_RET_NI;
break;
- case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
/*
* Trusted OS is either not present or
* does not require migration
*/
val = 2;
break;
- case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
- case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
case KVM_PSCI_0_2_FN_SYSTEM_OFF: kvm_psci_system_off(vcpu); val = KVM_PSCI_RET_SUCCESS;break;
@@ -196,12 +212,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) ret = 0; break; case KVM_PSCI_0_2_FN_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN_MIGRATE:
- case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
- case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN64_MIGRATE:
- case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: val = KVM_PSCI_RET_NI; break; default:
-- 1.7.9.5
Otherwise: Reviewed-by: Christoffer Dall christoffer.dall@linaro.org
On Mon, Mar 17, 2014 at 9:11 AM, Christoffer Dall christoffer.dall@linaro.org wrote:
On Thu, Feb 06, 2014 at 05:01:40PM +0530, Anup Patel wrote:
This patch adds emulation of PSCI v0.2 MIGRATE, MIGRATE_INFO_TYPE, and MIGRATE_INFO_UP_CPU function calls for KVM ARM/ARM64.
KVM ARM/ARM64 being a hypervisor (and not a Trusted OS), we cannot provide this functions hence we emulate these functions in following way:
- MIGRATE - Returns "Not Supported"
- MIGRATE_INFO_TYPE - Return 2 i.e. Trusted OS is either not present or does not require migration
- MIGRATE_INFO_UP_CPU - Returns "Not Supported"
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/kvm/psci.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 9890710..75447a3 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -120,7 +120,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) /* Ignore other bits of target affinity */ target_affinity &= target_affinity_mask;
/* If one or more VCPU matching target affinity are running
/*
* If one or more VCPU matching target affinity are running
ah, you fixed it here, please move change to previous patch, thanks.
OK, will do.
-- Anup
* then return 0 (ON) else return 1 (OFF) */ kvm_for_each_vcpu(i, tmp, kvm) {
@@ -185,6 +186,21 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) case KVM_PSCI_0_2_FN64_AFFINITY_INFO: val = kvm_psci_vcpu_affinity_info(vcpu); break;
case KVM_PSCI_0_2_FN_MIGRATE:
case KVM_PSCI_0_2_FN64_MIGRATE:
val = KVM_PSCI_RET_NI;
break;
case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
/*
* Trusted OS is either not present or
* does not require migration
*/
val = 2;
break;
case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
break; case KVM_PSCI_0_2_FN_SYSTEM_OFF: kvm_psci_system_off(vcpu); val = KVM_PSCI_RET_SUCCESS;
@@ -196,12 +212,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) ret = 0; break; case KVM_PSCI_0_2_FN_CPU_SUSPEND:
case KVM_PSCI_0_2_FN_MIGRATE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
case KVM_PSCI_0_2_FN64_MIGRATE:
case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: val = KVM_PSCI_RET_NI; break; default:
-- 1.7.9.5
Otherwise: Reviewed-by: Christoffer Dall christoffer.dall@linaro.org _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
As-per PSCI v0.2, the source CPU provides physical address of "entry point" and "context id" for starting a target CPU.
Current emulation of CPU_ON function does not consider physical address of "context id" hence this patch updates kvm_psci_vcpu_on() such that it works for both PSCI v0.1 and PSCI v0.2.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org --- arch/arm/kvm/psci.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 75447a3..675866e 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -32,12 +32,14 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) vcpu->arch.pause = true; }
-static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) +static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu, + int psci_version) { struct kvm *kvm = source_vcpu->kvm; struct kvm_vcpu *vcpu = NULL, *tmp; wait_queue_head_t *wq; unsigned long cpu_id; + unsigned long context_id; unsigned long mpidr; phys_addr_t target_pc; int i; @@ -62,6 +64,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_INVAL;
target_pc = *vcpu_reg(source_vcpu, 2); + context_id = *vcpu_reg(source_vcpu, 3);
kvm_reset_vcpu(vcpu);
@@ -76,6 +79,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) kvm_vcpu_set_be(vcpu);
*vcpu_pc(vcpu) = target_pc; + if (psci_version != KVM_ARM_PSCI_0_1) + *vcpu_reg(vcpu, 0) = context_id; vcpu->arch.pause = false; smp_mb(); /* Make sure the above is visible */
@@ -180,7 +185,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) break; case KVM_PSCI_0_2_FN_CPU_ON: case KVM_PSCI_0_2_FN64_CPU_ON: - val = kvm_psci_vcpu_on(vcpu); + val = kvm_psci_vcpu_on(vcpu, KVM_ARM_PSCI_0_2); break; case KVM_PSCI_0_2_FN_AFFINITY_INFO: case KVM_PSCI_0_2_FN64_AFFINITY_INFO: @@ -234,7 +239,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) val = KVM_PSCI_RET_SUCCESS; break; case KVM_PSCI_FN_CPU_ON: - val = kvm_psci_vcpu_on(vcpu); + val = kvm_psci_vcpu_on(vcpu, KVM_ARM_PSCI_0_1); break; case KVM_PSCI_FN_CPU_SUSPEND: case KVM_PSCI_FN_MIGRATE:
On Thu, Feb 06, 2014 at 05:01:41PM +0530, Anup Patel wrote:
As-per PSCI v0.2, the source CPU provides physical address of "entry point" and "context id" for starting a target CPU.
Current emulation of CPU_ON function does not consider physical address of "context id" hence this patch updates kvm_psci_vcpu_on() such that it works for both PSCI v0.1 and PSCI v0.2.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/kvm/psci.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 75447a3..675866e 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -32,12 +32,14 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) vcpu->arch.pause = true; } -static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) +static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu,
int psci_version)
I thought this would be what you have kvm_psci_version() for?
{ struct kvm *kvm = source_vcpu->kvm; struct kvm_vcpu *vcpu = NULL, *tmp; wait_queue_head_t *wq; unsigned long cpu_id;
- unsigned long context_id; unsigned long mpidr; phys_addr_t target_pc; int i;
@@ -62,6 +64,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_INVAL; target_pc = *vcpu_reg(source_vcpu, 2);
- context_id = *vcpu_reg(source_vcpu, 3);
kvm_reset_vcpu(vcpu); @@ -76,6 +79,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) kvm_vcpu_set_be(vcpu); *vcpu_pc(vcpu) = target_pc;
- if (psci_version != KVM_ARM_PSCI_0_1)
vcpu->arch.pause = false; smp_mb(); /* Make sure the above is visible */*vcpu_reg(vcpu, 0) = context_id;
@@ -180,7 +185,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) break; case KVM_PSCI_0_2_FN_CPU_ON: case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break; case KVM_PSCI_0_2_FN_AFFINITY_INFO: case KVM_PSCI_0_2_FN64_AFFINITY_INFO:val = kvm_psci_vcpu_on(vcpu, KVM_ARM_PSCI_0_2);
@@ -234,7 +239,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) val = KVM_PSCI_RET_SUCCESS; break; case KVM_PSCI_FN_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break; case KVM_PSCI_FN_CPU_SUSPEND: case KVM_PSCI_FN_MIGRATE:val = kvm_psci_vcpu_on(vcpu, KVM_ARM_PSCI_0_1);
-- 1.7.9.5
otherwise: Reviewed-by: Christoffer Dall christoffer.dall@linaro.org
On Mon, Mar 17, 2014 at 9:11 AM, Christoffer Dall christoffer.dall@linaro.org wrote:
On Thu, Feb 06, 2014 at 05:01:41PM +0530, Anup Patel wrote:
As-per PSCI v0.2, the source CPU provides physical address of "entry point" and "context id" for starting a target CPU.
Current emulation of CPU_ON function does not consider physical address of "context id" hence this patch updates kvm_psci_vcpu_on() such that it works for both PSCI v0.1 and PSCI v0.2.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/kvm/psci.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 75447a3..675866e 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -32,12 +32,14 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) vcpu->arch.pause = true; }
-static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) +static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu,
int psci_version)
I thought this would be what you have kvm_psci_version() for?
Good point. I will use kvm_psci_version() here.
-- Anup
{ struct kvm *kvm = source_vcpu->kvm; struct kvm_vcpu *vcpu = NULL, *tmp; wait_queue_head_t *wq; unsigned long cpu_id;
unsigned long context_id; unsigned long mpidr; phys_addr_t target_pc; int i;
@@ -62,6 +64,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return KVM_PSCI_RET_INVAL;
target_pc = *vcpu_reg(source_vcpu, 2);
context_id = *vcpu_reg(source_vcpu, 3); kvm_reset_vcpu(vcpu);
@@ -76,6 +79,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) kvm_vcpu_set_be(vcpu);
*vcpu_pc(vcpu) = target_pc;
if (psci_version != KVM_ARM_PSCI_0_1)
*vcpu_reg(vcpu, 0) = context_id; vcpu->arch.pause = false; smp_mb(); /* Make sure the above is visible */
@@ -180,7 +185,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) break; case KVM_PSCI_0_2_FN_CPU_ON: case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
val = kvm_psci_vcpu_on(vcpu, KVM_ARM_PSCI_0_2); break; case KVM_PSCI_0_2_FN_AFFINITY_INFO: case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
@@ -234,7 +239,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) val = KVM_PSCI_RET_SUCCESS; break; case KVM_PSCI_FN_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
val = kvm_psci_vcpu_on(vcpu, KVM_ARM_PSCI_0_1); break; case KVM_PSCI_FN_CPU_SUSPEND: case KVM_PSCI_FN_MIGRATE:
-- 1.7.9.5
otherwise: Reviewed-by: Christoffer Dall christoffer.dall@linaro.org _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
This patch adds emulation of PSCI v0.2 CPU_SUSPEND function call for KVM ARM/ARM64. This is a VCPU-level function call which can suspend current VCPU or all VCPUs within current VCPU's affinity level.
The CPU_SUSPEND emulation is not tested much because currently there is no CPUIDLE driver in Linux kernel that uses PSCI CPU_SUSPEND. The PSCI CPU_SUSPEND implementation in ARM64 kernel was tested using a Simple CPUIDLE driver which is not published due to unstable DT-bindings for PSCI. (For more info, http://lwn.net/Articles/574950/)
Even if we had stable DT-bindings for PSCI and CPUIDLE driver that uses PSCI CPU_SUSPEND then still we need to define SUSPEND states for KVM ARM/ARM64. Due to this, the CPU_SUSPEND emulation added by this patch only pause a VCPU and to wakeup a VCPU we need to explicity call PSCI CPU_ON from Guest.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org --- arch/arm/include/asm/kvm_host.h | 5 +++ arch/arm/include/asm/kvm_psci.h | 1 + arch/arm/kvm/psci.c | 88 +++++++++++++++++++++++++++++++++++-- arch/arm/kvm/reset.c | 4 ++ arch/arm64/include/asm/kvm_host.h | 5 +++ arch/arm64/include/asm/kvm_psci.h | 1 + arch/arm64/kvm/reset.c | 4 ++ 7 files changed, 104 insertions(+), 4 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 193ceaf..2cc36a6 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -131,6 +131,11 @@ struct kvm_vcpu_arch { /* Don't run the guest on this vcpu */ bool pause;
+ /* PSCI suspend state */ + bool suspend; + u32 suspend_entry; + u32 suspend_context_id; + /* IO related fields */ struct kvm_decode mmio_decode;
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 6bda945..6a05ada 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -22,6 +22,7 @@ #define KVM_ARM_PSCI_0_2 2
int kvm_psci_version(struct kvm_vcpu *vcpu); +void kvm_psci_reset(struct kvm_vcpu *vcpu); int kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 675866e..482b0f6 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -15,6 +15,7 @@ * along with this program. If not, see http://www.gnu.org/licenses/. */
+#include <linux/smp.h> #include <linux/kvm_host.h> #include <linux/wait.h>
@@ -27,9 +28,81 @@ * as described in ARM document number ARM DEN 0022A. */
+struct psci_suspend_info { + struct kvm_vcpu *vcpu; + unsigned long saved_entry; + unsigned long saved_context_id; +}; + +static void psci_do_suspend(void *context) +{ + struct psci_suspend_info *sinfo = context; + + sinfo->vcpu->arch.pause = true; + sinfo->vcpu->arch.suspend = true; + sinfo->vcpu->arch.suspend_entry = sinfo->saved_entry; + sinfo->vcpu->arch.suspend_context_id = sinfo->saved_context_id; +} + +static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu) +{ + int i; + unsigned long mpidr; + unsigned long target_affinity; + unsigned long target_affinity_mask; + unsigned long lowest_affinity_level; + struct kvm *kvm = vcpu->kvm; + struct kvm_vcpu *tmp; + struct psci_suspend_info sinfo; + + target_affinity = kvm_vcpu_get_mpidr(vcpu); + lowest_affinity_level = (*vcpu_reg(vcpu, 1) >> 24) & 0x3; + + /* Determine target affinity mask */ + target_affinity_mask = MPIDR_HWID_BITMASK; + switch (lowest_affinity_level) { + case 0: /* All affinity levels are valid */ + target_affinity_mask &= ~0x0UL; + break; + case 1: /* Aff0 ignored */ + target_affinity_mask &= ~0xFFUL; + break; + case 2: /* Aff0 and Aff1 ignored */ + target_affinity_mask &= ~0xFFFFUL; + break; + case 3: /* Aff0, Aff1, and Aff2 ignored */ + target_affinity_mask &= ~0xFFFFFFUL; + break; + default: + return KVM_PSCI_RET_INVAL; + }; + + /* Ignore other bits of target affinity */ + target_affinity &= target_affinity_mask; + + /* Prepare suspend info */ + sinfo.vcpu = NULL; + sinfo.saved_entry = *vcpu_reg(vcpu, 2); + sinfo.saved_context_id = *vcpu_reg(vcpu, 3); + + /* Suspend all VCPUs within target affinity */ + kvm_for_each_vcpu(i, tmp, kvm) { + mpidr = kvm_vcpu_get_mpidr(tmp); + if (((mpidr & target_affinity_mask) == target_affinity) && + !tmp->arch.suspend) { + sinfo.vcpu = tmp; + smp_call_function_single(tmp->cpu, + psci_do_suspend, &sinfo, 1); + } + } + + return KVM_PSCI_RET_SUCCESS; +} + static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) { vcpu->arch.pause = true; + vcpu->arch.suspend = false; }
static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu, @@ -179,6 +252,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) */ val = 2; break; + case KVM_PSCI_0_2_FN_CPU_SUSPEND: + case KVM_PSCI_0_2_FN64_CPU_SUSPEND: + val = kvm_psci_vcpu_suspend(vcpu); + break; case KVM_PSCI_0_2_FN_CPU_OFF: kvm_psci_vcpu_off(vcpu); val = KVM_PSCI_RET_SUCCESS; @@ -216,10 +293,6 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) val = KVM_PSCI_RET_SUCCESS; ret = 0; break; - case KVM_PSCI_0_2_FN_CPU_SUSPEND: - case KVM_PSCI_0_2_FN64_CPU_SUSPEND: - val = KVM_PSCI_RET_NI; - break; default: return -EINVAL; } @@ -253,6 +326,13 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) return 1; }
+void kvm_psci_reset(struct kvm_vcpu *vcpu) +{ + vcpu->arch.suspend = false; + vcpu->arch.suspend_entry = 0; + vcpu->arch.suspend_context_id = 0; +} + /** * kvm_psci_call - handle PSCI call if r0 value is in range * @vcpu: Pointer to the VCPU struct diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c index f558c07..220c892 100644 --- a/arch/arm/kvm/reset.c +++ b/arch/arm/kvm/reset.c @@ -26,6 +26,7 @@ #include <asm/cputype.h> #include <asm/kvm_arm.h> #include <asm/kvm_coproc.h> +#include <asm/kvm_psci.h>
#include <kvm/arm_arch_timer.h>
@@ -79,5 +80,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) /* Reset arch_timer context */ kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
+ /* Reset PSCI state */ + kvm_psci_reset(vcpu); + return 0; } diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 92242ce..b2c97dc 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -119,6 +119,11 @@ struct kvm_vcpu_arch { /* Don't run the guest */ bool pause;
+ /* PSCI suspend state */ + bool suspend; + u64 suspend_entry; + u64 suspend_context_id; + /* IO related fields */ struct kvm_decode mmio_decode;
diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index bc39e55..4da675d 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -22,6 +22,7 @@ #define KVM_ARM_PSCI_0_2 2
int kvm_psci_version(struct kvm_vcpu *vcpu); +void kvm_psci_reset(struct kvm_vcpu *vcpu); int kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 70a7816..aca9f65 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -29,6 +29,7 @@ #include <asm/ptrace.h> #include <asm/kvm_arm.h> #include <asm/kvm_coproc.h> +#include <asm/kvm_psci.h>
/* * ARMv8 Reset Values @@ -108,5 +109,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) /* Reset timer */ kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
+ /* Reset PSCI state */ + kvm_psci_reset(vcpu); + return 0; }
On Thu, Feb 06, 2014 at 05:01:42PM +0530, Anup Patel wrote:
This patch adds emulation of PSCI v0.2 CPU_SUSPEND function call for KVM ARM/ARM64. This is a VCPU-level function call which can suspend current VCPU or all VCPUs within current VCPU's affinity level.
The CPU_SUSPEND emulation is not tested much because currently there is no CPUIDLE driver in Linux kernel that uses PSCI CPU_SUSPEND. The PSCI CPU_SUSPEND implementation in ARM64 kernel was tested using a Simple CPUIDLE driver which is not published due to unstable DT-bindings for PSCI. (For more info, http://lwn.net/Articles/574950/)
Even if we had stable DT-bindings for PSCI and CPUIDLE driver that uses PSCI CPU_SUSPEND then still we need to define SUSPEND states for KVM ARM/ARM64. Due to this, the CPU_SUSPEND emulation added by this patch only pause a VCPU and to wakeup a VCPU we need to explicity call PSCI CPU_ON from Guest.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 5 +++ arch/arm/include/asm/kvm_psci.h | 1 + arch/arm/kvm/psci.c | 88 +++++++++++++++++++++++++++++++++++-- arch/arm/kvm/reset.c | 4 ++ arch/arm64/include/asm/kvm_host.h | 5 +++ arch/arm64/include/asm/kvm_psci.h | 1 + arch/arm64/kvm/reset.c | 4 ++ 7 files changed, 104 insertions(+), 4 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 193ceaf..2cc36a6 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -131,6 +131,11 @@ struct kvm_vcpu_arch { /* Don't run the guest on this vcpu */ bool pause;
- /* PSCI suspend state */
- bool suspend;
- u32 suspend_entry;
- u32 suspend_context_id;
- /* IO related fields */ struct kvm_decode mmio_decode;
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 6bda945..6a05ada 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -22,6 +22,7 @@ #define KVM_ARM_PSCI_0_2 2 int kvm_psci_version(struct kvm_vcpu *vcpu); +void kvm_psci_reset(struct kvm_vcpu *vcpu); int kvm_psci_call(struct kvm_vcpu *vcpu); #endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 675866e..482b0f6 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -15,6 +15,7 @@
- along with this program. If not, see http://www.gnu.org/licenses/.
*/ +#include <linux/smp.h> #include <linux/kvm_host.h> #include <linux/wait.h> @@ -27,9 +28,81 @@
- as described in ARM document number ARM DEN 0022A.
*/ +struct psci_suspend_info {
- struct kvm_vcpu *vcpu;
- unsigned long saved_entry;
- unsigned long saved_context_id;
+};
+static void psci_do_suspend(void *context) +{
- struct psci_suspend_info *sinfo = context;
- sinfo->vcpu->arch.pause = true;
- sinfo->vcpu->arch.suspend = true;
- sinfo->vcpu->arch.suspend_entry = sinfo->saved_entry;
- sinfo->vcpu->arch.suspend_context_id = sinfo->saved_context_id;
I don't really understand this, why are you not just setting pause = true and modifying the registers as per the reentry rules in the spec?
Doesn't seem like this patch ever reads any of these values back?
+}
+static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu) +{
- int i;
- unsigned long mpidr;
- unsigned long target_affinity;
- unsigned long target_affinity_mask;
- unsigned long lowest_affinity_level;
- struct kvm *kvm = vcpu->kvm;
- struct kvm_vcpu *tmp;
- struct psci_suspend_info sinfo;
- target_affinity = kvm_vcpu_get_mpidr(vcpu);
- lowest_affinity_level = (*vcpu_reg(vcpu, 1) >> 24) & 0x3;
- /* Determine target affinity mask */
- target_affinity_mask = MPIDR_HWID_BITMASK;
- switch (lowest_affinity_level) {
- case 0: /* All affinity levels are valid */
target_affinity_mask &= ~0x0UL;
break;
- case 1: /* Aff0 ignored */
target_affinity_mask &= ~0xFFUL;
break;
- case 2: /* Aff0 and Aff1 ignored */
target_affinity_mask &= ~0xFFFFUL;
break;
- case 3: /* Aff0, Aff1, and Aff2 ignored */
target_affinity_mask &= ~0xFFFFFFUL;
break;
- default:
return KVM_PSCI_RET_INVAL;
- };
I feel like I've read this code before, can you factor it out?
- /* Ignore other bits of target affinity */
- target_affinity &= target_affinity_mask;
- /* Prepare suspend info */
- sinfo.vcpu = NULL;
- sinfo.saved_entry = *vcpu_reg(vcpu, 2);
- sinfo.saved_context_id = *vcpu_reg(vcpu, 3);
- /* Suspend all VCPUs within target affinity */
- kvm_for_each_vcpu(i, tmp, kvm) {
mpidr = kvm_vcpu_get_mpidr(tmp);
if (((mpidr & target_affinity_mask) == target_affinity) &&
!tmp->arch.suspend) {
sinfo.vcpu = tmp;
smp_call_function_single(tmp->cpu,
psci_do_suspend, &sinfo, 1);
Hmmm, are you sure this is correct? How does that correspond to the PSCI docs saying
"It is only possible to call CPU_SUSPEND from the current core. That is, it is not possible to request suspension of another core."
I would think this means, if all other cores in the specified affinity level are already suspended, allow suspending the entire cluster/group/..., but I may be wrong.
My comments above notwithstanding, this also feels racy. What happens if two virtual cores within the same affinity level calls CPU_SUSPEND at the same time?
Also, there doesn't seem to be any handling of the StateType requested by the caller, the reentry behavior is very different depending on the state you enter, unless you always treat the request as a suspend (clause 3 under Section 5.4.2 in the PSCI spec), in that case that deserves a comment.
}
- }
- return KVM_PSCI_RET_SUCCESS;
+}
static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) { vcpu->arch.pause = true;
- vcpu->arch.suspend = false;
} static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu, @@ -179,6 +252,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) */ val = 2; break;
- case KVM_PSCI_0_2_FN_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
val = kvm_psci_vcpu_suspend(vcpu);
case KVM_PSCI_0_2_FN_CPU_OFF: kvm_psci_vcpu_off(vcpu); val = KVM_PSCI_RET_SUCCESS;break;
@@ -216,10 +293,6 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) val = KVM_PSCI_RET_SUCCESS; ret = 0; break;
- case KVM_PSCI_0_2_FN_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
val = KVM_PSCI_RET_NI;
default: return -EINVAL; }break;
@@ -253,6 +326,13 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) return 1; } +void kvm_psci_reset(struct kvm_vcpu *vcpu) +{
- vcpu->arch.suspend = false;
- vcpu->arch.suspend_entry = 0;
- vcpu->arch.suspend_context_id = 0;
+}
/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c index f558c07..220c892 100644 --- a/arch/arm/kvm/reset.c +++ b/arch/arm/kvm/reset.c @@ -26,6 +26,7 @@ #include <asm/cputype.h> #include <asm/kvm_arm.h> #include <asm/kvm_coproc.h> +#include <asm/kvm_psci.h> #include <kvm/arm_arch_timer.h> @@ -79,5 +80,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) /* Reset arch_timer context */ kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
- /* Reset PSCI state */
- kvm_psci_reset(vcpu);
- return 0;
} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 92242ce..b2c97dc 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -119,6 +119,11 @@ struct kvm_vcpu_arch { /* Don't run the guest */ bool pause;
- /* PSCI suspend state */
- bool suspend;
- u64 suspend_entry;
- u64 suspend_context_id;
- /* IO related fields */ struct kvm_decode mmio_decode;
diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index bc39e55..4da675d 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -22,6 +22,7 @@ #define KVM_ARM_PSCI_0_2 2 int kvm_psci_version(struct kvm_vcpu *vcpu); +void kvm_psci_reset(struct kvm_vcpu *vcpu); int kvm_psci_call(struct kvm_vcpu *vcpu); #endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 70a7816..aca9f65 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -29,6 +29,7 @@ #include <asm/ptrace.h> #include <asm/kvm_arm.h> #include <asm/kvm_coproc.h> +#include <asm/kvm_psci.h> /*
- ARMv8 Reset Values
@@ -108,5 +109,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) /* Reset timer */ kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
- /* Reset PSCI state */
- kvm_psci_reset(vcpu);
- return 0;
}
1.7.9.5
Thanks,
On Mon, Mar 17, 2014 at 9:11 AM, Christoffer Dall christoffer.dall@linaro.org wrote:
On Thu, Feb 06, 2014 at 05:01:42PM +0530, Anup Patel wrote:
This patch adds emulation of PSCI v0.2 CPU_SUSPEND function call for KVM ARM/ARM64. This is a VCPU-level function call which can suspend current VCPU or all VCPUs within current VCPU's affinity level.
The CPU_SUSPEND emulation is not tested much because currently there is no CPUIDLE driver in Linux kernel that uses PSCI CPU_SUSPEND. The PSCI CPU_SUSPEND implementation in ARM64 kernel was tested using a Simple CPUIDLE driver which is not published due to unstable DT-bindings for PSCI. (For more info, http://lwn.net/Articles/574950/)
Even if we had stable DT-bindings for PSCI and CPUIDLE driver that uses PSCI CPU_SUSPEND then still we need to define SUSPEND states for KVM ARM/ARM64. Due to this, the CPU_SUSPEND emulation added by this patch only pause a VCPU and to wakeup a VCPU we need to explicity call PSCI CPU_ON from Guest.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 5 +++ arch/arm/include/asm/kvm_psci.h | 1 + arch/arm/kvm/psci.c | 88 +++++++++++++++++++++++++++++++++++-- arch/arm/kvm/reset.c | 4 ++ arch/arm64/include/asm/kvm_host.h | 5 +++ arch/arm64/include/asm/kvm_psci.h | 1 + arch/arm64/kvm/reset.c | 4 ++ 7 files changed, 104 insertions(+), 4 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 193ceaf..2cc36a6 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -131,6 +131,11 @@ struct kvm_vcpu_arch { /* Don't run the guest on this vcpu */ bool pause;
/* PSCI suspend state */
bool suspend;
u32 suspend_entry;
u32 suspend_context_id;
/* IO related fields */ struct kvm_decode mmio_decode;
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h index 6bda945..6a05ada 100644 --- a/arch/arm/include/asm/kvm_psci.h +++ b/arch/arm/include/asm/kvm_psci.h @@ -22,6 +22,7 @@ #define KVM_ARM_PSCI_0_2 2
int kvm_psci_version(struct kvm_vcpu *vcpu); +void kvm_psci_reset(struct kvm_vcpu *vcpu); int kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 675866e..482b0f6 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c @@ -15,6 +15,7 @@
- along with this program. If not, see http://www.gnu.org/licenses/.
*/
+#include <linux/smp.h> #include <linux/kvm_host.h> #include <linux/wait.h>
@@ -27,9 +28,81 @@
- as described in ARM document number ARM DEN 0022A.
*/
+struct psci_suspend_info {
struct kvm_vcpu *vcpu;
unsigned long saved_entry;
unsigned long saved_context_id;
+};
+static void psci_do_suspend(void *context) +{
struct psci_suspend_info *sinfo = context;
sinfo->vcpu->arch.pause = true;
sinfo->vcpu->arch.suspend = true;
sinfo->vcpu->arch.suspend_entry = sinfo->saved_entry;
sinfo->vcpu->arch.suspend_context_id = sinfo->saved_context_id;
I don't really understand this, why are you not just setting pause = true and modifying the registers as per the reentry rules in the spec?
Doesn't seem like this patch ever reads any of these values back?
Thats because we don't have any wake-up events defined for PSCI v0.2 emulated by KVM.
+}
+static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu) +{
int i;
unsigned long mpidr;
unsigned long target_affinity;
unsigned long target_affinity_mask;
unsigned long lowest_affinity_level;
struct kvm *kvm = vcpu->kvm;
struct kvm_vcpu *tmp;
struct psci_suspend_info sinfo;
target_affinity = kvm_vcpu_get_mpidr(vcpu);
lowest_affinity_level = (*vcpu_reg(vcpu, 1) >> 24) & 0x3;
/* Determine target affinity mask */
target_affinity_mask = MPIDR_HWID_BITMASK;
switch (lowest_affinity_level) {
case 0: /* All affinity levels are valid */
target_affinity_mask &= ~0x0UL;
break;
case 1: /* Aff0 ignored */
target_affinity_mask &= ~0xFFUL;
break;
case 2: /* Aff0 and Aff1 ignored */
target_affinity_mask &= ~0xFFFFUL;
break;
case 3: /* Aff0, Aff1, and Aff2 ignored */
target_affinity_mask &= ~0xFFFFFFUL;
break;
default:
return KVM_PSCI_RET_INVAL;
};
I feel like I've read this code before, can you factor it out?
OK, I will factor-out this portion since it can be shared with AFFINTIY_INFO emulation.
/* Ignore other bits of target affinity */
target_affinity &= target_affinity_mask;
/* Prepare suspend info */
sinfo.vcpu = NULL;
sinfo.saved_entry = *vcpu_reg(vcpu, 2);
sinfo.saved_context_id = *vcpu_reg(vcpu, 3);
/* Suspend all VCPUs within target affinity */
kvm_for_each_vcpu(i, tmp, kvm) {
mpidr = kvm_vcpu_get_mpidr(tmp);
if (((mpidr & target_affinity_mask) == target_affinity) &&
!tmp->arch.suspend) {
sinfo.vcpu = tmp;
smp_call_function_single(tmp->cpu,
psci_do_suspend, &sinfo, 1);
Hmmm, are you sure this is correct? How does that correspond to the PSCI docs saying
"It is only possible to call CPU_SUSPEND from the current core. That is, it is not possible to request suspension of another core."
I would think this means, if all other cores in the specified affinity level are already suspended, allow suspending the entire cluster/group/..., but I may be wrong.
Actually, CPU_SUSPEND is for all cores belonging to affinity of current core.
My comments above notwithstanding, this also feels racy. What happens if two virtual cores within the same affinity level calls CPU_SUSPEND at the same time?
Yes, I know its racy. I was expecting this comment.
What would be appropriate lock to protect per-VCPU suspend context?
I think spinlock would be better because psci_do_suspend() is called using SMP IPIs.
Also, there doesn't seem to be any handling of the StateType requested by the caller, the reentry behavior is very different depending on the state you enter, unless you always treat the request as a suspend (clause 3 under Section 5.4.2 in the PSCI spec), in that case that deserves a comment.
The StateType is completely implementation dependent. Also, it is the StateType that will help determine the wake-up event.
For KVM, we really don't have any StateType defined hence we don't have any wake-up events defined for KVM PSCI.
Should we have KVM specific suspend states? What would KVM suspend states look like because suspend states are platform specific?
-- Anup
}
}
return KVM_PSCI_RET_SUCCESS;
+}
static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) { vcpu->arch.pause = true;
vcpu->arch.suspend = false;
}
static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu, @@ -179,6 +252,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) */ val = 2; break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
val = kvm_psci_vcpu_suspend(vcpu);
break; case KVM_PSCI_0_2_FN_CPU_OFF: kvm_psci_vcpu_off(vcpu); val = KVM_PSCI_RET_SUCCESS;
@@ -216,10 +293,6 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) val = KVM_PSCI_RET_SUCCESS; ret = 0; break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
val = KVM_PSCI_RET_NI;
break; default: return -EINVAL; }
@@ -253,6 +326,13 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) return 1; }
+void kvm_psci_reset(struct kvm_vcpu *vcpu) +{
vcpu->arch.suspend = false;
vcpu->arch.suspend_entry = 0;
vcpu->arch.suspend_context_id = 0;
+}
/**
- kvm_psci_call - handle PSCI call if r0 value is in range
- @vcpu: Pointer to the VCPU struct
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c index f558c07..220c892 100644 --- a/arch/arm/kvm/reset.c +++ b/arch/arm/kvm/reset.c @@ -26,6 +26,7 @@ #include <asm/cputype.h> #include <asm/kvm_arm.h> #include <asm/kvm_coproc.h> +#include <asm/kvm_psci.h>
#include <kvm/arm_arch_timer.h>
@@ -79,5 +80,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) /* Reset arch_timer context */ kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
/* Reset PSCI state */
kvm_psci_reset(vcpu);
return 0;
} diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 92242ce..b2c97dc 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -119,6 +119,11 @@ struct kvm_vcpu_arch { /* Don't run the guest */ bool pause;
/* PSCI suspend state */
bool suspend;
u64 suspend_entry;
u64 suspend_context_id;
/* IO related fields */ struct kvm_decode mmio_decode;
diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h index bc39e55..4da675d 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/arch/arm64/include/asm/kvm_psci.h @@ -22,6 +22,7 @@ #define KVM_ARM_PSCI_0_2 2
int kvm_psci_version(struct kvm_vcpu *vcpu); +void kvm_psci_reset(struct kvm_vcpu *vcpu); int kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */ diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 70a7816..aca9f65 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -29,6 +29,7 @@ #include <asm/ptrace.h> #include <asm/kvm_arm.h> #include <asm/kvm_coproc.h> +#include <asm/kvm_psci.h>
/*
- ARMv8 Reset Values
@@ -108,5 +109,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) /* Reset timer */ kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
/* Reset PSCI state */
kvm_psci_reset(vcpu);
return 0;
}
1.7.9.5
Thanks,
Christoffer _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
On Mon, Mar 17, 2014 at 06:54:28AM +0000, Anup Patel wrote:
On Mon, Mar 17, 2014 at 9:11 AM, Christoffer Dall christoffer.dall@linaro.org wrote:
On Thu, Feb 06, 2014 at 05:01:42PM +0530, Anup Patel wrote:
This patch adds emulation of PSCI v0.2 CPU_SUSPEND function call for KVM ARM/ARM64. This is a VCPU-level function call which can suspend current VCPU or all VCPUs within current VCPU's affinity level.
The CPU_SUSPEND emulation is not tested much because currently there is no CPUIDLE driver in Linux kernel that uses PSCI CPU_SUSPEND. The PSCI CPU_SUSPEND implementation in ARM64 kernel was tested using a Simple CPUIDLE driver which is not published due to unstable DT-bindings for PSCI. (For more info, http://lwn.net/Articles/574950/)
Even if we had stable DT-bindings for PSCI and CPUIDLE driver that uses PSCI CPU_SUSPEND then still we need to define SUSPEND states for KVM ARM/ARM64. Due to this, the CPU_SUSPEND emulation added by this patch only pause a VCPU and to wakeup a VCPU we need to explicity call PSCI CPU_ON from Guest.
Signed-off-by: Anup Patel anup.patel@linaro.org Signed-off-by: Pranavkumar Sawargaonkar pranavkumar@linaro.org
arch/arm/include/asm/kvm_host.h | 5 +++ arch/arm/include/asm/kvm_psci.h | 1 + arch/arm/kvm/psci.c | 88 +++++++++++++++++++++++++++++++++++-- arch/arm/kvm/reset.c | 4 ++ arch/arm64/include/asm/kvm_host.h | 5 +++ arch/arm64/include/asm/kvm_psci.h | 1 + arch/arm64/kvm/reset.c | 4 ++ 7 files changed, 104 insertions(+), 4 deletions(-)
[...]
+static void psci_do_suspend(void *context) +{
struct psci_suspend_info *sinfo = context;
sinfo->vcpu->arch.pause = true;
sinfo->vcpu->arch.suspend = true;
sinfo->vcpu->arch.suspend_entry = sinfo->saved_entry;
sinfo->vcpu->arch.suspend_context_id = sinfo->saved_context_id;
I don't really understand this, why are you not just setting pause = true and modifying the registers as per the reentry rules in the spec?
Doesn't seem like this patch ever reads any of these values back?
Thats because we don't have any wake-up events defined for PSCI v0.2 emulated by KVM.
I would expect interrupts to wake secondaries (e.g. SGIs for the broadcast timer). Do you have that at least?
[...]
/* Ignore other bits of target affinity */
target_affinity &= target_affinity_mask;
/* Prepare suspend info */
sinfo.vcpu = NULL;
sinfo.saved_entry = *vcpu_reg(vcpu, 2);
sinfo.saved_context_id = *vcpu_reg(vcpu, 3);
/* Suspend all VCPUs within target affinity */
kvm_for_each_vcpu(i, tmp, kvm) {
mpidr = kvm_vcpu_get_mpidr(tmp);
if (((mpidr & target_affinity_mask) == target_affinity) &&
!tmp->arch.suspend) {
sinfo.vcpu = tmp;
smp_call_function_single(tmp->cpu,
psci_do_suspend, &sinfo, 1);
Hmmm, are you sure this is correct? How does that correspond to the PSCI docs saying
"It is only possible to call CPU_SUSPEND from the current core. That is, it is not possible to request suspension of another core."
I would think this means, if all other cores in the specified affinity level are already suspended, allow suspending the entire cluster/group/..., but I may be wrong.
Actually, CPU_SUSPEND is for all cores belonging to affinity of current core.
Per 5.4.3 in the PSCI 0.2 spec:
The power state parameter expresses a constraint: Caller allows entry down to this state, but no deeper.
The AffinityLevel parameter is a maximum level to suspend, not a required level to suspend. CPUs are never forcibly suspended.
There's an example table in 5.4.3 which might help to clarify.
My comments above notwithstanding, this also feels racy. What happens if two virtual cores within the same affinity level calls CPU_SUSPEND at the same time?
Yes, I know its racy. I was expecting this comment.
What would be appropriate lock to protect per-VCPU suspend context?
I think spinlock would be better because psci_do_suspend() is called using SMP IPIs.
Also, there doesn't seem to be any handling of the StateType requested by the caller, the reentry behavior is very different depending on the state you enter, unless you always treat the request as a suspend (clause 3 under Section 5.4.2 in the PSCI spec), in that case that deserves a comment.
The StateType is completely implementation dependent. Also, it is the StateType that will help determine the wake-up event.
For KVM, we really don't have any StateType defined hence we don't have any wake-up events defined for KVM PSCI.
Should we have KVM specific suspend states? What would KVM suspend states look like because suspend states are platform specific?
This is something we need to figure out how to describe to the kernel.
Cheers, Mark.
On Mon, Mar 17, 2014 at 12:24:28PM +0530, Anup Patel wrote:
On Mon, Mar 17, 2014 at 9:11 AM, Christoffer Dall christoffer.dall@linaro.org wrote:
On Thu, Feb 06, 2014 at 05:01:42PM +0530, Anup Patel wrote:
This patch adds emulation of PSCI v0.2 CPU_SUSPEND function call for KVM ARM/ARM64. This is a VCPU-level function call which can suspend current VCPU or all VCPUs within current VCPU's affinity level.
The CPU_SUSPEND emulation is not tested much because currently there is no CPUIDLE driver in Linux kernel that uses PSCI CPU_SUSPEND. The PSCI CPU_SUSPEND implementation in ARM64 kernel was tested using a Simple CPUIDLE driver which is not published due to unstable DT-bindings for PSCI. (For more info, http://lwn.net/Articles/574950/)
Even if we had stable DT-bindings for PSCI and CPUIDLE driver that uses PSCI CPU_SUSPEND then still we need to define SUSPEND states for KVM ARM/ARM64. Due to this, the CPU_SUSPEND emulation added by this patch only pause a VCPU and to wakeup a VCPU we need to explicity call PSCI CPU_ON from Guest.
[...]
+static void psci_do_suspend(void *context) +{
struct psci_suspend_info *sinfo = context;
sinfo->vcpu->arch.pause = true;
sinfo->vcpu->arch.suspend = true;
sinfo->vcpu->arch.suspend_entry = sinfo->saved_entry;
sinfo->vcpu->arch.suspend_context_id = sinfo->saved_context_id;
I don't really understand this, why are you not just setting pause = true and modifying the registers as per the reentry rules in the spec?
Doesn't seem like this patch ever reads any of these values back?
Thats because we don't have any wake-up events defined for PSCI v0.2 emulated by KVM.
That doesn't make the code any more useful. All you're doing which has an effect here is setting pause = true.
If you're adding the other logic to create an infrastructure for some later time where you plan to add some logic, then (1) I think you should wait with introducing this infrastructure until you're going to use it, and (2) it needs a big fat comment and an explanation of this in the commit message.
+}
+static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu) +{
int i;
unsigned long mpidr;
unsigned long target_affinity;
unsigned long target_affinity_mask;
unsigned long lowest_affinity_level;
struct kvm *kvm = vcpu->kvm;
struct kvm_vcpu *tmp;
struct psci_suspend_info sinfo;
target_affinity = kvm_vcpu_get_mpidr(vcpu);
lowest_affinity_level = (*vcpu_reg(vcpu, 1) >> 24) & 0x3;
/* Determine target affinity mask */
target_affinity_mask = MPIDR_HWID_BITMASK;
switch (lowest_affinity_level) {
case 0: /* All affinity levels are valid */
target_affinity_mask &= ~0x0UL;
break;
case 1: /* Aff0 ignored */
target_affinity_mask &= ~0xFFUL;
break;
case 2: /* Aff0 and Aff1 ignored */
target_affinity_mask &= ~0xFFFFUL;
break;
case 3: /* Aff0, Aff1, and Aff2 ignored */
target_affinity_mask &= ~0xFFFFFFUL;
break;
default:
return KVM_PSCI_RET_INVAL;
};
I feel like I've read this code before, can you factor it out?
OK, I will factor-out this portion since it can be shared with AFFINTIY_INFO emulation.
/* Ignore other bits of target affinity */
target_affinity &= target_affinity_mask;
/* Prepare suspend info */
sinfo.vcpu = NULL;
sinfo.saved_entry = *vcpu_reg(vcpu, 2);
sinfo.saved_context_id = *vcpu_reg(vcpu, 3);
/* Suspend all VCPUs within target affinity */
kvm_for_each_vcpu(i, tmp, kvm) {
mpidr = kvm_vcpu_get_mpidr(tmp);
if (((mpidr & target_affinity_mask) == target_affinity) &&
!tmp->arch.suspend) {
sinfo.vcpu = tmp;
smp_call_function_single(tmp->cpu,
psci_do_suspend, &sinfo, 1);
Hmmm, are you sure this is correct? How does that correspond to the PSCI docs saying
"It is only possible to call CPU_SUSPEND from the current core. That is, it is not possible to request suspension of another core."
I would think this means, if all other cores in the specified affinity level are already suspended, allow suspending the entire cluster/group/..., but I may be wrong.
Actually, CPU_SUSPEND is for all cores belonging to affinity of current core.
I don't think so, see Mark's response. I think the note I quoted above about it not being possible to request suspend of other cores makes it clear that this is not the intended behavior.
My comments above notwithstanding, this also feels racy. What happens if two virtual cores within the same affinity level calls CPU_SUSPEND at the same time?
Yes, I know its racy. I was expecting this comment.
uh, ok :) Maybe that would make this an RFC patch and known race conditions should be pointed out at least in the commit message.
What would be appropriate lock to protect per-VCPU suspend context?
I think spinlock would be better because psci_do_suspend() is called using SMP IPIs.
Since we are not keeping any live state for anything else than each vcpu, this should all just be local operations and you don't need locking at all.
If needed, a per-VM spin-lock for psci state seems appropriate, but I didn't think carefully about this.
Also, there doesn't seem to be any handling of the StateType requested by the caller, the reentry behavior is very different depending on the state you enter, unless you always treat the request as a suspend (clause 3 under Section 5.4.2 in the PSCI spec), in that case that deserves a comment.
The StateType is completely implementation dependent. Also, it is the StateType that will help determine the wake-up event.
How do you arrive at this conclusion?
The StateID is completely platform-specific.
The StateType is referenced throughout the document, and the reentry from standby vs. power-down is very different (return to caller vs. reentry to different entry point address).
The only exception I can find in the spec is that power-down may not succeed and the firmware may just do standby instead, if this is what we're doing, this needs to be very clearly commented.
For KVM, we really don't have any StateType defined hence we don't have any wake-up events defined for KVM PSCI.
StateType is defined in the PSCI spec, see above.
Should we have KVM specific suspend states? What would KVM suspend states look like because suspend states are platform specific?
Do you mean StateID here? I don't think we need anything for KVM.
[...]
Thanks, -Christoffer
On Thu, Feb 06, 2014 at 05:01:32PM +0530, Anup Patel wrote:
Currently, KVM ARM/ARM64 only provides in-kernel emulation of Power State and Coordination Interface (PSCI) v0.1.
This patchset aims at providing newer PSCI v0.2 for KVM ARM/ARM64 VCPUs such that it does not break current KVM ARM/ARM64 ABI. Also, the patchset provides emulation of only few PSCI v0.2 functions such as PSCI_VERSION, CPU_ON, and CPU_OFF. Emulation of other PSCI v0.2 functions will be added later.
This doesn't seem to be true any longer does it?
The user space tools (i.e. QEMU or KVMTOOL) will have to explicitly enable KVM_ARM_VCPU_PSCI_0_2 feature using KVM_ARM_VCPU_INIT ioctl for providing PSCI v0.2 to VCPUs.
Besides the stuff you already added, I think you need to also add returning ALREADY_ON for the CPU_ON call if the VCPU requested is already on.
Thanks, -Christoffer
On Mon, Mar 17, 2014 at 9:09 AM, Christoffer Dall christoffer.dall@linaro.org wrote:
On Thu, Feb 06, 2014 at 05:01:32PM +0530, Anup Patel wrote:
Currently, KVM ARM/ARM64 only provides in-kernel emulation of Power State and Coordination Interface (PSCI) v0.1.
This patchset aims at providing newer PSCI v0.2 for KVM ARM/ARM64 VCPUs such that it does not break current KVM ARM/ARM64 ABI. Also, the patchset provides emulation of only few PSCI v0.2 functions such as PSCI_VERSION, CPU_ON, and CPU_OFF. Emulation of other PSCI v0.2 functions will be added later.
This doesn't seem to be true any longer does it?
Copy-Paste Error !!!!
I will correct this.
The user space tools (i.e. QEMU or KVMTOOL) will have to explicitly enable KVM_ARM_VCPU_PSCI_0_2 feature using KVM_ARM_VCPU_INIT ioctl for providing PSCI v0.2 to VCPUs.
Besides the stuff you already added, I think you need to also add returning ALREADY_ON for the CPU_ON call if the VCPU requested is already on.
OK, I will add it. Thanks for pointing.
Thanks, -Christoffer _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
-- Anup
linaro-kernel@lists.linaro.org