Skip to content

Commit 56019f9

Browse files
Pierre Morelborntraeger
authored andcommitted
KVM: s390: vsie: Allow CRYCB FORMAT-2
When the guest and the host both use CRYCB FORMAT-2, we copy the guest's FORMAT-1 APCB to a FORMAT-1 shadow APCB. This patch also cleans up the shadow_crycb() function. Signed-off-by: Pierre Morel <pmorel@linux.ibm.com> Signed-off-by: Tony Krowiak <akrowiak@linux.ibm.com> Message-Id: <20180925231641.4954-19-akrowiak@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
1 parent 3af84de commit 56019f9

File tree

1 file changed

+104
-10
lines changed

1 file changed

+104
-10
lines changed

arch/s390/kvm/vsie.c

Lines changed: 104 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,81 @@ static int prepare_cpuflags(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
136136
return 0;
137137
}
138138

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+
*
140202
* Create a shadow copy of the crycb block and setup key wrapping, if
141203
* requested for guest 3 and enabled for guest 2.
142204
*
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.
145209
* There is nothing to do for format-0.
146210
*
211+
* This function centralize the issuing of set_validity_icpt() for all
212+
* the subfunctions working on the crycb.
213+
*
147214
* Returns: - 0 if shadowed or nothing to do
148215
* - > 0 if control has to be given to guest 2
149216
*/
@@ -155,39 +222,66 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
155222
const u32 crycb_addr = crycbd_o & 0x7ffffff8U;
156223
unsigned long *b1, *b2;
157224
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;
158230

159231
scb_s->crycbd = 0;
160232
if (!(crycbd_o & vcpu->arch.sie_block->crycbd & CRYCB_FORMAT1))
161233
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)
164237
return 0;
165238

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)
169240
return set_validity_icpt(scb_s, 0x0039U);
170241

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+
171256
/* we may only allow it if enabled for guest 2 */
172257
ecb3_flags = scb_o->ecb3 & vcpu->arch.sie_block->ecb3 &
173258
(ECB3_AES | ECB3_DEA);
174259
if (!ecb3_flags)
175-
return 0;
260+
goto end;
176261

177262
/* copy only the wrapping keys */
178263
if (read_guest_real(vcpu, crycb_addr + 72,
179264
vsie_page->crycb.dea_wrapping_key_mask, 56))
180265
return set_validity_icpt(scb_s, 0x0035U);
181266

182267
scb_s->ecb3 |= ecb3_flags;
183-
scb_s->crycbd = ((__u32)(__u64) &vsie_page->crycb) | CRYCB_FORMAT2;
184268

185269
/* xor both blocks in one run */
186270
b1 = (unsigned long *) vsie_page->crycb.dea_wrapping_key_mask;
187271
b2 = (unsigned long *)
188272
vcpu->kvm->arch.crypto.crycb->dea_wrapping_key_mask;
189273
/* as 56%8 == 0, bitmap_xor won't overwrite any data */
190274
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;
191285
return 0;
192286
}
193287

0 commit comments

Comments
 (0)