In-kernel PSCI v0.2 emulation for KVM ARM/ARM64
Subsystems (5)
v5 cover In-kernel PSCI v0.2 emulation for KVM ARM/ARM64
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.
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:
V5:
- Have separate last patch to advertise KVM_CAP_ARM_PSCI_0_2
- Use kvm_psci_version() in kvm_psci_vcpu_on()
- Return ALREADY_ON for PSCI v0.2 CPU_ON if VCPU is not paused
- Remove per-VCPU suspend context
- As-per PSCI v0.2 spec, only current CPU can suspend itself
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 (11):
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
ARM/ARM64: KVM: Advertise KVM_CAP_ARM_PSCI_0_2 to user space
Documentation/virtual/kvm/api.txt | 17 +++ arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/include/asm/kvm_psci.h | 6 +- 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 | 220 ++++++++++++++++++++++++++++++++++--- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_psci.h | 6 +- arch/arm64/include/uapi/asm/kvm.h | 35 +++++- arch/arm64/kvm/handle_exit.c | 10 +- include/uapi/linux/kvm.h | 9 ++ 12 files changed, 326 insertions(+), 27 deletions(-)
Signature · 1 line
1.7.9.5
PATCH v5 1/11 KVM: Add capability to advertise PSCI v0.2 support
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.
--- include/uapi/linux/kvm.h | 1 + 1 file changed, 1 insertion(+)
include/uapi/linux/kvm.h +1 -0
@@ -741,6 +741,7 @@ struct kvm_ppc_smmu_info {#define KVM_CAP_EXT_EMUL_CPUID 95#define KVM_CAP_HYPERV_TIME 96#define KVM_CAP_IOAPIC_POLARITY_IGNORED 97 +#define KVM_CAP_ARM_PSCI_0_2 98#ifdef KVM_CAP_IRQ_ROUTING
Signature · 1 line
1.7.9.5
PATCH v5 1/11 KVM: Add capability to advertise PSCI v0.2 support
Quoted 6 lines · Anup Patel
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_2in KVM user space interface header.Signed-off-by Anup Patel <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>
Please add the acked-by tags when people give them to you - otherwise it's a bit of a wasted effort and I have to go back and check so I don't review the patches again.
Thanks,
-Christoffer
PATCH v5 1/11 KVM: Add capability to advertise PSCI v0.2 support
Quoted 11 lines · Christoffer Dall
Quoted 6 lines · Anup Patel
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_2in KVM user space interface header.Signed-off-by Anup Patel <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>Please add the acked-by tags when people give them to you - otherwise it's a bit of a wasted effort and I have to go back and check so I don't review the patches again.
OK.
Quoted 3 lines
Thanks,
-Christoffer
PATCH v5 2/11 ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
In reply to Anup PatelCurrently, 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.
--- 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(-)
arch/arm/include/asm/kvm_host.h +1 -1
@@ -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>
arch/arm/include/asm/kvm_psci.h +4 -0
@@ -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__ */
arch/arm/include/uapi/asm/kvm.h +34 -1
@@ -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__ */
arch/arm/kvm/psci.c +73 -12
100 lines not on this page · raw message
arch/arm64/include/asm/kvm_host.h +1 -1
@@ -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 3struct kvm_vcpu ;int kvm_target_cpu (void );
arch/arm64/include/asm/kvm_psci.h +4 -0
@@ -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__ */
arch/arm64/include/uapi/asm/kvm.h +34 -1
@@ -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
Signature · 1 line
1.7.9.5
PATCH v5 2/11 ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
Quoted 7 lines · Anup Patel
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.
Quoted 6 lines
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_2feature when doing VCPU init usingKVM_ARM_VCPU_INITioctl.Signed-off-by Anup Patel <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>
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
PATCH v5 2/11 ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
Quoted 12 lines · Christoffer Dall
Quoted 11 lines · Anup Patel
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_2feature when doing VCPU init usingKVM_ARM_VCPU_INITioctl.
Quoted 8 lines
Quoted 2 lines
Signed-off-by Anup Patel <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>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.harch/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
Quoted 4 lines
Thanks,
-Christoffer
PATCH v5 2/11 ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
Quoted 16 lines · Anup Patel
Quoted 15 lines · Christoffer Dall
Quoted 13 lines · Anup Patel
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_2feature when doing VCPU init usingKVM_ARM_VCPU_INITioctl.Signed-off-by Anup Patel <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>
Quoted 7 lines
Quoted 5 lines
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.
Quoted 4 lines
My suggestion would be to have:
arch/arm/include/uapi/asm/psci.harch/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?
PATCH v5 2/11 ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
Quoted 28 lines · Christoffer Dall
Quoted 16 lines · Anup Patel
Quoted 15 lines · Christoffer Dall
Quoted 13 lines · Anup Patel
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_2feature when doing VCPU init usingKVM_ARM_VCPU_INITioctl.Signed-off-by Anup Patel <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>Quoted 7 lines
Quoted 5 lines
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.
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
My suggestion would be to have:
arch/arm/include/uapi/asm/psci.harch/arm64/include/uapi/asm/psci.hI think the suggestion was to move all this to
include/uapi/linux/psci.hor 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
PATCH v5 2/11 ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
Hello,
Quoted 5 lines · Rob Herring
Quoted 5 lines
Quoted 4 lines
My suggestion would be to have:
arch/arm/include/uapi/asm/psci.harch/arm64/include/uapi/asm/psci.h
Quoted 8 lines
Quoted 3 lines
I think the suggestion was to move all this to
include/uapi/linux/psci.hor 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(orinclude/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
PATCH v5 2/11 ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
Quoted 17 lines · Ashwin Chaugule
Hello,
Quoted 5 lines · Rob Herring
Quoted 5 lines
Quoted 4 lines
My suggestion would be to have:
arch/arm/include/uapi/asm/psci.harch/arm64/include/uapi/asm/psci.hQuoted 8 lines
Quoted 3 lines
I think the suggestion was to move all this to
include/uapi/linux/psci.hor 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(orinclude/uapi/linux).
Quoted 5 lines
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/.
Quoted 2 lines
Alternately, is
drivers/psci.ca more suitable place? In this case, at least one function will be guarded byCONFIG_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
PATCH v5 3/11 KVM: Documentation: Add info regarding KVM_ARM_VCPU_PSCI_0_2 feature
In reply to Anup PatelWe 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.
--- Documentation/virtual/kvm/api.txt | 2 ++ 1 file changed, 2 insertions(+)
Documentation/virtual/kvm/api.txt +2 -0
@@ -2361,6 +2361,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
Signature · 1 line
1.7.9.5
PATCH v5 4/11 ARM/ARM64: KVM: Make kvm_psci_call() return convention more flexible
In reply to Anup PatelCurrently, 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)
--- 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(-)
arch/arm/include/asm/kvm_psci.h +1 -1
@@ -22,6 +22,6 @@#define KVM_ARM_PSCI_0_2 2int 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__ */
arch/arm/kvm/handle_exit.c +7 -3
@@ -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)
arch/arm/kvm/psci.c +16 -12
@@ -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 ; }; }
arch/arm64/include/asm/kvm_psci.h +1 -1
@@ -22,6 +22,6 @@#define KVM_ARM_PSCI_0_2 2int 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__ */
arch/arm64/kvm/handle_exit.c +7 -3
@@ -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)
Signature · 1 line
1.7.9.5
PATCH v5 5/11 KVM: Add KVM_EXIT_SYSTEM_EVENT to user space API header
In reply to Anup PatelCurrently, 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.
--- Documentation/virtual/kvm/api.txt | 15 +++++++++++++++ include/uapi/linux/kvm.h | 8 ++++++++ 2 files changed, 23 insertions(+)
Documentation/virtual/kvm/api.txt +15 -0
@@ -2721,6 +2721,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]; };
include/uapi/linux/kvm.h +8 -0
@@ -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 ]; };
Signature · 1 line
1.7.9.5
PATCH v5 6/11 ARM/ARM64: KVM: Emulate PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET
In reply to Anup PatelThe 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.
--- arch/arm/kvm/psci.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-)
arch/arm/kvm/psci.c +29 -3
@@ -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)
Signature · 1 line
1.7.9.5
PATCH v5 7/11 ARM/ARM64: KVM: Emulate PSCI v0.2 AFFINITY_INFO
In reply to Anup PatelThis 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.
--- arch/arm/kvm/psci.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-)
arch/arm/kvm/psci.c +65 -2
@@ -27,6 +27,31 @@* as described in ARM document number ARM DEN 0022A. */ +static unsigned long psci_affinity_mask (unsigned long affinity_level) +{ +unsigned long affinity_mask =MPIDR_HWID_BITMASK ; + +switch (affinity_level) { +case 0 :/* All affinity levels are valid */ + affinity_mask &= ~0x0UL ; +break ; +case 1 :/* Aff0 ignored */ + affinity_mask &= ~0xFFUL ; +break ; +case 2 :/* Aff0 and Aff1 ignored */ + affinity_mask &= ~0xFFFFUL ; +break ; +case 3 :/* Aff0, Aff1, and Aff2 ignored */ + affinity_mask &= ~0xFFFFFFUL ; +break ; +default : + affinity_mask =0 ; +break ; + }; + +return affinity_mask; +} +static void kvm_psci_vcpu_off (struct kvm_vcpu *vcpu) { vcpu->arch.pause = true;
@@ -85,6 +110,42 @@ 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 =psci_affinity_mask (lowest_affinity_level); +if (!target_affinity_mask) +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 +193,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 +208,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 ;
Signature · 1 line
1.7.9.5
PATCH v5 8/11 ARM/ARM64: KVM: Emulate PSCI v0.2 MIGRATE_INFO_TYPE and related functions
In reply to Anup PatelThis 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"
--- arch/arm/kvm/psci.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
arch/arm/kvm/psci.c +15 -5
@@ -197,6 +197,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 ;
@@ -208,12 +223,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 :
Signature · 1 line
1.7.9.5
PATCH v5 9/11 ARM/ARM64: KVM: Fix CPU_ON emulation for PSCI v0.2
In reply to Anup PatelAs-per PSCI v0.2, the source CPU provides physical address of "entry point" and "context id" for starting a target CPU. Also, if target CPU is already running then we should return ALREADY_ON.
Current emulation of CPU_ON function does not consider physical address of "context id" and returns INVALID_PARAMETERS if target CPU is already running.
This patch updates kvm_psci_vcpu_on() such that it works for both PSCI v0.1 and PSCI v0.2.
--- arch/arm/kvm/psci.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
arch/arm/kvm/psci.c +11 -1
@@ -63,6 +63,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)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;
@@ -83,10 +84,17 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)* Make sure the caller requested a valid CPU and that the CPU is * turned off. */ -if (!vcpu || !vcpu->arch.pause) +if (!vcpu)return KVM_PSCI_RET_INVAL ; +if (!vcpu->arch.pause) { +if (kvm_psci_version (source_vcpu) !=KVM_ARM_PSCI_0_1 ) +return KVM_PSCI_RET_ALREADY_ON ; +else +return KVM_PSCI_RET_INVAL ; + } target_pc = *vcpu_reg (source_vcpu,2 ); + context_id = *vcpu_reg (source_vcpu,3 );kvm_reset_vcpu (vcpu);
@@ -101,6 +109,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)kvm_vcpu_set_be (vcpu); *vcpu_pc (vcpu) = target_pc; +if (kvm_psci_version (source_vcpu) !=KVM_ARM_PSCI_0_1 ) + *vcpu_reg (vcpu,0 ) = context_id; vcpu->arch.pause = false;smp_mb ();/* Make sure the above is visible */
Signature · 1 line
1.7.9.5
PATCH v5 9/11 ARM/ARM64: KVM: Fix CPU_ON emulation for PSCI v0.2
Quoted 60 lines · Anup Patel
As-per PSCI v0.2, the source CPU provides physical address of "entry point" and "context id" for starting a target CPU. Also, if target CPU is already running then we should return
ALREADY_ON.Current emulation of
CPU_ONfunction does not consider physical address of "context id" and returnsINVALID_PARAMETERSif target CPU is already running.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 <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>--- arch/arm/kvm/psci.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)arch/arm/kvm/psci.c +11
-1@@ -63,6 +63,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)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;@@ -83,10 +84,17 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)* Make sure the caller requested a valid CPU and that the CPU is * turned off. */ -if (!vcpu || !vcpu->arch.pause) +if (!vcpu)return KVM_PSCI_RET_INVAL ; +if (!vcpu->arch.pause) { +if (kvm_psci_version (source_vcpu) !=KVM_ARM_PSCI_0_1 ) +return KVM_PSCI_RET_ALREADY_ON ; +else +return KVM_PSCI_RET_INVAL ; + } target_pc = *vcpu_reg (source_vcpu,2 ); + context_id = *vcpu_reg (source_vcpu,3 );kvm_reset_vcpu (vcpu);@@ -101,6 +109,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)kvm_vcpu_set_be (vcpu); *vcpu_pc (vcpu) = target_pc; +if (kvm_psci_version (source_vcpu) !=KVM_ARM_PSCI_0_1 ) + *vcpu_reg (vcpu,0 ) = context_id; vcpu->arch.pause = false;smp_mb ();/* Make sure the above is visible */ Signature · 1 line
1.7.9.5
PATCH v5 10/11 ARM/ARM64: KVM: Emulate PSCI v0.2 CPU_SUSPEND
In reply to Anup PatelThis patch adds emulation of PSCI v0.2 CPU_SUSPEND function call for KVM ARM/ARM64. This is a CPU-level function call which can suspend current CPU or current CPU cluster. We don't have VCPU clusters in KVM so for KVM we simply suspend the current VCPU.
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 current VCPU and to wakeup a suspended VCPU we need to explicity call PSCI CPU_ON from Guest.
--- arch/arm/kvm/psci.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)
arch/arm/kvm/psci.c +20 -4
@@ -52,6 +52,22 @@ static unsigned long psci_affinity_mask(unsigned long affinity_level)return affinity_mask; } +static unsigned long kvm_psci_vcpu_suspend (struct kvm_vcpu *vcpu) +{ +/* +* NOTE: Currently, we don't have any wakeup events for KVM +* hence VCPU suspend turns-out to be same as VCPU off request. +* This means to suspend a VCPU we simply set the pause flag +* and update VCPU registers as-per wakeup parameters provided +* via r2 & r3 (or x2 & x3). +*/ + vcpu->arch.pause = true; + *vcpu_pc (vcpu) = *vcpu_reg (vcpu,2 ); + *vcpu_reg (vcpu,0 ) = *vcpu_reg (vcpu,3 ); + +return KVM_PSCI_RET_SUCCESS ; +} +static void kvm_psci_vcpu_off (struct kvm_vcpu *vcpu) { vcpu->arch.pause = true;
@@ -195,6 +211,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 ;
@@ -232,10 +252,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 ; }
Signature · 1 line
1.7.9.5
PATCH v5 10/11 ARM/ARM64: KVM: Emulate PSCI v0.2 CPU_SUSPEND
Quoted 36 lines · Anup Patel
This patch adds emulation of PSCI v0.2
CPU_SUSPENDfunction call for KVM ARM/ARM64. This is a CPU-level function call which can suspend current CPU or current CPU cluster. We don't have VCPU clusters in KVM so for KVM we simply suspend the current VCPU.The
CPU_SUSPENDemulation is not tested much because currently there is no CPUIDLE driver in Linux kernel that uses PSCICPU_SUSPEND. The PSCICPU_SUSPENDimplementation 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_SUSPENDthen still we need to define SUSPEND states for KVM ARM/ARM64.Due to this, the
CPU_SUSPENDemulation added by this patch only pause current VCPU and to wakeup a suspended VCPU we need to explicity call PSCICPU_ONfrom Guest.Signed-off-by Anup Patel <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>--- arch/arm/kvm/psci.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)arch/arm/kvm/psci.c +2
-0@@ -52,6 +52,22 @@ static unsigned long psci_affinity_mask(unsigned long affinity_level)return affinity_mask; } +static unsigned long kvm_psci_vcpu_suspend (struct kvm_vcpu *vcpu) +{
arch/arm/kvm/psci.c static unsigned long psci_affinity_mask(unsigned long affinity_level) · line 66
Quoted 10 lines
arch/arm/kvm/psci.c +10
-0+/* +* NOTE: Currently, we don't have any wakeup events for KVM +* hence VCPU suspend turns-out to be same as VCPU off request. +* This means to suspend a VCPU we simply set the pause flag +* and update VCPU registers as-per wakeup parameters provided +* via r2 & r3 (or x2 & x3). +*/ + vcpu->arch.pause = true; + *vcpu_pc (vcpu) = *vcpu_reg (vcpu,2 ); + *vcpu_reg (vcpu,0 ) = *vcpu_reg (vcpu,3 );
But the spec states in Section 5.1.2 that if Bit[16] StateType == 0, then the entry point and context_id parameters are ignored, because all state is retained for a standby state.
I think Mark Rutland commented that KVM should define at last interrupts to the CPU as a wakeup event.
Quoted 32 lines
arch/arm/kvm/psci.c +8
-4+ +return KVM_PSCI_RET_SUCCESS ; +} +static void kvm_psci_vcpu_off (struct kvm_vcpu *vcpu) { vcpu->arch.pause = true;@@ -195,6 +211,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 ;@@ -232,10 +252,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 ; }Signature · 1 line
1.7.9.5
Thanks,
-Christoffer
PATCH v5 10/11 ARM/ARM64: KVM: Emulate PSCI v0.2 CPU_SUSPEND
Quoted 35 lines · Christoffer Dall
Quoted 34 lines · Anup Patel
This patch adds emulation of PSCI v0.2
CPU_SUSPENDfunction call for KVM ARM/ARM64. This is a CPU-level function call which can suspend current CPU or current CPU cluster. We don't have VCPU clusters in KVM so for KVM we simply suspend the current VCPU.The
CPU_SUSPENDemulation is not tested much because currently there is no CPUIDLE driver in Linux kernel that uses PSCICPU_SUSPEND. The PSCICPU_SUSPENDimplementation 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_SUSPENDthen still we need to define SUSPEND states for KVM ARM/ARM64.Due to this, the
CPU_SUSPENDemulation added by this patch only pause current VCPU and to wakeup a suspended VCPU we need to explicity call PSCICPU_ONfrom Guest.Signed-off-by Anup Patel <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>--- arch/arm/kvm/psci.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)arch/arm/kvm/psci.c +0
-0@@ -52,6 +52,22 @@ static unsigned long psci_affinity_mask(unsigned long affinity_level)return affinity_mask; }
Quoted 16 lines
arch/arm/kvm/psci.c static unsigned long psci_affinity_mask(unsigned long affinity_level) · line 66
Quoted 12 lines
arch/arm/kvm/psci.c +12
-0+static unsigned long kvm_psci_vcpu_suspend (struct kvm_vcpu *vcpu) +{ +/* +* NOTE: Currently, we don't have any wakeup events for KVM +* hence VCPU suspend turns-out to be same as VCPU off request. +* This means to suspend a VCPU we simply set the pause flag +* and update VCPU registers as-per wakeup parameters provided +* via r2 & r3 (or x2 & x3). +*/ + vcpu->arch.pause = true; + *vcpu_pc (vcpu) = *vcpu_reg (vcpu,2 ); + *vcpu_reg (vcpu,0 ) = *vcpu_reg (vcpu,3 );But the spec states in Section 5.1.2 that if Bit[16] StateType == 0, then the entry point and
context_idparameters are ignored, because all state is retained for a standby state.
OK, I will update this accordingly.
Quoted 3 lines
I think Mark Rutland commented that KVM should define at last interrupts to the CPU as a wakeup event.
How about using kvm_vcpu_block(vcpu) instead of "vcpu->arch.pause = true"?
This will make CPU_SUSPEND emulation very similar to WFI emulation.
Regards,
Anup
Quoted 37 lines
Quoted 31 lines
arch/arm/kvm/psci.c +8
-5+ +return KVM_PSCI_RET_SUCCESS ; +} +static void kvm_psci_vcpu_off (struct kvm_vcpu *vcpu) { vcpu->arch.pause = true;@@ -195,6 +211,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 ;@@ -232,10 +252,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 ; } --Quoted 2 lines
1.7.9.5
Thanks,
-Christoffer
PATCH v5 10/11 ARM/ARM64: KVM: Emulate PSCI v0.2 CPU_SUSPEND
Quoted 53 lines · Anup Patel
Quoted 35 lines · Christoffer Dall
Quoted 34 lines · Anup Patel
This patch adds emulation of PSCI v0.2
CPU_SUSPENDfunction call for KVM ARM/ARM64. This is a CPU-level function call which can suspend current CPU or current CPU cluster. We don't have VCPU clusters in KVM so for KVM we simply suspend the current VCPU.The
CPU_SUSPENDemulation is not tested much because currently there is no CPUIDLE driver in Linux kernel that uses PSCICPU_SUSPEND. The PSCICPU_SUSPENDimplementation 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_SUSPENDthen still we need to define SUSPEND states for KVM ARM/ARM64.Due to this, the
CPU_SUSPENDemulation added by this patch only pause current VCPU and to wakeup a suspended VCPU we need to explicity call PSCICPU_ONfrom Guest.Signed-off-by Anup Patel <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>--- arch/arm/kvm/psci.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)arch/arm/kvm/psci.c +0
-0@@ -52,6 +52,22 @@ static unsigned long psci_affinity_mask(unsigned long affinity_level)return affinity_mask; }Quoted 16 lines
arch/arm/kvm/psci.c static unsigned long psci_affinity_mask(unsigned long affinity_level) · line 66
Quoted 12 lines
arch/arm/kvm/psci.c +12
-0+static unsigned long kvm_psci_vcpu_suspend (struct kvm_vcpu *vcpu) +{ +/* +* NOTE: Currently, we don't have any wakeup events for KVM +* hence VCPU suspend turns-out to be same as VCPU off request. +* This means to suspend a VCPU we simply set the pause flag +* and update VCPU registers as-per wakeup parameters provided +* via r2 & r3 (or x2 & x3). +*/ + vcpu->arch.pause = true; + *vcpu_pc (vcpu) = *vcpu_reg (vcpu,2 ); + *vcpu_reg (vcpu,0 ) = *vcpu_reg (vcpu,3 );But the spec states in Section 5.1.2 that if Bit[16] StateType == 0, then the entry point and
context_idparameters are ignored, because all state is retained for a standby state.
Quoted 7 lines
OK, I will update this accordingly.
Quoted 3 lines
I think Mark Rutland commented that KVM should define at last interrupts to the CPU as a wakeup event.
How about using
kvm_vcpu_block(vcpu)instead of "vcpu->arch.pause= true"?
You mean if StateType==0 only, or will you always force a shutdown event to be handled as a suspend event (I believe the spec allows for you to do so)? If you are going down this path, please document that clearly somewhere.
I definitely want to see us using something like kvm_vcpu_block(vcpu) for suspend requests, but the thing with kvm_vcpu_block() is that a regular signal to the VCPU thread wakes up that VCPU, which I think we agreed was fine for the WFI implementation, as it should handle spurious interrupts as wake up events (which is also how we handle the fact that any VCPUs in WFI will be woken up when migrated).
But for PSCI CPU_SUSPEND, I'm not sure if that's still a valid assumption. Anyone?
Quoted 3 lines
This will make
CPU_SUSPENDemulation very similar to WFI emulation.
Yes, I think the PSCI docs suggest this should be the behavior as well.
Thanks,
-Christoffer
PATCH v5 11/11 ARM/ARM64: KVM: Advertise KVM_CAP_ARM_PSCI_0_2 to user space
In reply to Anup PatelWe have PSCI v0.2 emulation available in KVM ARM/ARM64 hence advertise this to user space (i.e. QEMU or KVMTOOL) via KVM_CHECK_EXTENSION ioctl.
--- arch/arm/kvm/arm.c | 1 + 1 file changed, 1 insertion(+)
arch/arm/kvm/arm.c +1 -0
@@ -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 :
Signature · 1 line
1.7.9.5
PATCH v5 11/11 ARM/ARM64: KVM: Advertise KVM_CAP_ARM_PSCI_0_2 to user space
Quoted 25 lines · Anup Patel
We have PSCI v0.2 emulation available in KVM ARM/ARM64 hence advertise this to user space (i.e. QEMU or KVMTOOL) via
KVM_CHECK_EXTENSIONioctl.Signed-off-by Anup Patel <[email protected]>Signed-off-by Pranavkumar Sawargaonkar <[email protected]>--- arch/arm/kvm/arm.c | 1 + 1 file changed, 1 insertion(+)arch/arm/kvm/arm.c +1
-0@@ -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 :Signature · 1 line
1.7.9.5