[PATCH v2 2/3] ARM/ARM64: KVM: Add support for PSCI v0.2 emulation
Anup Patel
apatel at apm.com
Mon Feb 3 06:16:35 EST 2014
Hi Mark,
On Mon, Feb 3, 2014 at 4:24 PM, Mark Rutland <mark.rutland at arm.com> wrote:
> On Thu, Jan 30, 2014 at 10:41:18AM +0000, 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.
>
> I have an issue with this. PSCI 0.2 makes all but two functions (MIGRATE
> and MIGRATE_INFO_CPU_UP) mandatory, and hence not allowed to return
> NOT_SUPPORTED.
>
> Additionally, for correct behaviour across a kexec in future, we'll
> require AFFINITY_INFO for PSCI 0.2+ systems to determint when a CPU is
> actually dead (and cannot affect the cache hierarchy). I'd very much
> like to make that a hard requirement to ensure correctness.
>
> I would very much like to see at least trivial implementations of those
> mandatory functions, so that we don't need a
> KVM_ARM_VCPU_PSCI_REALLY_0_2 or similar in future. As it stands this
> series does not implement PSCI 0.2.
The intention behind this series was to provide a base implementation of
PSCI v0.2 which can be extended by subsequent patches that implement
other PSCI v0.2 functions.
I already have a patch series that implement PSCI v0.2 SYSTEM_OFF and
SYSTEM_RESET based on this series.
Regards,
Anup
>
> Thanks,
> Mark.
>
>>
>> Signed-off-by: Anup Patel <anup.patel at linaro.org>
>> Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar at 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 bce6d32..dc4e3ed 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 c498b60..bf860e2 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;
>> @@ -164,7 +165,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))
>>
>> @@ -173,9 +174,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 151eb91..e508125 100644
>> --- a/arch/arm/kvm/arm.c
>> +++ b/arch/arm/kvm/arm.c
>> @@ -193,6 +193,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..7fdc881 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 d9f026b..b7555d3 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;
>> @@ -150,7 +151,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))
>>
>> @@ -159,10 +160,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
>>
>>
> CONFIDENTIALITY NOTICE: This e-mail message, including any attachments,
> is for the sole use of the intended recipient(s) and contains information
> that is confidential and proprietary to Applied Micro Circuits Corporation or its subsidiaries.
> It is to be used solely for the purpose of furthering the parties' business relationship.
> All unauthorized review, use, disclosure or distribution is prohibited.
> If you are not the intended recipient, please contact the sender by reply e-mail
> and destroy all copies of the original message.
>
More information about the linux-arm-kernel
mailing list