@@ -322,7 +322,8 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
322
322
u8 type , void * req_buf , size_t req_sz , void * resp_buf ,
323
323
u32 resp_sz , __u64 * fw_err )
324
324
{
325
- unsigned long err ;
325
+ unsigned long err , override_err = 0 ;
326
+ unsigned int override_npages = 0 ;
326
327
u64 seqno ;
327
328
int rc ;
328
329
@@ -338,6 +339,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
338
339
if (rc )
339
340
return rc ;
340
341
342
+ retry_request :
341
343
/*
342
344
* Call firmware to process the request. In this function the encrypted
343
345
* message enters shared memory with the host. So after this call the
@@ -346,17 +348,24 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
346
348
*/
347
349
rc = snp_issue_guest_request (exit_code , & snp_dev -> input , & err );
348
350
349
- /*
350
- * If the extended guest request fails due to having too small of a
351
- * certificate data buffer, retry the same guest request without the
352
- * extended data request in order to increment the sequence number
353
- * and thus avoid IV reuse.
354
- */
355
- if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST &&
356
- err == SNP_GUEST_REQ_INVALID_LEN ) {
357
- const unsigned int certs_npages = snp_dev -> input .data_npages ;
351
+ switch (rc ) {
352
+ case - ENOSPC :
353
+ /*
354
+ * If the extended guest request fails due to having too
355
+ * small of a certificate data buffer, retry the same
356
+ * guest request without the extended data request in
357
+ * order to increment the sequence number and thus avoid
358
+ * IV reuse.
359
+ */
360
+ override_npages = snp_dev -> input .data_npages ;
361
+ exit_code = SVM_VMGEXIT_GUEST_REQUEST ;
358
362
359
- exit_code = SVM_VMGEXIT_GUEST_REQUEST ;
363
+ /*
364
+ * Override the error to inform callers the given extended
365
+ * request buffer size was too small and give the caller the
366
+ * required buffer size.
367
+ */
368
+ override_err = SNP_GUEST_REQ_INVALID_LEN ;
360
369
361
370
/*
362
371
* If this call to the firmware succeeds, the sequence number can
@@ -366,15 +375,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
366
375
* of the VMPCK and the error code being propagated back to the
367
376
* user as an ioctl() return code.
368
377
*/
369
- rc = snp_issue_guest_request (exit_code , & snp_dev -> input , & err );
370
-
371
- /*
372
- * Override the error to inform callers the given extended
373
- * request buffer size was too small and give the caller the
374
- * required buffer size.
375
- */
376
- err = SNP_GUEST_REQ_INVALID_LEN ;
377
- snp_dev -> input .data_npages = certs_npages ;
378
+ goto retry_request ;
378
379
}
379
380
380
381
/*
@@ -386,15 +387,18 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
386
387
snp_inc_msg_seqno (snp_dev );
387
388
388
389
if (fw_err )
389
- * fw_err = err ;
390
+ * fw_err = override_err ?: err ;
391
+
392
+ if (override_npages )
393
+ snp_dev -> input .data_npages = override_npages ;
390
394
391
395
/*
392
396
* If an extended guest request was issued and the supplied certificate
393
397
* buffer was not large enough, a standard guest request was issued to
394
398
* prevent IV reuse. If the standard request was successful, return -EIO
395
399
* back to the caller as would have originally been returned.
396
400
*/
397
- if (!rc && err == SNP_GUEST_REQ_INVALID_LEN )
401
+ if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN )
398
402
return - EIO ;
399
403
400
404
if (rc ) {
0 commit comments