aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm
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/kvm
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/kvm')
-rw-r--r--arch/arm/kvm/psci.c93
1 files changed, 77 insertions, 16 deletions
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}