diff mbox

[v5,02/11] ARM/ARM64: KVM: Add base for PSCI v0.2 emulation

Message ID 1395406414-11707-3-git-send-email-anup.patel@linaro.org
State New
Headers show

Commit Message

Anup Patel March 21, 2014, 12:53 p.m. UTC
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/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 ++++++++++++++-
 7 files changed, 151 insertions(+), 16 deletions(-)

Comments

Christoffer Dall March 21, 2014, 11:27 p.m. UTC | #1
On Fri, Mar 21, 2014 at 06:23:25PM +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>

The content here can carry my Reviewed-by tag, but I think Rob's point
about sharing this code between KVM arm/arm64 and the PSCI code itself
it important, see:

http://lists.infradead.org/pipermail/linux-arm-kernel/2014-March/241792.html


Thanks,
-Christoffer
Anup Patel March 22, 2014, 4:24 a.m. UTC | #2
On 22 March 2014 04:57, Christoffer Dall <christoffer.dall@linaro.org> wrote:
> On Fri, Mar 21, 2014 at 06:23:25PM +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>
>
> The content here can carry my Reviewed-by tag, but I think Rob's point
> about sharing this code between KVM arm/arm64 and the PSCI code itself
> it important, see:
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-March/241792.html

My apologies, I totally missed Rob's comment.

My suggestion would be to have:
arch/arm/include/uapi/asm/psci.h
arch/arm64/include/uapi/asm/psci.h

These headers can have following defines:

/* PSCI v0.1 interface */
#define PSCI_FN(base, n)            (base + (n))

#define PSCI_FN_CPU_SUSPEND(base)        PSCI_FN(base, 0)
#define PSCI_FN_CPU_OFF(base)        PSCI_FN(base, 1)
#define PSCI_FN_CPU_ON(base)        PSCI_FN(base, 2)
#define PSCI_FN_MIGRATE(base)        PSCI_FN(base, 3)

/* PSCI v0.2 interface */
#define PSCI_0_2_FN_BASE        0x84000000
#define PSCI_0_2_FN(n)        (PSCI_0_2_FN_BASE + (n))
#define PSCI_0_2_FN64_BASE        0xC4000000
#define PSCI_0_2_FN64(n)        (PSCI_0_2_FN64_BASE + (n))

#define PSCI_0_2_FN_PSCI_VERSION    PSCI_0_2_FN(0)
#define PSCI_0_2_FN_CPU_SUSPEND    PSCI_0_2_FN(1)
#define PSCI_0_2_FN_CPU_OFF        PSCI_0_2_FN(2)
#define PSCI_0_2_FN_CPU_ON        PSCI_0_2_FN(3)
#define PSCI_0_2_FN_AFFINITY_INFO    PSCI_0_2_FN(4)
#define PSCI_0_2_FN_MIGRATE        PSCI_0_2_FN(5)
#define PSCI_0_2_FN_MIGRATE_INFO_TYPE \
                    PSCI_0_2_FN(6)
#define PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
                    PSCI_0_2_FN(7)
#define PSCI_0_2_FN_SYSTEM_OFF    PSCI_0_2_FN(8)
#define PSCI_0_2_FN_SYSTEM_RESET    PSCI_0_2_FN(9)

#define PSCI_0_2_FN64_CPU_SUSPEND    PSCI_0_2_FN64(1)
#define PSCI_0_2_FN64_CPU_ON    PSCI_0_2_FN64(3)
#define PSCI_0_2_FN64_AFFINITY_INFO    PSCI_0_2_FN64(4)
#define PSCI_0_2_FN64_MIGRATE    PSCI_0_2_FN64(5)
#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
                    PSCI_0_2_FN64(7)

/* PSCI return values */
#define PSCI_RET_SUCCESS        0
#define PSCI_RET_NI            ((unsigned long)-1)
#define PSCI_RET_INVAL        ((unsigned long)-2)
#define PSCI_RET_DENIED        ((unsigned long)-3)
#define PSCI_RET_ALREADY_ON        ((unsigned long)-4)
#define PSCI_RET_ON_PENDING        ((unsigned long)-5)
#define PSCI_RET_INTERNAL_FAILURE    ((unsigned long)-6)
#define PSCI_RET_NOT_PRESENT    ((unsigned long)-7)
#define PSCI_RET_DISABLED        ((unsigned long)-8)

The usual headers arch/arm/include/uapi/asm/kvm.h and
arch/arm64/include/uapi/asm/kvm.h will only define
KVM_PSCI_FN_BASE for PSCI v0.1

Regards,
Anup

