aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@linaro.org>2014-04-29 01:54:16 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2014-04-30 07:18:57 -0400
commit7d0f84aae9e231930985eaff63ac91b61aaa15d6 (patch)
treeb034732021a3b095fd39139f3205ddfe299b7c2f /arch/arm
parente546eea74ec66698e29c583639cf6e2a11e46490 (diff)
ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
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> Acked-by: Christoffer Dall <christoffer.dall@linaro.org> Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/include/asm/kvm_host.h2
-rw-r--r--arch/arm/include/asm/kvm_psci.h4
-rw-r--r--arch/arm/include/uapi/asm/kvm.h10
-rw-r--r--arch/arm/kvm/psci.c93
4 files changed, 88 insertions, 21 deletions
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 09af14999c9b..193ceaf01bfd 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -36,7 +36,7 @@
36#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 36#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
37#define KVM_HAVE_ONE_REG 37#define KVM_HAVE_ONE_REG
38 38
39#define KVM_VCPU_MAX_FEATURES 1 39#define KVM_VCPU_MAX_FEATURES 2
40 40
41#include <kvm/arm_vgic.h> 41#include <kvm/arm_vgic.h>
42 42
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
index 9a83d98bf170..4c0e3e1d1597 100644
--- a/arch/arm/include/asm/kvm_psci.h
+++ b/arch/arm/include/asm/kvm_psci.h
@@ -18,6 +18,10 @@
18#ifndef __ARM_KVM_PSCI_H__ 18#ifndef __ARM_KVM_PSCI_H__
19#define __ARM_KVM_PSCI_H__ 19#define __ARM_KVM_PSCI_H__
20 20
21#define KVM_ARM_PSCI_0_1 1
22#define KVM_ARM_PSCI_0_2 2
23
24int kvm_psci_version(struct kvm_vcpu *vcpu);
21bool kvm_psci_call(struct kvm_vcpu *vcpu); 25bool kvm_psci_call(struct kvm_vcpu *vcpu);
22 26
23#endif /* __ARM_KVM_PSCI_H__ */ 27#endif /* __ARM_KVM_PSCI_H__ */
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index ef0c8785ba16..e6ebdd3471e5 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -20,6 +20,7 @@
20#define __ARM_KVM_H__ 20#define __ARM_KVM_H__
21 21
22#include <linux/types.h> 22#include <linux/types.h>
23#include <linux/psci.h>
23#include <asm/ptrace.h> 24#include <asm/ptrace.h>
24 25
25#define __KVM_HAVE_GUEST_DEBUG 26#define __KVM_HAVE_GUEST_DEBUG
@@ -83,6 +84,7 @@ struct kvm_regs {
83#define KVM_VGIC_V2_CPU_SIZE 0x2000 84#define KVM_VGIC_V2_CPU_SIZE 0x2000
84 85
85#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ 86#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
87#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
86 88
87struct kvm_vcpu_init { 89struct kvm_vcpu_init {
88 __u32 target; 90 __u32 target;
@@ -201,9 +203,9 @@ struct kvm_arch_memory_slot {
201#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) 203#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2)
202#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3) 204#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
203 205
204#define KVM_PSCI_RET_SUCCESS 0 206#define KVM_PSCI_RET_SUCCESS PSCI_RET_SUCCESS
205#define KVM_PSCI_RET_NI ((unsigned long)-1) 207#define KVM_PSCI_RET_NI PSCI_RET_NOT_SUPPORTED
206#define KVM_PSCI_RET_INVAL ((unsigned long)-2) 208#define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS
207#define KVM_PSCI_RET_DENIED ((unsigned long)-3) 209#define KVM_PSCI_RET_DENIED PSCI_RET_DENIED
208 210
209#endif /* __ARM_KVM_H__ */ 211#endif /* __ARM_KVM_H__ */
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 448f60e8d23c..8c42596cdbdf 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -59,7 +59,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
59 * turned off. 59 * turned off.
60 */ 60 */
61 if (!vcpu || !vcpu->arch.pause) 61 if (!vcpu || !vcpu->arch.pause)
62 return KVM_PSCI_RET_INVAL; 62 return PSCI_RET_INVALID_PARAMS;
63 63
64 target_pc = *vcpu_reg(source_vcpu, 2); 64 target_pc = *vcpu_reg(source_vcpu, 2);
65 65
@@ -82,20 +82,60 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
82 wq = kvm_arch_vcpu_wq(vcpu); 82 wq = kvm_arch_vcpu_wq(vcpu);
83 wake_up_interruptible(wq); 83 wake_up_interruptible(wq);
84 84
85 return KVM_PSCI_RET_SUCCESS; 85 return PSCI_RET_SUCCESS;
86} 86}
87 87
88/** 88int kvm_psci_version(struct kvm_vcpu *vcpu)
89 * kvm_psci_call - handle PSCI call if r0 value is in range 89{
90 * @vcpu: Pointer to the VCPU struct 90 if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
91 * 91 return KVM_ARM_PSCI_0_2;
92 * Handle PSCI calls from guests through traps from HVC instructions. 92
93 * The calling convention is similar to SMC calls to the secure world where 93 return KVM_ARM_PSCI_0_1;
94 * the function number is placed in r0 and this function returns true if the 94}
95 * function number specified in r0 is withing the PSCI range, and false 95
96 * otherwise. 96static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
97 */ 97{
98bool kvm_psci_call(struct kvm_vcpu *vcpu) 98 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
99 unsigned long val;
100
101 switch (psci_fn) {
102 case PSCI_0_2_FN_PSCI_VERSION:
103 /*
104 * Bits[31:16] = Major Version = 0
105 * Bits[15:0] = Minor Version = 2
106 */
107 val = 2;
108 break;
109 case PSCI_0_2_FN_CPU_OFF:
110 kvm_psci_vcpu_off(vcpu);
111 val = PSCI_RET_SUCCESS;
112 break;
113 case PSCI_0_2_FN_CPU_ON:
114 case PSCI_0_2_FN64_CPU_ON:
115 val = kvm_psci_vcpu_on(vcpu);
116 break;
117 case PSCI_0_2_FN_CPU_SUSPEND:
118 case PSCI_0_2_FN_AFFINITY_INFO:
119 case PSCI_0_2_FN_MIGRATE:
120 case PSCI_0_2_FN_MIGRATE_INFO_TYPE:
121 case PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
122 case PSCI_0_2_FN_SYSTEM_OFF:
123 case PSCI_0_2_FN_SYSTEM_RESET:
124 case PSCI_0_2_FN64_CPU_SUSPEND:
125 case PSCI_0_2_FN64_AFFINITY_INFO:
126 case PSCI_0_2_FN64_MIGRATE:
127 case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
128 val = PSCI_RET_NOT_SUPPORTED;
129 break;
130 default:
131 return false;
132 }
133
134 *vcpu_reg(vcpu, 0) = val;
135 return true;
136}
137
138static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
99{ 139{
100 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); 140 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
101 unsigned long val; 141 unsigned long val;
@@ -103,16 +143,15 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
103 switch (psci_fn) { 143 switch (psci_fn) {
104 case KVM_PSCI_FN_CPU_OFF: 144 case KVM_PSCI_FN_CPU_OFF:
105 kvm_psci_vcpu_off(vcpu); 145 kvm_psci_vcpu_off(vcpu);
106 val = KVM_PSCI_RET_SUCCESS; 146 val = PSCI_RET_SUCCESS;
107 break; 147 break;
108 case KVM_PSCI_FN_CPU_ON: 148 case KVM_PSCI_FN_CPU_ON:
109 val = kvm_psci_vcpu_on(vcpu); 149 val = kvm_psci_vcpu_on(vcpu);
110 break; 150 break;
111 case KVM_PSCI_FN_CPU_SUSPEND: 151 case KVM_PSCI_FN_CPU_SUSPEND:
112 case KVM_PSCI_FN_MIGRATE: 152 case KVM_PSCI_FN_MIGRATE:
113 val = KVM_PSCI_RET_NI; 153 val = PSCI_RET_NOT_SUPPORTED;
114 break; 154 break;
115
116 default: 155 default:
117 return false; 156 return false;
118 } 157 }
@@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
120 *vcpu_reg(vcpu, 0) = val; 159 *vcpu_reg(vcpu, 0) = val;
121 return true; 160 return true;
122} 161}
162
163/**
164 * kvm_psci_call - handle PSCI call if r0 value is in range
165 * @vcpu: Pointer to the VCPU struct
166 *
167 * Handle PSCI calls from guests through traps from HVC instructions.
168 * The calling convention is similar to SMC calls to the secure world where
169 * the function number is placed in r0 and this function returns true if the
170 * function number specified in r0 is withing the PSCI range, and false
171 * otherwise.
172 */
173bool kvm_psci_call(struct kvm_vcpu *vcpu)
174{
175 switch (kvm_psci_version(vcpu)) {
176 case KVM_ARM_PSCI_0_2:
177 return kvm_psci_0_2_call(vcpu);
178 case KVM_ARM_PSCI_0_1:
179 return kvm_psci_0_1_call(vcpu);
180 default:
181 return false;
182 };
183}