@@ -136,14 +136,81 @@ static int prepare_cpuflags(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
136
136
return 0 ;
137
137
}
138
138
139
- /*
139
+ /**
140
+ * setup_apcb11 - Copy the FORMAT1 APCB from the guest to the shadow CRYCB
141
+ * @vcpu: pointer to the virtual CPU
142
+ * @apcb_s: pointer to start of apcb in the shadow crycb
143
+ * @apcb_o: pointer to start of original guest apcb
144
+ * @apcb_h: pointer to start of apcb in the host
145
+ *
146
+ * Returns 0 and -EFAULT on error reading guest apcb
147
+ */
148
+ static int setup_apcb11 (struct kvm_vcpu * vcpu , unsigned long * apcb_s ,
149
+ unsigned long apcb_o ,
150
+ unsigned long * apcb_h )
151
+ {
152
+ if (read_guest_real (vcpu , apcb_o , apcb_s ,
153
+ sizeof (struct kvm_s390_apcb1 )))
154
+ return - EFAULT ;
155
+
156
+ bitmap_and (apcb_s , apcb_s , apcb_h , sizeof (struct kvm_s390_apcb1 ));
157
+
158
+ return 0 ;
159
+ }
160
+
161
+ /**
162
+ * setup_apcb - Create a shadow copy of the apcb.
163
+ * @vcpu: pointer to the virtual CPU
164
+ * @crycb_s: pointer to shadow crycb
165
+ * @crycb_o: pointer to original guest crycb
166
+ * @crycb_h: pointer to the host crycb
167
+ * @fmt_o: format of the original guest crycb.
168
+ * @fmt_h: format of the host crycb.
169
+ *
170
+ * Checks the compatibility between the guest and host crycb and calls the
171
+ * appropriate copy function.
172
+ *
173
+ * Return 0 or an error number if the guest and host crycb are incompatible.
174
+ */
175
+ static int setup_apcb (struct kvm_vcpu * vcpu , struct kvm_s390_crypto_cb * crycb_s ,
176
+ const u32 crycb_o ,
177
+ struct kvm_s390_crypto_cb * crycb_h ,
178
+ int fmt_o , int fmt_h )
179
+ {
180
+ struct kvm_s390_crypto_cb * crycb ;
181
+
182
+ crycb = (struct kvm_s390_crypto_cb * ) (unsigned long )crycb_o ;
183
+
184
+ switch (fmt_o ) {
185
+ case CRYCB_FORMAT2 :
186
+ if ((crycb_o & PAGE_MASK ) != ((crycb_o + 256 ) & PAGE_MASK ))
187
+ return - EACCES ;
188
+ if (fmt_h != CRYCB_FORMAT2 )
189
+ return - EINVAL ;
190
+ return setup_apcb11 (vcpu , (unsigned long * )& crycb_s -> apcb1 ,
191
+ (unsigned long ) & crycb -> apcb1 ,
192
+ (unsigned long * )& crycb_h -> apcb1 );
193
+ }
194
+ return - EINVAL ;
195
+ }
196
+
197
+ /**
198
+ * shadow_crycb - Create a shadow copy of the crycb block
199
+ * @vcpu: a pointer to the virtual CPU
200
+ * @vsie_page: a pointer to internal date used for the vSIE
201
+ *
140
202
* Create a shadow copy of the crycb block and setup key wrapping, if
141
203
* requested for guest 3 and enabled for guest 2.
142
204
*
143
- * We accept format-1 or format-2, but we treat it as a format-1 (no AP in g2),
144
- * and we convert it into format-2 in the shadow CRYCB.
205
+ * We accept format-1 or format-2, but we convert format-1 into format-2
206
+ * in the shadow CRYCB.
207
+ * Using format-2 enables the firmware to choose the right format when
208
+ * scheduling the SIE.
145
209
* There is nothing to do for format-0.
146
210
*
211
+ * This function centralize the issuing of set_validity_icpt() for all
212
+ * the subfunctions working on the crycb.
213
+ *
147
214
* Returns: - 0 if shadowed or nothing to do
148
215
* - > 0 if control has to be given to guest 2
149
216
*/
@@ -155,39 +222,66 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
155
222
const u32 crycb_addr = crycbd_o & 0x7ffffff8U ;
156
223
unsigned long * b1 , * b2 ;
157
224
u8 ecb3_flags ;
225
+ int apie_h ;
226
+ int key_msk = test_kvm_facility (vcpu -> kvm , 76 );
227
+ int fmt_o = crycbd_o & CRYCB_FORMAT_MASK ;
228
+ int fmt_h = vcpu -> arch .sie_block -> crycbd & CRYCB_FORMAT_MASK ;
229
+ int ret = 0 ;
158
230
159
231
scb_s -> crycbd = 0 ;
160
232
if (!(crycbd_o & vcpu -> arch .sie_block -> crycbd & CRYCB_FORMAT1 ))
161
233
return 0 ;
162
- /* format-1 is supported with message-security-assist extension 3 */
163
- if (!test_kvm_facility (vcpu -> kvm , 76 ))
234
+
235
+ apie_h = vcpu -> arch .sie_block -> eca & ECA_APIE ;
236
+ if (!apie_h && !key_msk )
164
237
return 0 ;
165
238
166
- if ((crycb_addr & PAGE_MASK ) != ((crycb_addr + 128 ) & PAGE_MASK ))
167
- return set_validity_icpt (scb_s , 0x003CU );
168
- else if (!crycb_addr )
239
+ if (!crycb_addr )
169
240
return set_validity_icpt (scb_s , 0x0039U );
170
241
242
+ if (fmt_o == CRYCB_FORMAT1 )
243
+ if ((crycb_addr & PAGE_MASK ) !=
244
+ ((crycb_addr + 128 ) & PAGE_MASK ))
245
+ return set_validity_icpt (scb_s , 0x003CU );
246
+
247
+ if (apie_h && (scb_o -> eca & ECA_APIE )) {
248
+ ret = setup_apcb (vcpu , & vsie_page -> crycb , crycb_addr ,
249
+ vcpu -> kvm -> arch .crypto .crycb ,
250
+ fmt_o , fmt_h );
251
+ if (ret )
252
+ goto end ;
253
+ scb_s -> eca |= scb_o -> eca & ECA_APIE ;
254
+ }
255
+
171
256
/* we may only allow it if enabled for guest 2 */
172
257
ecb3_flags = scb_o -> ecb3 & vcpu -> arch .sie_block -> ecb3 &
173
258
(ECB3_AES | ECB3_DEA );
174
259
if (!ecb3_flags )
175
- return 0 ;
260
+ goto end ;
176
261
177
262
/* copy only the wrapping keys */
178
263
if (read_guest_real (vcpu , crycb_addr + 72 ,
179
264
vsie_page -> crycb .dea_wrapping_key_mask , 56 ))
180
265
return set_validity_icpt (scb_s , 0x0035U );
181
266
182
267
scb_s -> ecb3 |= ecb3_flags ;
183
- scb_s -> crycbd = ((__u32 )(__u64 ) & vsie_page -> crycb ) | CRYCB_FORMAT2 ;
184
268
185
269
/* xor both blocks in one run */
186
270
b1 = (unsigned long * ) vsie_page -> crycb .dea_wrapping_key_mask ;
187
271
b2 = (unsigned long * )
188
272
vcpu -> kvm -> arch .crypto .crycb -> dea_wrapping_key_mask ;
189
273
/* as 56%8 == 0, bitmap_xor won't overwrite any data */
190
274
bitmap_xor (b1 , b1 , b2 , BITS_PER_BYTE * 56 );
275
+ end :
276
+ switch (ret ) {
277
+ case - EINVAL :
278
+ return set_validity_icpt (scb_s , 0x0020U );
279
+ case - EFAULT :
280
+ return set_validity_icpt (scb_s , 0x0035U );
281
+ case - EACCES :
282
+ return set_validity_icpt (scb_s , 0x003CU );
283
+ }
284
+ scb_s -> crycbd = ((__u32 )(__u64 ) & vsie_page -> crycb ) | CRYCB_FORMAT2 ;
191
285
return 0 ;
192
286
}
193
287
0 commit comments