>
>
> Thanks,
> -Christoffer
Christoffer Dall March 23, 2014, 5:44 p.m. UTC | #3
On Sat, Mar 22, 2014 at 09:54:55AM +0530, Anup Patel wrote:
> On 22 March 2014 04:57, Christoffer Dall <christoffer.dall@linaro.org> wrote:
> > On Fri, Mar 21, 2014 at 06:23:25PM +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>
> >
> > The content here can carry my Reviewed-by tag, but I think Rob's point
> > about sharing this code between KVM arm/arm64 and the PSCI code itself
> > it important, see:
> >
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2014-March/241792.html
> 
> My apologies, I totally missed Rob's comment.

No worries at all.

> 
> My suggestion would be to have:
> arch/arm/include/uapi/asm/psci.h
> arch/arm64/include/uapi/asm/psci.h

I think the suggestion was to move all this to include/uapi/linux/psci.h
or something equivalent so also arm and arm64 can share these defines,
but maybe I read too much into it.

Rob?
Rob Herring March 24, 2014, 1:26 p.m. UTC | #4
On Sun, Mar 23, 2014 at 12:44 PM, Christoffer Dall
<christoffer.dall@linaro.org> wrote:
> On Sat, Mar 22, 2014 at 09:54:55AM +0530, Anup Patel wrote:
>> On 22 March 2014 04:57, Christoffer Dall <christoffer.dall@linaro.org> wrote:
>> > On Fri, Mar 21, 2014 at 06:23:25PM +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>
>> >
>> > The content here can carry my Reviewed-by tag, but I think Rob's point
>> > about sharing this code between KVM arm/arm64 and the PSCI code itself
>> > it important, see:
>> >
>> > http://lists.infradead.org/pipermail/linux-arm-kernel/2014-March/241792.html
>>
>> My apologies, I totally missed Rob's comment.
>
> No worries at all.
>
>>
>> My suggestion would be to have:
>> arch/arm/include/uapi/asm/psci.h
>> arch/arm64/include/uapi/asm/psci.h
>
> I think the suggestion was to move all this to include/uapi/linux/psci.h
> or something equivalent so also arm and arm64 can share these defines,
> but maybe I read too much into it.

Yes. It is perfectly fine for a somewhat architecture specific header
to live in include/linux (or include/uapi/linux).

Rob
Ashwin Chaugule March 26, 2014, 3:32 p.m. UTC | #5
Hello,

On 24 March 2014 09:26, Rob Herring <rob.herring@linaro.org> wrote:

>>>
>>> My suggestion would be to have:
>>> arch/arm/include/uapi/asm/psci.h
>>> arch/arm64/include/uapi/asm/psci.h
>>
>> I think the suggestion was to move all this to include/uapi/linux/psci.h
>> or something equivalent so also arm and arm64 can share these defines,
>> but maybe I read too much into it.
>
> Yes. It is perfectly fine for a somewhat architecture specific header
> to live in include/linux (or include/uapi/linux).
>
>
While I'm aware that we wouldn't want to push seemingly irrelevant
stuff into this header, I'm thinking of ways to unify the ARM and
ARM64 PSCI code. A lot of it is reusable between the two.
So, can this header also include all the common PSCI functions between
ARM and ARM64? And can KVM possibly use these functions as well?

Alternately, is drivers/psci.c a more suitable place? In this case, at
least one function will be guarded by CONFIG_ARM64.

Cheers,
Ashwin
Rob Herring March 26, 2014, 4:08 p.m. UTC | #6
On Wed, Mar 26, 2014 at 10:32 AM, Ashwin Chaugule
<ashwin.chaugule@linaro.org> wrote:
> Hello,
>
> On 24 March 2014 09:26, Rob Herring <rob.herring@linaro.org> wrote:
>
>>>>
>>>> My suggestion would be to have:
>>>> arch/arm/include/uapi/asm/psci.h
>>>> arch/arm64/include/uapi/asm/psci.h
>>>
>>> I think the suggestion was to move all this to include/uapi/linux/psci.h
>>> or something equivalent so also arm and arm64 can share these defines,
>>> but maybe I read too much into it.
>>
>> Yes. It is perfectly fine for a somewhat architecture specific header
>> to live in include/linux (or include/uapi/linux).
>>
>>
> While I'm aware that we wouldn't want to push seemingly irrelevant
> stuff into this header, I'm thinking of ways to unify the ARM and
> ARM64 PSCI code. A lot of it is reusable between the two.
> So, can this header also include all the common PSCI functions between
> ARM and ARM64? And can KVM possibly use these functions as well?

Anything under uapi should be related to the PSCI ABI. If there are
headers to be shared that are just kernel implementation specific,
then they can go in include/linux/.

> Alternately, is drivers/psci.c a more suitable place? In this case, at
> least one function will be guarded by CONFIG_ARM64.

No. For .c files, I don't think we have a good solution. Some of the
kvm stuff does ../../ type includes back to arch/arm, but that's not a
very clean solution.

Rob
diff mbox

Patch

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/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