History

KVM: SVM: Add support for KVM_SEV_RECEIVE_START command

The command is used to create the encryption context for an incoming SEV guest. The encryption context can be later used by the hypervisor to import the incoming data into the SEV guest memory space.

Brijesh Singh committed 5 years ago

Commit af43cbb1 parent 5569e2e3 files · +119 −0Browse files

Unified · Split

3 files
  1. Documentation/virt/kvm/amd-memory-encryption.rst +29 −0
  2. arch/x86/kvm/svm/sev.c +81 −0
  3. include/uapi/linux/kvm.h +9 −0
Documentation/virt/kvm/amd-memory-encryption.rst+29−0
@@ -365,6 +365,35 @@ migration can restart with a new target later. · 364 unmodified lines
365 365
366Returns: 0 on success, -negative on error366Returns: 0 on success, -negative on error
367 367
36815. KVM_SEV_RECEIVE_START
369------------------------
370
371The KVM_SEV_RECEIVE_START command is used for creating the memory encryption
372context for an incoming SEV guest. To create the encryption context, the user must
373provide a guest policy, the platform public Diffie-Hellman (PDH) key and session
374information.
375
376Parameters: struct kvm_sev_receive_start (in/out)
377
378Returns: 0 on success, -negative on error
379
380::
381
382 struct kvm_sev_receive_start {
383 __u32 handle; /* if zero then firmware creates a new handle */
384 __u32 policy; /* guest's policy */
385
386 __u64 pdh_uaddr; /* userspace address pointing to the PDH key */
387 __u32 pdh_len;
388
389 __u64 session_uaddr; /* userspace address which points to the guest session information */
390 __u32 session_len;
391 };
392
393On success, the 'handle' field contains a new handle and on error, a negative value.
394
395For more details, see SEV spec Section 6.12.
396
368References397References
369==========398==========
370 399
arch/x86/kvm/svm/sev.c+81−0
@@ -1397,6 +1397,84 @@ static int sev_send_cancel(struct kvm *kvm, struct kvm_sev_cmd *argp) · 1396 unmodified lines
1397 return ret;1397 return ret;
1398}1398}
1399 1399
1400static int sev_receive_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
1401{
1402 struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
1403 struct sev_data_receive_start *start;
1404 struct kvm_sev_receive_start params;
1405 int *error = &argp->error;
1406 void *session_data;
1407 void *pdh_data;
1408 int ret;
1409
1410 if (!sev_guest(kvm))
1411 return -ENOTTY;
1412
1413 /* Get parameter from the userspace */
1414 if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data,
1415 sizeof(struct kvm_sev_receive_start)))
1416 return -EFAULT;
1417
1418 /* some sanity checks */
1419 if (!params.pdh_uaddr || !params.pdh_len ||
1420 !params.session_uaddr || !params.session_len)
1421 return -EINVAL;
1422
1423 pdh_data = psp_copy_user_blob(params.pdh_uaddr, params.pdh_len);
1424 if (IS_ERR(pdh_data))
1425 return PTR_ERR(pdh_data);
1426
1427 session_data = psp_copy_user_blob(params.session_uaddr,
1428 params.session_len);
1429 if (IS_ERR(session_data)) {
1430 ret = PTR_ERR(session_data);
1431 goto e_free_pdh;
1432 }
1433
1434 ret = -ENOMEM;
1435 start = kzalloc(sizeof(*start), GFP_KERNEL);
1436 if (!start)
1437 goto e_free_session;
1438
1439 start->handle = params.handle;
1440 start->policy = params.policy;
1441 start->pdh_cert_address = __psp_pa(pdh_data);
1442 start->pdh_cert_len = params.pdh_len;
1443 start->session_address = __psp_pa(session_data);
1444 start->session_len = params.session_len;
1445
1446 /* create memory encryption context */
1447 ret = __sev_issue_cmd(argp->sev_fd, SEV_CMD_RECEIVE_START, start,
1448 error);
1449 if (ret)
1450 goto e_free;
1451
1452 /* Bind ASID to this guest */
1453 ret = sev_bind_asid(kvm, start->handle, error);
1454 if (ret)
1455 goto e_free;
1456
1457 params.handle = start->handle;
1458 if (copy_to_user((void __user *)(uintptr_t)argp->data,
1459 &params, sizeof(struct kvm_sev_receive_start))) {
1460 ret = -EFAULT;
1461 sev_unbind_asid(kvm, start->handle);
1462 goto e_free;
1463 }
1464
1465 sev->handle = start->handle;
1466 sev->fd = argp->sev_fd;
1467
1468e_free:
1469 kfree(start);
1470e_free_session:
1471 kfree(session_data);
1472e_free_pdh:
1473 kfree(pdh_data);
1474
1475 return ret;
1476}
1477
1400int svm_mem_enc_op(struct kvm *kvm, void __user *argp)1478int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
1401{1479{
1402 struct kvm_sev_cmd sev_cmd;1480 struct kvm_sev_cmd sev_cmd;
@@ -1471,6 +1549,9 @@ int svm_mem_enc_op(struct kvm *kvm, void __user *argp) · 68 unmodified lines
1471 case KVM_SEV_SEND_CANCEL:1549 case KVM_SEV_SEND_CANCEL:
1472 r = sev_send_cancel(kvm, &sev_cmd);1550 r = sev_send_cancel(kvm, &sev_cmd);
1473 break;1551 break;
1552 case KVM_SEV_RECEIVE_START:
1553 r = sev_receive_start(kvm, &sev_cmd);
1554 break;
1474 default:1555 default:
1475 r = -EINVAL;1556 r = -EINVAL;
1476 goto out;1557 goto out;
include/uapi/linux/kvm.h+9−0
@@ -1755,6 +1755,15 @@ struct kvm_sev_send_update_data { · 1754 unmodified lines
1755 __u32 trans_len;1755 __u32 trans_len;
1756};1756};
1757 1757
1758struct kvm_sev_receive_start {
1759 __u32 handle;
1760 __u32 policy;
1761 __u64 pdh_uaddr;
1762 __u32 pdh_len;
1763 __u64 session_uaddr;
1764 __u32 session_len;
1765};
1766
1758#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)1767#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
1759#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)1768#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
1760#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)1769#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)