lkml.org 
[lkml]   [2021]   [Aug]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH Part2 v5 23/45] KVM: SVM: Add KVM_SNP_INIT command
    Date
    The KVM_SNP_INIT command is used by the hypervisor to initialize the
    SEV-SNP platform context. In a typical workflow, this command should be the
    first command issued. When creating SEV-SNP guest, the VMM must use this
    command instead of the KVM_SEV_INIT or KVM_SEV_ES_INIT.

    The flags value must be zero, it will be extended in future SNP support to
    communicate the optional features (such as restricted INT injection etc).

    Co-developed-by: Pavan Kumar Paluri <papaluri@amd.com>
    Signed-off-by: Pavan Kumar Paluri <papaluri@amd.com>
    Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
    ---
    .../virt/kvm/amd-memory-encryption.rst | 27 ++++++++++++
    arch/x86/include/asm/svm.h | 2 +
    arch/x86/kvm/svm/sev.c | 44 ++++++++++++++++++-
    arch/x86/kvm/svm/svm.h | 4 ++
    include/uapi/linux/kvm.h | 13 ++++++
    5 files changed, 88 insertions(+), 2 deletions(-)

    diff --git a/Documentation/virt/kvm/amd-memory-encryption.rst b/Documentation/virt/kvm/amd-memory-encryption.rst
    index 5c081c8c7164..7b1d32fb99a8 100644
    --- a/Documentation/virt/kvm/amd-memory-encryption.rst
    +++ b/Documentation/virt/kvm/amd-memory-encryption.rst
    @@ -427,6 +427,33 @@ issued by the hypervisor to make the guest ready for execution.

    Returns: 0 on success, -negative on error

    +18. KVM_SNP_INIT
    +----------------
    +
    +The KVM_SNP_INIT command can be used by the hypervisor to initialize SEV-SNP
    +context. In a typical workflow, this command should be the first command issued.
    +
    +Parameters (in/out): struct kvm_snp_init
    +
    +Returns: 0 on success, -negative on error
    +
    +::
    +
    + struct kvm_snp_init {
    + __u64 flags;
    + };
    +
    +The flags bitmap is defined as::
    +
    + /* enable the restricted injection */
    + #define KVM_SEV_SNP_RESTRICTED_INJET (1<<0)
    +
    + /* enable the restricted injection timer */
    + #define KVM_SEV_SNP_RESTRICTED_TIMER_INJET (1<<1)
    +
    +If the specified flags is not supported then return -EOPNOTSUPP, and the supported
    +flags are returned.
    +
    References
    ==========

    diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
    index 44a3f920f886..a39e31845a33 100644
    --- a/arch/x86/include/asm/svm.h
    +++ b/arch/x86/include/asm/svm.h
    @@ -218,6 +218,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
    #define SVM_NESTED_CTL_SEV_ENABLE BIT(1)
    #define SVM_NESTED_CTL_SEV_ES_ENABLE BIT(2)

    +#define SVM_SEV_FEAT_SNP_ACTIVE BIT(0)
    +
    struct vmcb_seg {
    u16 selector;
    u16 attrib;
    diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
    index 50fddbe56981..93da463545ef 100644
    --- a/arch/x86/kvm/svm/sev.c
    +++ b/arch/x86/kvm/svm/sev.c
    @@ -235,10 +235,30 @@ static void sev_unbind_asid(struct kvm *kvm, unsigned int handle)
    sev_decommission(handle);
    }

    +static int verify_snp_init_flags(struct kvm *kvm, struct kvm_sev_cmd *argp)
    +{
    + struct kvm_snp_init params;
    + int ret = 0;
    +
    + if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data, sizeof(params)))
    + return -EFAULT;
    +
    + if (params.flags & ~SEV_SNP_SUPPORTED_FLAGS)
    + ret = -EOPNOTSUPP;
    +
    + params.flags = SEV_SNP_SUPPORTED_FLAGS;
    +
    + if (copy_to_user((void __user *)(uintptr_t)argp->data, &params, sizeof(params)))
    + ret = -EFAULT;
    +
    + return ret;
    +}
    +
    static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
    {
    + bool es_active = (argp->id == KVM_SEV_ES_INIT || argp->id == KVM_SEV_SNP_INIT);
    struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
    - bool es_active = argp->id == KVM_SEV_ES_INIT;
    + bool snp_active = argp->id == KVM_SEV_SNP_INIT;
    int asid, ret;

    if (kvm->created_vcpus)
    @@ -249,12 +269,22 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
    return ret;

    sev->es_active = es_active;
    + sev->snp_active = snp_active;
    asid = sev_asid_new(sev);
    if (asid < 0)
    goto e_no_asid;
    sev->asid = asid;

    - ret = sev_platform_init(&argp->error);
    + if (snp_active) {
    + ret = verify_snp_init_flags(kvm, argp);
    + if (ret)
    + goto e_free;
    +
    + ret = sev_snp_init(&argp->error);
    + } else {
    + ret = sev_platform_init(&argp->error);
    + }
    +
    if (ret)
    goto e_free;

    @@ -600,6 +630,10 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
    save->pkru = svm->vcpu.arch.pkru;
    save->xss = svm->vcpu.arch.ia32_xss;

    + /* Enable the SEV-SNP feature */
    + if (sev_snp_guest(svm->vcpu.kvm))
    + save->sev_features |= SVM_SEV_FEAT_SNP_ACTIVE;
    +
    return 0;
    }

    @@ -1532,6 +1566,12 @@ int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
    }

    switch (sev_cmd.id) {
    + case KVM_SEV_SNP_INIT:
    + if (!sev_snp_enabled) {
    + r = -ENOTTY;
    + goto out;
    + }
    + fallthrough;
    case KVM_SEV_ES_INIT:
    if (!sev_es_enabled) {
    r = -ENOTTY;
    diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
    index 01953522097d..57c3c404b0b3 100644
    --- a/arch/x86/kvm/svm/svm.h
    +++ b/arch/x86/kvm/svm/svm.h
    @@ -69,6 +69,9 @@ enum {
    /* TPR and CR2 are always written before VMRUN */
    #define VMCB_ALWAYS_DIRTY_MASK ((1U << VMCB_INTR) | (1U << VMCB_CR2))

    +/* Supported init feature flags */
    +#define SEV_SNP_SUPPORTED_FLAGS 0x0
    +
    struct kvm_sev_info {
    bool active; /* SEV enabled guest */
    bool es_active; /* SEV-ES enabled guest */
    @@ -81,6 +84,7 @@ struct kvm_sev_info {
    u64 ap_jump_table; /* SEV-ES AP Jump Table address */
    struct kvm *enc_context_owner; /* Owner of copied encryption context */
    struct misc_cg *misc_cg; /* For misc cgroup accounting */
    + u64 snp_init_flags;
    };

    struct kvm_svm {
    diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
    index d9e4aabcb31a..944e2bf601fe 100644
    --- a/include/uapi/linux/kvm.h
    +++ b/include/uapi/linux/kvm.h
    @@ -1712,6 +1712,9 @@ enum sev_cmd_id {
    /* Guest Migration Extension */
    KVM_SEV_SEND_CANCEL,

    + /* SNP specific commands */
    + KVM_SEV_SNP_INIT,
    +
    KVM_SEV_NR_MAX,
    };

    @@ -1808,6 +1811,16 @@ struct kvm_sev_receive_update_data {
    __u32 trans_len;
    };

    +/* enable the restricted injection */
    +#define KVM_SEV_SNP_RESTRICTED_INJET (1 << 0)
    +
    +/* enable the restricted injection timer */
    +#define KVM_SEV_SNP_RESTRICTED_TIMER_INJET (1 << 1)
    +
    +struct kvm_snp_init {
    + __u64 flags;
    +};
    +
    #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
    #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
    #define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
    --
    2.17.1
    \
     
     \ /
      Last update: 2021-08-20 18:01    [W:4.074 / U:0.820 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site